Browse files

Fixed issue where an uninitialized plugin would die on a call to its …

…registry method. Also added in version.pm
  • Loading branch information...
1 parent a73670a commit a018f3cdf7918ab0551204503ea6eb03c57bb649 @jayallen jayallen committed Dec 8, 2010
View
215 addons/Melody-compat.pack/extlib/version.pm
@@ -0,0 +1,215 @@
+#!perl -w
+package version;
+
+use 5.005_04;
+use strict;
+
+use vars qw(@ISA $VERSION $CLASS $STRICT $LAX *declare *qv);
+
+$VERSION = 0.85;
+
+$CLASS = 'version';
+
+#--------------------------------------------------------------------------#
+# Version regexp components
+#--------------------------------------------------------------------------#
+
+# Fraction part of a decimal version number. This is a common part of
+# both strict and lax decimal versions
+
+my $FRACTION_PART = qr/\.[0-9]+/;
+
+# First part of either decimal or dotted-decimal strict version number.
+# Unsigned integer with no leading zeroes (except for zero itself) to
+# avoid confusion with octal.
+
+my $STRICT_INTEGER_PART = qr/0|[1-9][0-9]*/;
+
+# First part of either decimal or dotted-decimal lax version number.
+# Unsigned integer, but allowing leading zeros. Always interpreted
+# as decimal. However, some forms of the resulting syntax give odd
+# results if used as ordinary Perl expressions, due to how perl treats
+# octals. E.g.
+# version->new("010" ) == 10
+# version->new( 010 ) == 8
+# version->new( 010.2) == 82 # "8" . "2"
+
+my $LAX_INTEGER_PART = qr/[0-9]+/;
+
+# Second and subsequent part of a strict dotted-decimal version number.
+# Leading zeroes are permitted, and the number is always decimal.
+# Limited to three digits to avoid overflow when converting to decimal
+# form and also avoid problematic style with excessive leading zeroes.
+
+my $STRICT_DOTTED_DECIMAL_PART = qr/\.[0-9]{1,3}/;
+
+# Second and subsequent part of a lax dotted-decimal version number.
+# Leading zeroes are permitted, and the number is always decimal. No
+# limit on the numerical value or number of digits, so there is the
+# possibility of overflow when converting to decimal form.
+
+my $LAX_DOTTED_DECIMAL_PART = qr/\.[0-9]+/;
+
+# Alpha suffix part of lax version number syntax. Acts like a
+# dotted-decimal part.
+
+my $LAX_ALPHA_PART = qr/_[0-9]+/;
+
+#--------------------------------------------------------------------------#
+# Strict version regexp definitions
+#--------------------------------------------------------------------------#
+
+# Strict decimal version number.
+
+my $STRICT_DECIMAL_VERSION =
+ qr/ $STRICT_INTEGER_PART $FRACTION_PART? /x;
+
+# Strict dotted-decimal version number. Must have both leading "v" and
+# at least three parts, to avoid confusion with decimal syntax.
+
+my $STRICT_DOTTED_DECIMAL_VERSION =
+ qr/ v $STRICT_INTEGER_PART $STRICT_DOTTED_DECIMAL_PART{2,} /x;
+
+# Complete strict version number syntax -- should generally be used
+# anchored: qr/ \A $STRICT \z /x
+
+$STRICT =
+ qr/ $STRICT_DECIMAL_VERSION | $STRICT_DOTTED_DECIMAL_VERSION /x;
+
+#--------------------------------------------------------------------------#
+# Lax version regexp definitions
+#--------------------------------------------------------------------------#
+
+# Lax decimal version number. Just like the strict one except for
+# allowing an alpha suffix or allowing a leading or trailing
+# decimal-point
+
+my $LAX_DECIMAL_VERSION =
+ qr/ $LAX_INTEGER_PART (?: \. | $FRACTION_PART $LAX_ALPHA_PART? )?
+ |
+ $FRACTION_PART $LAX_ALPHA_PART?
+ /x;
+
+# Lax dotted-decimal version number. Distinguished by having either
+# leading "v" or at least three non-alpha parts. Alpha part is only
+# permitted if there are at least two non-alpha parts. Strangely
+# enough, without the leading "v", Perl takes .1.2 to mean v0.1.2,
+# so when there is no "v", the leading part is optional
+
+my $LAX_DOTTED_DECIMAL_VERSION =
+ qr/
+ v $LAX_INTEGER_PART (?: $LAX_DOTTED_DECIMAL_PART+ $LAX_ALPHA_PART? )?
+ |
+ $LAX_INTEGER_PART? $LAX_DOTTED_DECIMAL_PART{2,} $LAX_ALPHA_PART?
+ /x;
+
+# Complete lax version number syntax -- should generally be used
+# anchored: qr/ \A $LAX \z /x
+#
+# The string 'undef' is a special case to make for easier handling
+# of return values from ExtUtils::MM->parse_version
+
+$LAX =
+ qr/ undef | $LAX_DECIMAL_VERSION | $LAX_DOTTED_DECIMAL_VERSION /x;
+
+#--------------------------------------------------------------------------#
+
+eval "use version::vxs $VERSION";
+if ( $@ ) { # don't have the XS version installed
+ eval "use version::vpp $VERSION"; # don't tempt fate
+ die "$@" if ( $@ );
+ push @ISA, "version::vpp";
+ local $^W;
+ *version::qv = \&version::vpp::qv;
+ *version::declare = \&version::vpp::declare;
+ *version::_VERSION = \&version::vpp::_VERSION;
+ if ($] >= 5.009000 && $] < 5.011004) {
+ no strict 'refs';
+ *version::stringify = \&version::vpp::stringify;
+ *{'version::(""'} = \&version::vpp::stringify;
+ *version::new = \&version::vpp::new;
+ *version::parse = \&version::vpp::parse;
+ }
+}
+else { # use XS module
+ push @ISA, "version::vxs";
+ local $^W;
+ *version::declare = \&version::vxs::declare;
+ *version::qv = \&version::vxs::qv;
+ *version::_VERSION = \&version::vxs::_VERSION;
+ *version::vcmp = \&version::vxs::VCMP;
+ if ($] >= 5.009000 && $] < 5.011004) {
+ no strict 'refs';
+ *version::stringify = \&version::vxs::stringify;
+ *{'version::(""'} = \&version::vxs::stringify;
+ *version::new = \&version::vxs::new;
+ *version::parse = \&version::vxs::parse;
+ }
+
+}
+
+# Preloaded methods go here.
+sub import {
+ no strict 'refs';
+ my ($class) = shift;
+
+ # Set up any derived class
+ unless ($class eq 'version') {
+ local $^W;
+ *{$class.'::declare'} = \&version::declare;
+ *{$class.'::qv'} = \&version::qv;
+ }
+
+ my %args;
+ if (@_) { # any remaining terms are arguments
+ map { $args{$_} = 1 } @_
+ }
+ else { # no parameters at all on use line
+ %args =
+ (
+ qv => 1,
+ 'UNIVERSAL::VERSION' => 1,
+ );
+ }
+
+ my $callpkg = caller();
+
+ if (exists($args{declare})) {
+ *{$callpkg.'::declare'} =
+ sub {return $class->declare(shift) }
+ unless defined(&{$callpkg.'::declare'});
+ }
+
+ if (exists($args{qv})) {
+ *{$callpkg.'::qv'} =
+ sub {return $class->qv(shift) }
+ unless defined(&{$callpkg.'::qv'});
+ }
+
+ if (exists($args{'UNIVERSAL::VERSION'})) {
+ local $^W;
+ *UNIVERSAL::VERSION
+ = \&version::_VERSION;
+ }
+
+ if (exists($args{'VERSION'})) {
+ *{$callpkg.'::VERSION'} = \&version::_VERSION;
+ }
+
+ if (exists($args{'is_strict'})) {
+ *{$callpkg.'::is_strict'} =
+ sub {return $class->is_strict(shift)}
+ unless defined(&{$callpkg.'::is_strict'});
+ }
+
+ if (exists($args{'is_lax'})) {
+ *{$callpkg.'::is_lax'} =
+ sub {return $class->is_lax(shift)}
+ unless defined(&{$callpkg.'::is_lax'});
+ }
+}
+
+sub is_strict { defined $_[0] && $_[0] =~ qr/ \A $STRICT \z /x }
+sub is_lax { defined $_[0] && $_[0] =~ qr/ \A $LAX \z /x }
+
+1;
View
321 addons/Melody-compat.pack/extlib/version.pod
@@ -0,0 +1,321 @@
+=head1 NAME
+
+version - Perl extension for Version Objects
+
+=head1 SYNOPSIS
+
+ # Parsing version strings (decimal or dotted-decimal)
+
+ use version 0.77; # get latest bug-fixes and API
+ $ver = version->parse($string)
+
+ # Declaring a dotted-decimal $VERSION (keep on one line!)
+
+ use version 0.77; our $VERSION = version->declare("v1.2.3"); # formal
+ use version 0.77; our $VERSION = qv("v1.2.3"); # shorthand
+ use version 0.77; our $VERSION = qv("v1.2_3"); # alpha
+
+ # Declaring an old-style decimal $VERSION (use quotes!)
+
+ our $VERSION = "1.0203"; # recommended
+ use version 0.77; our $VERSION = version->parse("1.0203"); # formal
+ use version 0.77; our $VERSION = version->parse("1.02_03"); # alpha
+
+ # Comparing mixed version styles (decimals, dotted-decimals, objects)
+
+ if ( version->parse($v1) == version->parse($v2) ) {
+ # do stuff
+ }
+
+ # Sorting mixed version styles
+
+ @ordered = sort { version->parse($a) <=> version->parse($b) } @list;
+
+=head1 DESCRIPTION
+
+Version objects were added to Perl in 5.10. This module implements version
+objects for older version of Perl and provides the version object API for all
+versions of Perl. All previous releases before 0.74 are deprecated and should
+not be used due to incompatible API changes. Version 0.77 introduces the new
+'parse' and 'declare' methods to standardize usage. You are strongly urged to
+set 0.77 as a minimum in your code, e.g.
+
+ use version 0.77; # even for Perl v.5.10.0
+
+=head1 TYPES OF VERSION OBJECTS
+
+There are two different types of version objects, corresponding to the two
+different styles of versions in use:
+
+=over 2
+
+=item Decimal Versions
+
+The classic floating-point number $VERSION. The advantage to this style is
+that you don't need to do anything special, just type a number into your
+source file. Quoting is recommended, as it ensures that trailing zeroes
+("1.50") are preserved in any warnings or other output.
+
+=item Dotted Decimal Versions
+
+The more modern form of version assignment, with 3 (or potentially more)
+integers seperated by decimal points (e.g. v1.2.3). This is the form that
+Perl itself has used since 5.6.0 was released. The leading "v" is now
+strongly recommended for clarity, and will throw a warning in a future
+release if omitted.
+
+=back
+
+=head1 DECLARING VERSIONS
+
+If you have a module that uses a decimal $VERSION (floating point), and you
+do not intend to ever change that, this module is not for you. There is
+nothing that version.pm gains you over a simple $VERSION assignment:
+
+ our $VERSION = "1.02";
+
+Since Perl v5.10.0 includes the version.pm comparison logic anyways,
+you don't need to do anything at all.
+
+=head2 How to convert a module from decimal to dotted-decimal
+
+If you have used a decimal $VERSION in the past and wish to switch to a
+dotted-decimal $VERSION, then you need to make a one-time conversion to
+the new format.
+
+B<Important Note>: you must ensure that your new $VERSION is numerically
+greater than your current decimal $VERSION; this is not always obvious. First,
+convert your old decimal version (e.g. 1.02) to a normalized dotted-decimal
+form:
+
+ $ perl -Mversion -e 'print version->parse("1.02")->normal'
+ v1.20.0
+
+Then increment any of the dotted-decimal components (v1.20.1 or v1.21.0).
+
+=head2 How to C<declare()> a dotted-decimal version
+
+ use version 0.77; our $VERSION = version->declare("v1.2.3");
+
+The C<declare()> method always creates dotted-decimal version objects. When
+used in a module, you B<must> put it on the same line as "use version" to
+ensure that $VERSION is read correctly by PAUSE and installer tools. You
+should also add 'version' to the 'configure_requires' section of your
+module metadata file. See instructions in L<ExtUtils::MakeMaker> or
+L<Module::Build> for details.
+
+B<Important Note>: Even if you pass in what looks like a decimal number
+("1.2"), a dotted-decimal will be created ("v1.200.0"). To avoid confusion
+or unintentional errors on older Perls, follow these guidelines:
+
+=over 2
+
+=item *
+
+Always use a dotted-decimal with (at least) three components
+
+=item *
+
+Always use a leading-v
+
+=item *
+
+Always quote the version
+
+=back
+
+If you really insist on using version.pm with an ordinary decimal version,
+use C<parse()> instead of declare. See the L<PARSING AND COMPARING VERSIONS>
+for details.
+
+See also L<version::Internals> for more on version number conversion,
+quoting, calculated version numbers and declaring developer or "alpha" version
+numbers.
+
+=head1 PARSING AND COMPARING VERSIONS
+
+If you need to compare version numbers, but can't be sure whether they are
+expressed as numbers, strings, v-strings or version objects, then you should
+use version.pm to parse them all into objects for comparison.
+
+=head2 How to C<parse()> a version
+
+The C<parse()> method takes in anything that might be a version and returns
+a corresponding version object, doing any necessary conversion along the way.
+
+=over 2
+
+=item *
+
+Dotted-decimal: bare v-strings (v1.2.3) and strings with more than one
+decimal point and a leading 'v' ("v1.2.3"); NOTE you can technically use a
+v-string or strings with a leading-v and only one decimal point (v1.2 or
+"v1.2"), but you will confuse both yourself and others.
+
+=item *
+
+Decimal: regular decimal numbers (literal or in a string)
+
+=back
+
+Some examples:
+
+ $variable version->parse($variable)
+ --------- -------------------------
+ 1.23 v1.230.0
+ "1.23" v1.230.0
+ v1.23 v1.23.0
+ "v1.23" v1.23.0
+ "1.2.3" v1.2.3
+ "v1.2.3" v1.2.3
+
+See L<version::Internals> for more on version number conversion.
+
+=head2 How to check for a legal version string
+
+If you do not want to actually create a full blown version object, but
+would still like to verify that a given string meets the criteria to
+be parsed as a version, there are two helper functions that can be
+employed directly:
+
+=over 4
+
+=item C<is_lax()>
+
+The lax criteria corresponds to what is currently allowed by the
+version parser. All of the following formats are acceptable
+for dotted-decimal formats strings:
+
+ v1.2
+ 1.2345.6
+ v1.23_4
+ 1.2345
+ 1.2345_01
+
+=item C<is_strict()>
+
+If you want to limit youself to a much more narrow definition of what
+a version string constitutes, C<is_strict()> is limited to version
+strings like the following list:
+
+ v1.234.5
+ 2.3456
+
+=back
+
+See L<version::Internals> for details of the regular expressions
+that define the legal version string forms, as well as how to use
+those regular expressions in your own code if C<is_lax()> and
+C<is_strict()> are not sufficient for your needs.
+
+=head2 How to compare version objects
+
+Version objects overload the C<cmp> and C<< E<lt>=E<gt> >> operators. Perl
+automatically generates all of the other comparison operators based on those
+two so all the normal logical comparisons will work.
+
+ if ( version->parse($v1) == version->parse($v2) ) {
+ # do stuff
+ }
+
+If a version object is compared against a non-version object, the non-object
+term will be converted to a version object using C<parse()>. This may give
+surprising results:
+
+ $v1 = version->parse("v0.95.0");
+ $bool = $v1 < 0.96; # FALSE since 0.96 is v0.960.0
+
+Always comparing to a version object will help avoid surprises:
+
+ $bool = $v1 < version->parse("v0.96.0"); # TRUE
+
+Note that "alpha" version objects (where the version string contains
+a trailing underscore segment) compare as less than the equivalent
+version without an underscore:
+
+ $bool = version->parse("1.23_45") < version->parse("1.2345"); # TRUE
+
+See L<version::Internals> for more details on "alpha" versions.
+
+=head1 OBJECT METHODS
+
+=head2 is_alpha()
+
+True if and only if the version object was created with a underscore, e.g.
+
+ version->parse('1.002_03')->is_alpha; # TRUE
+ version->declare('1.2.3_4')->is_alpha; # TRUE
+
+=head2 is_qv()
+
+True only if the version object is a dotted-decimal version, e.g.
+
+ version->parse('v1.2.0')->is_qv; # TRUE
+ version->declare('v1.2')->is_qv; # TRUE
+ qv('1.2')->is_qv; # TRUE
+ version->parse('1.2')->is_qv; # FALSE
+
+=head2 normal()
+
+Returns a string with a standard 'normalized' dotted-decimal form with a
+leading-v and at least 3 components.
+
+ version->declare('v1.2')->normal; # v1.2.0
+ version->parse('1.2')->normal; # v1.200.0
+
+=head2 numify()
+
+Returns a value representing the object in a pure decimal form without
+trailing zeroes.
+
+ version->declare('v1.2')->numify; # 1.002
+ version->parse('1.2')->numify; # 1.2
+
+=head2 stringify()
+
+Returns a string that is as close to the original representation as possible.
+If the original representation was a numeric literal, it will be returned the
+way perl would normally represent it in a string. This method is used whenever
+a version object is interpolated into a string.
+
+ version->declare('v1.2')->stringify; # v1.2
+ version->parse('1.200')->stringify; # 1.200
+ version->parse(1.02_30)->stringify; # 1.023
+
+=head1 EXPORTED FUNCTIONS
+
+=head2 qv()
+
+This function is no longer recommended for use, but is maintained for
+compatibility with existing code. If you do not want to have it exported
+to your namespace, use this form:
+
+ use version 0.77 ();
+
+=head2 is_lax()
+
+(Not exported by default)
+
+This function takes a scalar argument and returns a boolean value indicating
+whether the argument meets the "lax" rules for a version number. Leading and
+trailing spaces are not allowed.
+
+=head2 is_strict()
+
+(Not exported by default)
+
+This function takes a scalar argument and returns a boolean value indicating
+whether the argument meets the "strict" rules for a version number. Leading
+and trailing spaces are not allowed.
+
+=head1 AUTHOR
+
+John Peacock E<lt>jpeacock@cpan.orgE<gt>
+
+=head1 SEE ALSO
+
+L<version::Internals>.
+
+L<perl>.
+
+=cut
View
698 addons/Melody-compat.pack/extlib/version/Internals.pod
@@ -0,0 +1,698 @@
+=head1 NAME
+
+version::Internals - Perl extension for Version Objects
+
+=head1 DESCRIPTION
+
+Overloaded version objects for all modern versions of Perl. This documents
+the internal data representation and underlying code for version.pm. See
+L<version.pod> for daily usage. This document is only useful for users
+interested in the gory details.
+
+=head1 WHAT IS A VERSION?
+
+For the purposes of this module, a version "number" is a sequence of
+positive integer values separated by one or more decimal points and
+optionally a single underscore. This corresponds to what Perl itself
+uses for a version, as well as extending the "version as number" that
+is discussed in the various editions of the Camel book.
+
+There are actually two distinct kinds of version objects:
+
+=over 4
+
+=item Decimal Versions
+
+Any version which "looks like a number", see L<Decimal Versions>. This
+also includes versions with a single decimal point and a single embedded
+underscore, see L<Alpha Versions>, even though these must be quoted
+to preserve the underscore formatting.
+
+=item Dotted-Decimal Versions
+
+Also referred to as "Dotted-Integer", these contains more than one decimal
+point and may have an optional embedded underscore, see L<Dotted-Decimal
+Versions>. This is what is commonly used in most open source software as
+the "external" version (the one used as part of the tag or tarfile name).
+A leading 'v' character is now required and will warn if it missing.
+
+=back
+
+Both of these methods will produce similar version objects, in that
+the default stringification will yield the version L<Normal Form> only
+if required:
+
+ $v = version->new(1.002); # 1.002, but compares like 1.2.0
+ $v = version->new(1.002003); # 1.002003
+ $v2 = version->new("v1.2.3"); # v1.2.3
+
+In specific, version numbers initialized as L<Decimal Versions> will
+stringify as they were originally created (i.e. the same string that was
+passed to C<new()>. Version numbers initialized as L<Dotted-Decimal Versions>
+will be stringified as L<Normal Form>.
+
+=head2 Decimal Versions
+
+These correspond to historical versions of Perl itself prior to 5.6.0,
+as well as all other modules which follow the Camel rules for the
+$VERSION scalar. A Decimal version is initialized with what looks like
+a floating point number. Leading zeros B<are> significant and trailing
+zeros are implied so that a minimum of three places is maintained
+between subversions. What this means is that any subversion (digits
+to the right of the decimal place) that contains less than three digits
+will have trailing zeros added to make up the difference, but only for
+purposes of comparison with other version objects. For example:
+
+ # Prints Equivalent to
+ $v = version->new( 1.2); # 1.2 v1.200.0
+ $v = version->new( 1.02); # 1.02 v1.20.0
+ $v = version->new( 1.002); # 1.002 v1.2.0
+ $v = version->new( 1.0023); # 1.0023 v1.2.300
+ $v = version->new( 1.00203); # 1.00203 v1.2.30
+ $v = version->new( 1.002003); # 1.002003 v1.2.3
+
+All of the preceding examples are true whether or not the input value is
+quoted. The important feature is that the input value contains only a
+single decimal. See also L<Alpha Versions>.
+
+IMPORTANT NOTE: As shown above, if your Decimal version contains more
+than 3 significant digits after the decimal place, it will be split on
+each multiple of 3, so 1.0003 is equivalent to v1.0.300, due to the need
+to remain compatible with Perl's own 5.005_03 == 5.5.30 interpretation.
+Any trailing zeros are ignored for mathematical comparison purposes.
+
+=head2 Dotted-Decimal Versions
+
+These are the newest form of versions, and correspond to Perl's own
+version style beginning with 5.6.0. Starting with Perl 5.10.0,
+and most likely Perl 6, this is likely to be the preferred form. This
+method normally requires that the input parameter be quoted, although
+Perl's after 5.8.1 can use v-strings as a special form of quoting, but
+this is highly discouraged.
+
+Unlike L<Decimal Versions>, Dotted-Decimal Versions have more than
+a single decimal point, e.g.:
+
+ # Prints
+ $v = version->new( "v1.200"); # v1.200.0
+ $v = version->new("v1.20.0"); # v1.20.0
+ $v = qv("v1.2.3"); # v1.2.3
+ $v = qv("1.2.3"); # v1.2.3
+ $v = qv("1.20"); # v1.20.0
+
+In general, Dotted-Decimal Versions permit the greatest amount of freedom
+to specify a version, whereas Decimal Versions enforce a certain
+uniformity.
+
+Just like L<Decimal Versions>, Dotted-Decimal Versions can be used as
+L<Alpha Versions>.
+
+=head2 Alpha Versions
+
+For module authors using CPAN, the convention has been to note unstable
+releases with an underscore in the version string. (See L<CPAN>.) version.pm
+follows this convention and alpha releases will test as being newer than the
+more recent stable release, and less than the next stable release. Only the
+last element may be separated by an underscore:
+
+ # Declaring
+ use version 0.77; our $VERSION = version->declare("v1.2_3");
+
+ # Parsing
+ $v1 = version->parse("v1.2_3");
+ $v1 = version->parse("1.002_003");
+
+Note that you B<must> quote the version when writing an alpha Decimal version.
+The stringified form of Decimal versions will always be the same string that
+was used to initialize the version object.
+
+=head2 Regular Expressions for Version Parsing
+
+A formalized definition of the legal forms for version strings is
+included in the main F<version.pm> file. Primitives are included for
+common elements, although they are scoped to the file so they are useful
+for reference purposes only. There are two publicly accessible scalars
+that can be used in other code (not exported):
+
+=over 4
+
+=item C<$version::LAX>
+
+This regexp covers all of the legal forms allowed under the current
+version string parser. This is not to say that all of these forms
+are recommended, and some of them can only be used when quoted.
+
+For dotted decimals:
+
+ v1.2
+ 1.2345.6
+ v1.23_4
+
+The leading 'v' is optional if two or more decimals appear. If only
+a single decimal is included, then the leading 'v' is required to
+trigger the dotted-decimal parsing. A leading zero is permitted,
+though not recommended except when quoted, because of the risk that
+Perl will treat the number as octal. A trailing underscore plus one
+or more digits denotes an alpha or development release (and must be
+quoted to be parsed properly).
+
+For decimal versions:
+
+ 1
+ 1.2345
+ 1.2345_01
+
+an integer portion, an optional decimal point, and optionally one or
+more digits to the right of the decimal are all required. A trailing
+underscore is permitted and a leading zero is permitted. Just like
+the lax dotted-decimal version, quoting the values is required for
+alpha/development forms to be parsed correctly.
+
+=item C<$version::STRICT>
+
+This regexp covers a much more limited set of formats and constitutes
+the best practices for initializing version objects. Whether you choose
+to employ decimal or dotted-decimal for is a personal preference however.
+
+=over 4
+
+=item v1.234.5
+
+For dotted-decimal versions, a leading 'v' is required, with three or
+more sub-versions of no more than three digits. A leading 0 (zero)
+before the first sub-version (in the above example, '1') is also
+prohibited.
+
+=item 2.3456
+
+For decimal versions, an integer portion (no leading 0), a decimal point,
+and one or more digits to the right of the decimal are all required.
+
+=back
+
+=back
+
+Both of the provided scalars are already compiled as regular expressions
+and do not contain either anchors or implicit groupings, so they can be
+included in your own regular expressions freely. For example, consider
+the following code:
+
+ ($pkg, $ver) =~ /
+ ^[ \t]*
+ use [ \t]+($PKGNAME)
+ (?:[ \t]+($version::STRICT))?
+ [ \t]*;
+ /x;
+
+This would match a line of the form:
+
+ use Foo::Bar::Baz v1.2.3; # legal only in Perl 5.8.1+
+
+where C<$PKGNAME> is another regular expression that defines the legal
+forms for package names.
+
+=head1 IMPLEMENTATION DETAILS
+
+=head2 Equivalence between Decimal and Dotted-Decimal Versions
+
+When Perl 5.6.0 was released, the decision was made to provide a
+transformation between the old-style decimal versions and new-style
+dotted-decimal versions:
+
+ 5.6.0 == 5.006000
+ 5.005_04 == 5.5.40
+
+The floating point number is taken and split first on the single decimal
+place, then each group of three digits to the right of the decimal makes up
+the next digit, and so on until the number of significant digits is exhausted,
+B<plus> enough trailing zeros to reach the next multiple of three.
+
+This was the method that version.pm adopted as well. Some examples may be
+helpful:
+
+ equivalent
+ decimal zero-padded dotted-decimal
+ ------- ----------- --------------
+ 1.2 1.200 v1.200.0
+ 1.02 1.020 v1.20.0
+ 1.002 1.002 v1.2.0
+ 1.0023 1.002300 v1.2.300
+ 1.00203 1.002030 v1.2.30
+ 1.002003 1.002003 v1.2.3
+
+=head2 Quoting Rules
+
+Because of the nature of the Perl parsing and tokenizing routines,
+certain initialization values B<must> be quoted in order to correctly
+parse as the intended version, especially when using the L<declare> or
+L<qv> methods. While you do not have to quote decimal numbers when
+creating version objects, it is always safe to quote B<all> initial values
+when using version.pm methods, as this will ensure that what you type is
+what is used.
+
+Additionally, if you quote your initializer, then the quoted value that goes
+B<in> will be be exactly what comes B<out> when your $VERSION is printed
+(stringified). If you do not quote your value, Perl's normal numeric handling
+comes into play and you may not get back what you were expecting.
+
+If you use a mathematic formula that resolves to a floating point number,
+you are dependent on Perl's conversion routines to yield the version you
+expect. You are pretty safe by dividing by a power of 10, for example,
+but other operations are not likely to be what you intend. For example:
+
+ $VERSION = version->new((qw$Revision: 1.4)[1]/10);
+ print $VERSION; # yields 0.14
+ $V2 = version->new(100/9); # Integer overflow in decimal number
+ print $V2; # yields something like 11.111.111.100
+
+Perl 5.8.1 and beyond are able to automatically quote v-strings but
+that is not possible in earlier versions of Perl. In other words:
+
+ $version = version->new("v2.5.4"); # legal in all versions of Perl
+ $newvers = version->new(v2.5.4); # legal only in Perl >= 5.8.1
+
+=head2 What about v-strings?
+
+There are two ways to enter v-strings: a bare number with two or more
+decimal points, or a bare number with one or more decimal points and a
+leading 'v' character (also bare). For example:
+
+ $vs1 = 1.2.3; # encoded as \1\2\3
+ $vs2 = v1.2; # encoded as \1\2
+
+However, the use of bare v-strings to initialize version objects is
+B<strongly> discouraged in all circumstances. Also, bare
+v-strings are not completely supported in any version of Perl prior to
+5.8.1.
+
+If you insist on using bare v-strings with Perl > 5.6.0, be aware of the
+following limitations:
+
+1) For Perl releases 5.6.0 through 5.8.0, the v-string code merely guesses,
+based on some characteristics of v-strings. You B<must> use a three part
+version, e.g. 1.2.3 or v1.2.3 in order for this heuristic to be successful.
+
+2) For Perl releases 5.8.1 and later, v-strings have changed in the Perl
+core to be magical, which means that the version.pm code can automatically
+determine whether the v-string encoding was used.
+
+3) In all cases, a version created using v-strings will have a stringified
+form that has a leading 'v' character, for the simple reason that sometimes
+it is impossible to tell whether one was present initially.
+
+=head2 Version Object Internals
+
+version.pm provides an overloaded version object that is designed to both
+encapsulate the author's intended $VERSION assignment as well as make it
+completely natural to use those objects as if they were numbers (e.g. for
+comparisons). To do this, a version object contains both the original
+representation as typed by the author, as well as a parsed representation
+to ease comparisons. Version objects employ L<overload> methods to
+simplify code that needs to compare, print, etc the objects.
+
+The internal structure of version objects is a blessed hash with several
+components:
+
+ bless( {
+ 'original' => 'v1.2.3_4',
+ 'alpha' => 1,
+ 'qv' => 1,
+ 'version' => [
+ 1,
+ 2,
+ 3,
+ 4
+ ]
+ }, 'version' );
+
+=over 4
+
+=item original
+
+A faithful representation of the value used to initialize this version
+object. The only time this will not be precisely the same characters
+that exist in the source file is if a short dotted-decimal version like
+v1.2 was used (in which case it will contain 'v1.2'). This form is
+B<STRONGLY> discouraged, in that it will confuse you and your users.
+
+=item qv
+
+A boolean that denotes whether this is a decimal or dotted-decimal version.
+See L<is_qv>.
+
+=item alpha
+
+A boolean that denotes whether this is an alpha version. NOTE: that the
+underscore can can only appear in the last position. See L<is_alpha>.
+
+=item version
+
+An array of non-negative integers that is used for comparison purposes with
+other version objects.
+
+=back
+
+=head2 Replacement UNIVERSAL::VERSION
+
+In addition to the version objects, this modules also replaces the core
+UNIVERSAL::VERSION function with one that uses version objects for its
+comparisons. The return from this operator is always the stringified form
+as a simple scalar (i.e. not an object), but the warning message generated
+includes either the stringified form or the normal form, depending on how
+it was called.
+
+For example:
+
+ package Foo;
+ $VERSION = 1.2;
+
+ package Bar;
+ $VERSION = "v1.3.5"; # works with all Perl's (since it is quoted)
+
+ package main;
+ use version;
+
+ print $Foo::VERSION; # prints 1.2
+
+ print $Bar::VERSION; # prints 1.003005
+
+ eval "use foo 10";
+ print $@; # prints "foo version 10 required..."
+ eval "use foo 1.3.5; # work in Perl 5.6.1 or better
+ print $@; # prints "foo version 1.3.5 required..."
+
+ eval "use bar 1.3.6";
+ print $@; # prints "bar version 1.3.6 required..."
+ eval "use bar 1.004"; # note Decimal version
+ print $@; # prints "bar version 1.004 required..."
+
+
+IMPORTANT NOTE: This may mean that code which searches for a specific
+string (to determine whether a given module is available) may need to be
+changed. It is always better to use the built-in comparison implicit in
+C<use> or C<require>, rather than manually poking at C<< class->VERSION >>
+and then doing a comparison yourself.
+
+The replacement UNIVERSAL::VERSION, when used as a function, like this:
+
+ print $module->VERSION;
+
+will also exclusively return the stringified form. See L<Stringification>
+for more details.
+
+=head1 USAGE DETAILS
+
+=head2 Using modules that use version.pm
+
+As much as possible, the version.pm module remains compatible with all
+current code. However, if your module is using a module that has defined
+C<$VERSION> using the version class, there are a couple of things to be
+aware of. For purposes of discussion, we will assume that we have the
+following module installed:
+
+ package Example;
+ use version; $VERSION = qv('1.2.2');
+ ...module code here...
+ 1;
+
+=over 4
+
+=item Decimal versions always work
+
+Code of the form:
+
+ use Example 1.002003;
+
+will always work correctly. The C<use> will perform an automatic
+C<$VERSION> comparison using the floating point number given as the first
+term after the module name (e.g. above 1.002.003). In this case, the
+installed module is too old for the requested line, so you would see an
+error like:
+
+ Example version 1.002003 (v1.2.3) required--this is only version 1.002002 (v1.2.2)...
+
+=item Dotted-Decimal version work sometimes
+
+With Perl >= 5.6.2, you can also use a line like this:
+
+ use Example 1.2.3;
+
+and it will again work (i.e. give the error message as above), even with
+releases of Perl which do not normally support v-strings (see L<version/What about v-strings> below). This has to do with that fact that C<use> only checks
+to see if the second term I<looks like a number> and passes that to the
+replacement L<UNIVERSAL::VERSION>. This is not true in Perl 5.005_04,
+however, so you are B<strongly encouraged> to always use a Decimal version
+in your code, even for those versions of Perl which support the Dotted-Decimal
+version.
+
+=back
+
+=head2 Object Methods
+
+=over 4
+
+=item new()
+
+Like many OO interfaces, the new() method is used to initialize version
+objects. If two arguments are passed to C<new()>, the B<second> one will be
+used as if it were prefixed with "v". This is to support historical use of the
+C<qw> operator with the CVS variable $Revision, which is automatically
+incremented by CVS every time the file is committed to the repository.
+
+In order to facilitate this feature, the following
+code can be employed:
+
+ $VERSION = version->new(qw$Revision: 2.7 $);
+
+and the version object will be created as if the following code
+were used:
+
+ $VERSION = version->new("v2.7");
+
+In other words, the version will be automatically parsed out of the
+string, and it will be quoted to preserve the meaning CVS normally
+carries for versions. The CVS $Revision$ increments differently from
+Decimal versions (i.e. 1.10 follows 1.9), so it must be handled as if
+it were a Dotted-Decimal Version.
+
+A new version object can be created as a copy of an existing version
+object, either as a class method:
+
+ $v1 = version->new(12.3);
+ $v2 = version->new($v1);
+
+or as an object method:
+
+ $v1 = version->new(12.3);
+ $v2 = $v1->new(12.3);
+
+and in each case, $v1 and $v2 will be identical. NOTE: if you create
+a new object using an existing object like this:
+
+ $v2 = $v1->new();
+
+the new object B<will not> be a clone of the existing object. In the
+example case, $v2 will be an empty object of the same type as $v1.
+
+=back
+
+=over 4
+
+=item qv()
+
+An alternate way to create a new version object is through the exported
+qv() sub. This is not strictly like other q? operators (like qq, qw),
+in that the only delimiters supported are parentheses (or spaces). It is
+the best way to initialize a short version without triggering the floating
+point interpretation. For example:
+
+ $v1 = qv(1.2); # v1.2.0
+ $v2 = qv("1.2"); # also v1.2.0
+
+As you can see, either a bare number or a quoted string can usually
+be used interchangably, except in the case of a trailing zero, which
+must be quoted to be converted properly. For this reason, it is strongly
+recommended that all initializers to qv() be quoted strings instead of
+bare numbers.
+
+To prevent the C<qv()> function from being exported to the caller's namespace,
+either use version with a null parameter:
+
+ use version ();
+
+or just require version, like this:
+
+ require version;
+
+Both methods will prevent the import() method from firing and exporting the
+C<qv()> sub.
+
+=back
+
+For the subsequent examples, the following three objects will be used:
+
+ $ver = version->new("1.2.3.4"); # see "Quoting Rules"
+ $alpha = version->new("1.2.3_4"); # see "Alpha Versions"
+ $nver = version->new(1.002); # see "Decimal Versions"
+
+=over 4
+
+=item Normal Form
+
+For any version object which is initialized with multiple decimal
+places (either quoted or if possible v-string), or initialized using
+the L<qv>() operator, the stringified representation is returned in
+a normalized or reduced form (no extraneous zeros), and with a leading 'v':
+
+ print $ver->normal; # prints as v1.2.3.4
+ print $ver->stringify; # ditto
+ print $ver; # ditto
+ print $nver->normal; # prints as v1.2.0
+ print $nver->stringify; # prints as 1.002, see "Stringification"
+
+In order to preserve the meaning of the processed version, the
+normalized representation will always contain at least three sub terms.
+In other words, the following is guaranteed to always be true:
+
+ my $newver = version->new($ver->stringify);
+ if ($newver eq $ver ) # always true
+ {...}
+
+=back
+
+=over 4
+
+=item Numification
+
+Although all mathematical operations on version objects are forbidden
+by default, it is possible to retrieve a number which corresponds
+to the version object through the use of the $obj->numify
+method. For formatting purposes, when displaying a number which
+corresponds a version object, all sub versions are assumed to have
+three decimal places. So for example:
+
+ print $ver->numify; # prints 1.002003004
+ print $nver->numify; # prints 1.002
+
+Unlike the stringification operator, there is never any need to append
+trailing zeros to preserve the correct version value.
+
+=back
+
+=over 4
+
+=item Stringification
+
+The default stringification for version objects returns exactly the same
+string as was used to create it, whether you used C<new()> or C<qv()>,
+with one exception. The sole exception is if the object was created using
+C<qv()> and the initializer did not have two decimal places or a leading
+'v' (both optional), then the stringified form will have a leading 'v'
+prepended, in order to support round-trip processing.
+
+For example:
+
+ Initialized as Stringifies to
+ ============== ==============
+ version->new("1.2") 1.2
+ version->new("v1.2") v1.2
+ qv("1.2.3") 1.2.3
+ qv("v1.3.5") v1.3.5
+ qv("1.2") v1.2 ### exceptional case
+
+See also L<UNIVERSAL::VERSION>, as this also returns the stringified form
+when used as a class method.
+
+IMPORTANT NOTE: There is one exceptional cases shown in the above table
+where the "initializer" is not stringwise equivalent to the stringified
+representation. If you use the C<qv>() operator on a version without a
+leading 'v' B<and> with only a single decimal place, the stringified output
+will have a leading 'v', to preserve the sense. See the L<qv>() operator
+for more details.
+
+IMPORTANT NOTE 2: Attempting to bypass the normal stringification rules by
+manually applying L<numify>() and L<normal>() will sometimes yield
+surprising results:
+
+ print version->new(version->new("v1.0")->numify)->normal; # v1.0.0
+
+The reason for this is that the L<numify>() operator will turn "v1.0"
+into the equivalent string "1.000000". Forcing the outer version object
+to L<normal>() form will display the mathematically equivalent "v1.0.0".
+
+As the example in L<new>() shows, you can always create a copy of an
+existing version object with the same value by the very compact:
+
+ $v2 = $v1->new($v1);
+
+and be assured that both C<$v1> and C<$v2> will be completely equivalent,
+down to the same internal representation as well as stringification.
+
+=back
+
+=over 4
+
+=item Comparison operators
+
+Both C<cmp> and C<E<lt>=E<gt>> operators perform the same comparison between
+terms (upgrading to a version object automatically). Perl automatically
+generates all of the other comparison operators based on those two.
+In addition to the obvious equalities listed below, appending a single
+trailing 0 term does not change the value of a version for comparison
+purposes. In other words "v1.2" and "1.2.0" will compare as identical.
+
+For example, the following relations hold:
+
+ As Number As String Truth Value
+ ------------- ---------------- -----------
+ $ver > 1.0 $ver gt "1.0" true
+ $ver < 2.5 $ver lt true
+ $ver != 1.3 $ver ne "1.3" true
+ $ver == 1.2 $ver eq "1.2" false
+ $ver == 1.2.3.4 $ver eq "1.2.3.4" see discussion below
+
+It is probably best to chose either the Decimal notation or the string
+notation and stick with it, to reduce confusion. Perl6 version objects
+B<may> only support Decimal comparisons. See also L<Quoting Rules>.
+
+WARNING: Comparing version with unequal numbers of decimal points (whether
+explicitly or implicitly initialized), may yield unexpected results at
+first glance. For example, the following inequalities hold:
+
+ version->new(0.96) > version->new(0.95); # 0.960.0 > 0.950.0
+ version->new("0.96.1") < version->new(0.95); # 0.096.1 < 0.950.0
+
+For this reason, it is best to use either exclusively L<Decimal Versions> or
+L<Dotted-Decimal Versions> with multiple decimal points.
+
+=back
+
+=over 4
+
+=item Logical Operators
+
+If you need to test whether a version object
+has been initialized, you can simply test it directly:
+
+ $vobj = version->new($something);
+ if ( $vobj ) # true only if $something was non-blank
+
+You can also test whether a version object is an alpha version, for
+example to prevent the use of some feature not present in the main
+release:
+
+ $vobj = version->new("1.2_3"); # MUST QUOTE
+ ...later...
+ if ( $vobj->is_alpha ) # True
+
+=back
+
+=head1 AUTHOR
+
+John Peacock E<lt>jpeacock@cpan.orgE<gt>
+
+=head1 SEE ALSO
+
+L<perl>.
+
+=cut
View
931 addons/Melody-compat.pack/extlib/version/vpp.pm
@@ -0,0 +1,931 @@
+package charstar;
+# a little helper class to emulate C char* semantics in Perl
+# so that prescan_version can use the same code as in C
+
+use overload (
+ '""' => \&thischar,
+ '0+' => \&thischar,
+ '++' => \&increment,
+ '--' => \&decrement,
+ '+' => \&plus,
+ '-' => \&minus,
+ '*' => \&multiply,
+ 'cmp' => \&cmp,
+ '<=>' => \&spaceship,
+ 'bool' => \&thischar,
+ '=' => \&clone,
+);
+
+sub new {
+ my ($self, $string) = @_;
+ my $class = ref($self) || $self;
+
+ my $obj = {
+ string => [split(//,$string)],
+ current => 0,
+ };
+ return bless $obj, $class;
+}
+
+sub thischar {
+ my ($self) = @_;
+ my $last = $#{$self->{string}};
+ my $curr = $self->{current};
+ if ($curr >= 0 && $curr <= $last) {
+ return $self->{string}->[$curr];
+ }
+ else {
+ return '';
+ }
+}
+
+sub increment {
+ my ($self) = @_;
+ $self->{current}++;
+}
+
+sub decrement {
+ my ($self) = @_;
+ $self->{current}--;
+}
+
+sub plus {
+ my ($self, $offset) = @_;
+ my $rself = $self->clone;
+ $rself->{current} += $offset;
+ return $rself;
+}
+
+sub minus {
+ my ($self, $offset) = @_;
+ my $rself = $self->clone;
+ $rself->{current} -= $offset;
+ return $rself;
+}
+
+sub multiply {
+ my ($left, $right, $swapped) = @_;
+ my $char = $left->thischar();
+ return $char * $right;
+}
+
+sub spaceship {
+ my ($left, $right, $swapped) = @_;
+ unless (ref($right)) { # not an object already
+ $right = $left->new($right);
+ }
+ return $left->{current} <=> $right->{current};
+}
+
+sub cmp {
+ my ($left, $right, $swapped) = @_;
+ unless (ref($right)) { # not an object already
+ if (length($right) == 1) { # comparing single character only
+ return $left->thischar cmp $right;
+ }
+ $right = $left->new($right);
+ }
+ return $left->currstr cmp $right->currstr;
+}
+
+sub bool {
+ my ($self) = @_;
+ my $char = $self->thischar;
+ return ($char ne '');
+}
+
+sub clone {
+ my ($left, $right, $swapped) = @_;
+ $right = {
+ string => [@{$left->{string}}],
+ current => $left->{current},
+ };
+ return bless $right, ref($left);
+}
+
+sub currstr {
+ my ($self, $s) = @_;
+ my $curr = $self->{current};
+ my $last = $#{$self->{string}};
+ if (defined($s) && $s->{current} < $last) {
+ $last = $s->{current};
+ }
+
+ my $string = join('', @{$self->{string}}[$curr..$last]);
+ return $string;
+}
+
+package version::vpp;
+use strict;
+
+use POSIX qw/locale_h/;
+use locale;
+use vars qw ($VERSION @ISA @REGEXS);
+$VERSION = 0.85;
+
+use overload (
+ '""' => \&stringify,
+ '0+' => \&numify,
+ 'cmp' => \&vcmp,
+ '<=>' => \&vcmp,
+ 'bool' => \&vbool,
+ 'nomethod' => \&vnoop,
+);
+
+eval "use warnings";
+if ($@) {
+ eval '
+ package warnings;
+ sub enabled {return $^W;}
+ 1;
+ ';
+}
+
+my $VERSION_MAX = 0x7FFFFFFF;
+
+# implement prescan_version as closely to the C version as possible
+use constant TRUE => 1;
+use constant FALSE => 0;
+
+sub isDIGIT {
+ my ($char) = shift->thischar();
+ return ($char =~ /\d/);
+}
+
+sub isALPHA {
+ my ($char) = shift->thischar();
+ return ($char =~ /[a-zA-Z]/);
+}
+
+sub isSPACE {
+ my ($char) = shift->thischar();
+ return ($char =~ /\s/);
+}
+
+sub BADVERSION {
+ my ($s, $errstr, $error) = @_;
+ if ($errstr) {
+ $$errstr = $error;
+ }
+ return $s;
+}
+
+sub prescan_version {
+ my ($s, $strict, $errstr, $sqv, $ssaw_decimal, $swidth, $salpha) = @_;
+ my $qv = defined $sqv ? $$sqv : FALSE;
+ my $saw_decimal = defined $ssaw_decimal ? $$ssaw_decimal : 0;
+ my $width = defined $swidth ? $$swidth : 3;
+ my $alpha = defined $salpha ? $$salpha : FALSE;
+
+ my $d = $s;
+
+ if ($qv && isDIGIT($d)) {
+ goto dotted_decimal_version;
+ }
+
+ if ($d eq 'v') { # explicit v-string
+ $d++;
+ if (isDIGIT($d)) {
+ $qv = TRUE;
+ }
+ else { # degenerate v-string
+ # requires v1.2.3
+ return BADVERSION($s,$errstr,"Invalid version format (dotted-decimal versions require at least three parts)");
+ }
+
+dotted_decimal_version:
+ if ($strict && $d eq '0' && isDIGIT($d+1)) {
+ # no leading zeros allowed
+ return BADVERSION($s,$errstr,"Invalid version format (no leading zeros)");
+ }
+
+ while (isDIGIT($d)) { # integer part
+ $d++;
+ }
+
+ if ($d eq '.')
+ {
+ $saw_decimal++;
+ $d++; # decimal point
+ }
+ else
+ {
+ if ($strict) {
+ # require v1.2.3
+ return BADVERSION($s,$errstr,"Invalid version format (dotted-decimal versions require at least three parts)");
+ }
+ else {
+ goto version_prescan_finish;
+ }
+ }
+
+ {
+ my $i = 0;
+ my $j = 0;
+ while (isDIGIT($d)) { # just keep reading
+ $i++;
+ while (isDIGIT($d)) {
+ $d++; $j++;
+ # maximum 3 digits between decimal
+ if ($strict && $j > 3) {
+ return BADVERSION($s,$errstr,"Invalid version format (maximum 3 digits between decimals)");
+ }
+ }
+ if ($d eq '_') {
+ if ($strict) {
+ return BADVERSION($s,$errstr,"Invalid version format (no underscores)");
+ }
+ if ( $alpha ) {
+ return BADVERSION($s,$errstr,"Invalid version format (multiple underscores)");
+ }
+ $d++;
+ $alpha = TRUE;
+ }
+ elsif ($d eq '.') {
+ if ($alpha) {
+ return BADVERSION($s,$errstr,"Invalid version format (underscores before decimal)");
+ }
+ $saw_decimal++;
+ $d++;
+ }
+ elsif (!isDIGIT($d)) {
+ last;
+ }
+ $j = 0;
+ }
+
+ if ($strict && $i < 2) {
+ # requires v1.2.3
+ return BADVERSION($s,$errstr,"Invalid version format (dotted-decimal versions require at least three parts)");
+ }
+ }
+ } # end if dotted-decimal
+ else
+ { # decimal versions
+ # special $strict case for leading '.' or '0'
+ if ($strict) {
+ if ($d eq '.') {
+ return BADVERSION($s,$errstr,"Invalid version format (0 before decimal required)");
+ }
+ if ($d eq '0' && isDIGIT($d+1)) {
+ return BADVERSION($s,$errstr,"Invalid version format (no leading zeros)");
+ }
+ }
+
+ # consume all of the integer part
+ while (isDIGIT($d)) {
+ $d++;
+ }
+
+ # look for a fractional part
+ if ($d eq '.') {
+ # we found it, so consume it
+ $saw_decimal++;
+ $d++;
+ }
+ elsif (!$d || $d eq ';' || isSPACE($d) || $d eq '}') {
+ if ( $d == $s ) {
+ # found nothing
+ return BADVERSION($s,$errstr,"Invalid version format (version required)");
+ }
+ # found just an integer
+ goto version_prescan_finish;
+ }
+ elsif ( $d == $s ) {
+ # didn't find either integer or period
+ return BADVERSION($s,$errstr,"Invalid version format (non-numeric data)");
+ }
+ elsif ($d eq '_') {
+ # underscore can't come after integer part
+ if ($strict) {
+ return BADVERSION($s,$errstr,"Invalid version format (no underscores)");
+ }
+ elsif (isDIGIT($d+1)) {
+ return BADVERSION($s,$errstr,"Invalid version format (alpha without decimal)");
+ }
+ else {
+ return BADVERSION($s,$errstr,"Invalid version format (misplaced underscore)");
+ }
+ }
+ elsif ($d) {
+ # anything else after integer part is just invalid data
+ return BADVERSION($s,$errstr,"Invalid version format (non-numeric data)");
+ }
+
+ # scan the fractional part after the decimal point
+ if ($d && !isDIGIT($d) && ($strict || ! ($d eq ';' || isSPACE($d) || $d eq '}') )) {
+ # $strict or lax-but-not-the-end
+ return BADVERSION($s,$errstr,"Invalid version format (fractional part required)");
+ }
+
+ while (isDIGIT($d)) {
+ $d++;
+ if ($d eq '.' && isDIGIT($d-1)) {
+ if ($alpha) {
+ return BADVERSION($s,$errstr,"Invalid version format (underscores before decimal)");
+ }
+ if ($strict) {
+ return BADVERSION($s,$errstr,"Invalid version format (dotted-decimal versions must begin with 'v')");
+ }
+ $d = $s; # start all over again
+ $qv = TRUE;
+ goto dotted_decimal_version;
+ }
+ if ($d eq '_') {
+ if ($strict) {
+ return BADVERSION($s,$errstr,"Invalid version format (no underscores)");
+ }
+ if ( $alpha ) {
+ return BADVERSION($s,$errstr,"Invalid version format (multiple underscores)");
+ }
+ if ( ! isDIGIT($d+1) ) {
+ return BADVERSION($s,$errstr,"Invalid version format (misplaced underscore)");
+ }
+ $d++;
+ $alpha = TRUE;
+ }
+ }
+ }
+
+version_prescan_finish:
+ while (isSPACE($d)) {
+ $d++;
+ }
+
+ if ($d && !isDIGIT($d) && (! ($d eq ';' || $d eq '}') )) {
+ # trailing non-numeric data
+ return BADVERSION($s,$errstr,"Invalid version format (non-numeric data)");
+ }
+
+ if (defined $sqv) {
+ $$sqv = $qv;
+ }
+ if (defined $swidth) {
+ $$swidth = $width;
+ }
+ if (defined $ssaw_decimal) {
+ $$ssaw_decimal = $saw_decimal;
+ }
+ if (defined $salpha) {
+ $$salpha = $alpha;
+ }
+ return $d;
+}
+
+sub scan_version {
+ my ($s, $rv, $qv) = @_;
+ my $start;
+ my $pos;
+ my $last;
+ my $errstr;
+ my $saw_decimal = 0;
+ my $width = 3;
+ my $alpha = FALSE;
+ my $vinf = FALSE;
+ my @av;
+
+ $s = new charstar $s;
+
+ while (isSPACE($s)) { # leading whitespace is OK
+ $s++;
+ }
+
+ $last = prescan_version($s, FALSE, \$errstr, \$qv, \$saw_decimal,
+ \$width, \$alpha);
+
+ if ($errstr) {
+ # 'undef' is a special case and not an error
+ if ( $s ne 'undef') {
+ use Carp;
+ Carp::croak($errstr);
+ }
+ }
+
+ $start = $s;
+ if ($s eq 'v') {
+ $s++;
+ }
+ $pos = $s;
+
+ if ( $qv ) {
+ $$rv->{qv} = $qv;
+ }
+ if ( $alpha ) {
+ $$rv->{alpha} = $alpha;
+ }
+ if ( !$qv && $width < 3 ) {
+ $$rv->{width} = $width;
+ }
+
+ while (isDIGIT($pos)) {
+ $pos++;
+ }
+ if (!isALPHA($pos)) {
+ my $rev;
+
+ for (;;) {
+ $rev = 0;
+ {
+ # this is atoi() that delimits on underscores
+ my $end = $pos;
+ my $mult = 1;
+ my $orev;
+
+ # the following if() will only be true after the decimal
+ # point of a version originally created with a bare
+ # floating point number, i.e. not quoted in any way
+ #
+ if ( !$qv && $s > $start && $saw_decimal == 1 ) {
+ $mult *= 100;
+ while ( $s < $end ) {
+ $orev = $rev;
+ $rev += $s * $mult;
+ $mult /= 10;
+ if ( (abs($orev) > abs($rev))
+ || (abs($rev) > $VERSION_MAX )) {
+ warn("Integer overflow in version %d",
+ $VERSION_MAX);
+ $s = $end - 1;
+ $rev = $VERSION_MAX;
+ $vinf = 1;
+ }
+ $s++;
+ if ( $s eq '_' ) {
+ $s++;
+ }
+ }
+ }
+ else {
+ while (--$end >= $s) {
+ $orev = $rev;
+ $rev += $end * $mult;
+ $mult *= 10;
+ if ( (abs($orev) > abs($rev))
+ || (abs($rev) > $VERSION_MAX )) {
+ warn("Integer overflow in version");
+ $end = $s - 1;
+ $rev = $VERSION_MAX;
+ $vinf = 1;
+ }
+ }
+ }
+ }
+
+ # Append revision
+ push @av, $rev;
+ if ( $vinf ) {
+ $s = $last;
+ last;
+ }
+ elsif ( $pos eq '.' ) {
+ $s = ++$pos;
+ }
+ elsif ( $pos eq '_' && isDIGIT($pos+1) ) {
+ $s = ++$pos;
+ }
+ elsif ( $pos eq ',' && isDIGIT($pos+1) ) {
+ $s = ++$pos;
+ }
+ elsif ( isDIGIT($pos) ) {
+ $s = $pos;
+ }
+ else {
+ $s = $pos;
+ last;
+ }
+ if ( $qv ) {
+ while ( isDIGIT($pos) ) {
+ $pos++;
+ }
+ }
+ else {
+ my $digits = 0;
+ while ( ( isDIGIT($pos) || $pos eq '_' ) && $digits < 3 ) {
+ if ( $pos ne '_' ) {
+ $digits++;
+ }
+ $pos++;
+ }
+ }
+ }
+ }
+ if ( $qv ) { # quoted versions always get at least three terms
+ my $len = $#av;
+ # This for loop appears to trigger a compiler bug on OS X, as it
+ # loops infinitely. Yes, len is negative. No, it makes no sense.
+ # Compiler in question is:
+ # gcc version 3.3 20030304 (Apple Computer, Inc. build 1640)
+ # for ( len = 2 - len; len > 0; len-- )
+ # av_push(MUTABLE_AV(sv), newSViv(0));
+ #
+ $len = 2 - $len;
+ while ($len-- > 0) {
+ push @av, 0;
+ }
+ }
+
+ # need to save off the current version string for later
+ if ( $vinf ) {
+ $$rv->{original} = "v.Inf";
+ $$rv->{vinf} = 1;
+ }
+ elsif ( $s > $start ) {
+ $$rv->{original} = $start->currstr($s);
+ if ( $qv && $saw_decimal == 1 && $start ne 'v' ) {
+ # need to insert a v to be consistent
+ $$rv->{original} = 'v' . $$rv->{original};
+ }
+ }
+ else {
+ $$rv->{original} = '0';
+ push(@av, 0);
+ }
+
+ # And finally, store the AV in the hash
+ $$rv->{version} = \@av;
+
+ # fix RT#19517 - special case 'undef' as string
+ if ($s eq 'undef') {
+ $s += 5;
+ }
+
+ return $s;
+}
+
+sub new
+{
+ my ($class, $value) = @_;
+ my $self = bless ({}, ref ($class) || $class);
+ my $qv = FALSE;
+
+ if ( ref($value) && eval('$value->isa("version")') ) {
+ # Can copy the elements directly
+ $self->{version} = [ @{$value->{version} } ];
+ $self->{qv} = 1 if $value->{qv};
+ $self->{alpha} = 1 if $value->{alpha};
+ $self->{original} = ''.$value->{original};
+ return $self;
+ }
+
+ my $currlocale = setlocale(LC_ALL);
+
+ # if the current locale uses commas for decimal points, we
+ # just replace commas with decimal places, rather than changing
+ # locales
+ if ( localeconv()->{decimal_point} eq ',' ) {
+ $value =~ tr/,/./;
+ }
+
+ if ( not defined $value or $value =~ /^undef$/ ) {
+ # RT #19517 - special case for undef comparison
+ # or someone forgot to pass a value
+ push @{$self->{version}}, 0;
+ $self->{original} = "0";
+ return ($self);
+ }
+
+ if ( $#_ == 2 ) { # must be CVS-style
+ $value = $_[2];
+ $qv = TRUE;
+ }
+
+ $value = _un_vstring($value);
+
+ # exponential notation
+ if ( $value =~ /\d+.?\d*e[-+]?\d+/ ) {
+ $value = sprintf("%.9f",$value);
+ $value =~ s/(0+)$//; # trim trailing zeros
+ }
+
+ my $s = scan_version($value, \$self, $qv);
+
+ if ($s) { # must be something left over
+ warn("Version string '%s' contains invalid data; "
+ ."ignoring: '%s'", $value, $s);
+ }
+
+ return ($self);
+}
+
+*parse = \&new;
+
+sub numify
+{
+ my ($self) = @_;
+ unless (_verify($self)) {
+ require Carp;
+ Carp::croak("Invalid version object");
+ }
+ my $width = $self->{width} || 3;
+ my $alpha = $self->{alpha} || "";
+ my $len = $#{$self->{version}};
+ my $digit = $self->{version}[0];
+ my $string = sprintf("%d.", $digit );
+
+ for ( my $i = 1 ; $i < $len ; $i++ ) {
+ $digit = $self->{version}[$i];
+ if ( $width < 3 ) {
+ my $denom = 10**(3-$width);
+ my $quot = int($digit/$denom);
+ my $rem = $digit - ($quot * $denom);
+ $string .= sprintf("%0".$width."d_%d", $quot, $rem);
+ }
+ else {
+ $string .= sprintf("%03d", $digit);
+ }
+ }
+
+ if ( $len > 0 ) {
+ $digit = $self->{version}[$len];
+ if ( $alpha && $width == 3 ) {
+ $string .= "_";
+ }
+ $string .= sprintf("%0".$width."d", $digit);
+ }
+ else # $len = 0
+ {
+ $string .= sprintf("000");
+ }
+
+ return $string;
+}
+
+sub normal
+{
+ my ($self) = @_;
+ unless (_verify($self)) {
+ require Carp;
+ Carp::croak("Invalid version object");
+ }
+ my $alpha = $self->{alpha} || "";
+ my $len = $#{$self->{version}};
+ my $digit = $self->{version}[0];
+ my $string = sprintf("v%d", $digit );
+
+ for ( my $i = 1 ; $i < $len ; $i++ ) {
+ $digit = $self->{version}[$i];
+ $string .= sprintf(".%d", $digit);
+ }
+
+ if ( $len > 0 ) {
+ $digit = $self->{version}[$len];
+ if ( $alpha ) {
+ $string .= sprintf("_%0d", $digit);
+ }
+ else {
+ $string .= sprintf(".%0d", $digit);
+ }
+ }
+
+ if ( $len <= 2 ) {
+ for ( $len = 2 - $len; $len != 0; $len-- ) {
+ $string .= sprintf(".%0d", 0);
+ }
+ }
+
+ return $string;
+}
+
+sub stringify
+{
+ my ($self) = @_;
+ unless (_verify($self)) {
+ require Carp;
+ Carp::croak("Invalid version object");
+ }
+ return exists $self->{original}
+ ? $self->{original}
+ : exists $self->{qv}
+ ? $self->normal
+ : $self->numify;
+}
+
+sub vcmp
+{
+ require UNIVERSAL;
+ my ($left,$right,$swap) = @_;
+ my $class = ref($left);
+ unless ( UNIVERSAL::isa($right, $class) ) {
+ $right = $class->new($right);
+ }
+
+ if ( $swap ) {
+ ($left, $right) = ($right, $left);
+ }
+ unless (_verify($left)) {
+ require Carp;
+ Carp::croak("Invalid version object");
+ }
+ unless (_verify($right)) {
+ require Carp;
+ Carp::croak("Invalid version object");
+ }
+ my $l = $#{$left->{version}};
+ my $r = $#{$right->{version}};
+ my $m = $l < $r ? $l : $r;
+ my $lalpha = $left->is_alpha;
+ my $ralpha = $right->is_alpha;
+ my $retval = 0;
+ my $i = 0;
+ while ( $i <= $m && $retval == 0 ) {
+ $retval = $left->{version}[$i] <=> $right->{version}[$i];
+ $i++;
+ }
+
+ # tiebreaker for alpha with identical terms
+ if ( $retval == 0
+ && $l == $r
+ && $left->{version}[$m] == $right->{version}[$m]
+ && ( $lalpha || $ralpha ) ) {
+
+ if ( $lalpha && !$ralpha ) {
+ $retval = -1;
+ }
+ elsif ( $ralpha && !$lalpha) {
+ $retval = +1;
+ }
+ }
+
+ # possible match except for trailing 0's
+ if ( $retval == 0 && $l != $r ) {
+ if ( $l < $r ) {
+ while ( $i <= $r && $retval == 0 ) {
+ if ( $right->{version}[$i] != 0 ) {
+ $retval = -1; # not a match after all
+ }
+ $i++;
+ }
+ }
+ else {
+ while ( $i <= $l && $retval == 0 ) {
+ if ( $left->{version}[$i] != 0 ) {
+ $retval = +1; # not a match after all
+ }
+ $i++;
+ }
+ }
+ }
+
+ return $retval;
+}
+
+sub vbool {
+ my ($self) = @_;
+ return vcmp($self,$self->new("0"),1);
+}
+
+sub vnoop {
+ require Carp;
+ Carp::croak("operation not supported with version object");
+}
+
+sub is_alpha {
+ my ($self) = @_;
+ return (exists $self->{alpha});
+}
+
+sub qv {
+ my $value = shift;
+ my $class = 'version';
+ if (@_) {
+ $class = ref($value) || $value;
+ $value = shift;
+ }
+
+ $value = _un_vstring($value);
+ $value = 'v'.$value unless $value =~ /(^v|\d+\.\d+\.\d)/;
+ my $version = $class->new($value);
+ return $version;
+}
+
+*declare = \&qv;
+
+sub is_qv {
+ my ($self) = @_;
+ return (exists $self->{qv});
+}
+
+
+sub _verify {
+ my ($self) = @_;
+ if ( ref($self)
+ && eval { exists $self->{version} }
+ && ref($self->{version}) eq 'ARRAY'
+ ) {
+ return 1;
+ }
+ else {
+ return 0;
+ }
+}
+
+sub _is_non_alphanumeric {
+ my $s = shift;
+ $s = new charstar $s;
+ while ($s) {
+ return 0 if isSPACE($s); # early out
+ return 1 unless (isALPHA($s) || isDIGIT($s) || $s =~ /[.-]/);
+ $s++;
+ }
+ return 0;
+}
+
+sub _un_vstring {
+ my $value = shift;
+ # may be a v-string
+ if ( length($value) >= 3 && $value !~ /[._]/
+ && _is_non_alphanumeric($value)) {
+ my $tvalue;
+ if ( $] ge 5.008_001 ) {
+ $tvalue = _find_magic_vstring($value);
+ $value = $tvalue if length $tvalue;
+ }
+ elsif ( $] ge 5.006_000 ) {
+ $tvalue = sprintf("v%vd",$value);
+ if ( $tvalue =~ /^v\d+(\.\d+){2,}$/ ) {
+ # must be a v-string
+ $value = $tvalue;
+ }
+ }
+ }
+ return $value;
+}
+
+sub _find_magic_vstring {
+ my $value = shift;
+ my $tvalue = '';
+ require B;
+ my $sv = B::svref_2object(\$value);
+ my $magic = ref($sv) eq 'B::PVMG' ? $sv->MAGIC : undef;
+ while ( $magic ) {
+ if ( $magic->TYPE eq 'V' ) {
+ $tvalue = $magic->PTR;
+ $tvalue =~ s/^v?(.+)$/v$1/;
+ last;
+ }
+ else {
+ $magic = $magic->MOREMAGIC;
+ }
+ }
+ return $tvalue;
+}
+
+sub _VERSION {
+ my ($obj, $req) = @_;
+ my $class = ref($obj) || $obj;
+
+ no strict 'refs';
+ if ( exists $INC{"$class.pm"} and not %{"$class\::"} and $] >= 5.008) {
+ # file but no package
+ require Carp;
+ Carp::croak( "$class defines neither package nor VERSION"
+ ."--version check failed");
+ }
+
+ my $version = eval "\$$class\::VERSION";
+ if ( defined $version ) {
+ local $^W if $] <= 5.008;
+ $version = version::vpp->new($version);
+ }
+
+ if ( defined $req ) {
+ unless ( defined $version ) {
+ require Carp;
+ my $msg = $] < 5.006
+ ? "$class version $req required--this is only version "
+ : "$class does not define \$$class\::VERSION"
+ ."--version check failed";
+
+ if ( $ENV{VERSION_DEBUG} ) {
+ Carp::confess($msg);
+ }
+ else {
+ Carp::croak($msg);
+ }
+ }
+
+ $req = version::vpp->new($req);
+
+ if ( $req > $version ) {
+ require Carp;
+ if ( $req->is_qv ) {
+ Carp::croak(
+ sprintf ("%s version %s required--".
+ "this is only version %s", $class,
+ $req->normal, $version->normal)
+ );
+ }
+ else {
+ Carp::croak(
+ sprintf ("%s version %s required--".
+ "this is only version %s", $class,
+ $req->stringify, $version->stringify)
+ );
+ }
+ }
+ }
+
+ return defined $version ? $version->stringify : undef;
+}
+
+1; #this line is important and will help the module return a true value
View
9 addons/Melody-compat.pack/lib/Melody/Compat.pm
@@ -32,8 +32,13 @@ sub post_init {
return if __PACKAGE__->is_disabled();
foreach my $c ( MT::Component->select(), MT::Plugin->select() ) {
- my $pclass_cfg = $c->registry('plugin_class');
- bless $c, $pclass_cfg if $pclass_cfg;
+ my $plugin_class = eval { $c->registry('plugin_class') }
+ || eval { $c->{registry}{plugin_class} };
+ if ($plugin_class) {
+ eval "require $plugin_class;";
+ die $@ if $@;
+ bless $c, $plugin_class;
+ }
}
}

0 comments on commit a018f3c

Please sign in to comment.