├── .travis.yml ├── t ├── 00_compile.t ├── 04_pack.t ├── 02_sample.t ├── 03_empty_string.t ├── regression │ └── 003_normal_when.t ├── sample │ └── Padre-SVN.pm └── 01_simple.t ├── cpanfile ├── Build.PL ├── .gitignore ├── author └── benchmark.pl ├── script └── perlver-fast ├── META.json ├── Changes ├── README.md ├── lib └── Perl │ └── MinimumVersion │ └── Fast.pm └── LICENSE /.travis.yml: -------------------------------------------------------------------------------- 1 | language: perl 2 | sudo: false 3 | perl: 4 | - 5.14 5 | - 5.16 6 | - 5.28 7 | - 5.30 8 | 9 | -------------------------------------------------------------------------------- /t/00_compile.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use Test::More; 3 | 4 | use_ok $_ for qw( 5 | Perl::MinimumVersion::Fast 6 | ); 7 | 8 | done_testing; 9 | 10 | -------------------------------------------------------------------------------- /cpanfile: -------------------------------------------------------------------------------- 1 | requires 'perl', '5.008001'; 2 | requires 'Compiler::Lexer', 0.23; 3 | configure_requires 'Module::Build::Tiny', '0.035'; 4 | 5 | on 'test' => sub { 6 | requires 'Test::More', '0.98'; 7 | }; 8 | 9 | -------------------------------------------------------------------------------- /t/04_pack.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | use Test::More; 4 | 5 | use Perl::MinimumVersion::Fast; 6 | 7 | my $p = Perl::MinimumVersion::Fast->new(\'my $p = pack "L>", 1'); 8 | is($p->minimum_version, '5.010'); 9 | 10 | done_testing; 11 | -------------------------------------------------------------------------------- /t/02_sample.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | use utf8; 4 | use Test::More; 5 | 6 | use Perl::MinimumVersion::Fast; 7 | 8 | my $p = Perl::MinimumVersion::Fast->new('t/sample/Padre-SVN.pm'); 9 | is($p->minimum_version, '5.008'); 10 | 11 | done_testing; 12 | 13 | -------------------------------------------------------------------------------- /t/03_empty_string.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | use utf8; 4 | use Test::More; 5 | use Perl::MinimumVersion::Fast; 6 | 7 | { 8 | my $warn; 9 | $SIG{__WARN__} = sub { $warn = shift }; 10 | my $p = Perl::MinimumVersion::Fast->new(\''); 11 | is($warn, undef); 12 | }; 13 | 14 | done_testing; 15 | 16 | -------------------------------------------------------------------------------- /Build.PL: -------------------------------------------------------------------------------- 1 | # ========================================================================= 2 | # THIS FILE IS AUTOMATICALLY GENERATED BY MINILLA. 3 | # DO NOT EDIT DIRECTLY. 4 | # ========================================================================= 5 | 6 | use 5.008_001; 7 | use strict; 8 | 9 | use Module::Build::Tiny 0.035; 10 | 11 | Build_PL(); 12 | 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.build/ 2 | /_build/ 3 | /Build 4 | /blib 5 | 6 | /carton.lock 7 | /.carton/ 8 | /local/ 9 | 10 | nytprof.out 11 | nytprof/ 12 | 13 | cover_db/ 14 | 15 | *.bak 16 | *.old 17 | *~ 18 | *.swp 19 | *.o 20 | *.obj 21 | 22 | !LICENSE 23 | 24 | MYMETA.* 25 | 26 | /Perl-MinimumVersion-Fast-* 27 | /.build 28 | /_build_params 29 | !Build/ 30 | !META.json 31 | -------------------------------------------------------------------------------- /t/regression/003_normal_when.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | use utf8; 4 | use Test::More; 5 | use Perl::MinimumVersion::Fast; 6 | use Data::Dumper; 7 | 8 | # normal when should be 5.010 not 5.012 9 | # https://github.com/tokuhirom/Perl-MinimumVersion-Fast/issues/3 10 | 11 | my $src = <<'...'; 12 | use v5.10; 13 | given ($fruit) { 14 | when (/apples?/) { 15 | print "I like apples." 16 | } 17 | when (/oranges?/) { 18 | print "I don't like oranges." 19 | } 20 | default { 21 | print "I don't like anything" 22 | } 23 | } 24 | ... 25 | 26 | my $pmf = Perl::MinimumVersion::Fast->new(\$src); 27 | is($pmf->minimum_version, '5.010') or diag Dumper($pmf->version_markers); 28 | 29 | 30 | done_testing; 31 | 32 | -------------------------------------------------------------------------------- /author/benchmark.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env perl 2 | use strict; 3 | use warnings; 4 | use utf8; 5 | use 5.010000; 6 | use autodie; 7 | 8 | use Perl::MinimumVersion; 9 | use Perl::MinimumVersion::Fast; 10 | use Benchmark qw(cmpthese); 11 | 12 | my $filename = 't/sample/Padre-SVN.pm'; 13 | print "target file: $filename\n"; 14 | 15 | my $c1 = sub { 16 | my $p = Perl::MinimumVersion::Fast->new($filename); 17 | $p->minimum_version(); 18 | }; 19 | 20 | my $c2 = sub { 21 | my $p = Perl::MinimumVersion->new($filename); 22 | $p->minimum_version(); 23 | }; 24 | 25 | print "Testing:\n"; 26 | print $c2->(), "\n"; 27 | print $c1->(), "\n"; 28 | 29 | cmpthese( 30 | -1 => { 31 | 'Perl::MinimumVersion::Fast' => $c1, 32 | 'Perl::MinimumVersion' => $c2, 33 | }, 34 | ); 35 | 36 | -------------------------------------------------------------------------------- /script/perlver-fast: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env perl 2 | use strict; 3 | use warnings; 4 | use Getopt::Long qw(:config bundling passthrough); 5 | use Perl::MinimumVersion::Fast; 6 | 7 | GetOptions( 8 | "e:s" => \my $expr, 9 | "v" => \my $verbose, 10 | ) or die "usage: $0 [file | -e expr]\n"; 11 | 12 | if (@ARGV) { 13 | report($_, $_) for @ARGV; 14 | } 15 | elsif ($expr) { 16 | report("-e", \$expr); 17 | } 18 | else { 19 | my $src = do { local $/; <> }; 20 | report("STDIN", \$src); 21 | } 22 | 23 | sub report { 24 | my($in, $src) = @_; 25 | my $v = Perl::MinimumVersion::Fast->new($src); 26 | printf "%s: %s / %s\n", $in, $v->minimum_version, $v->minimum_syntax_version; 27 | $verbose or return; 28 | my @markers = $v->version_markers; 29 | while (@markers) { 30 | my($pv, $m) = splice @markers, 0, 2; 31 | printf "%-10s %s\n", $pv, $_ for @$m; 32 | } 33 | } 34 | __END__ 35 | 36 | =head1 NAME 37 | 38 | perlver-fast - Minimum perl version detector 39 | 40 | =head1 SYNOPSIS 41 | 42 | reports minimum version and minimum syntax version. Adding C<-c> tries to 43 | add detailed information. 44 | 45 | Analyze from file list 46 | 47 | $ perlver-fast lib/Acme/Kensiro.pm t/00.load.t 48 | lib/Acme/Kensiro.pm: 5.008001 / 5.006 49 | t/00.load.t: 5.006 / 5.006 50 | 51 | Analyze from STDIN 52 | 53 | $ perlver-fast < lib/Acme/Kensiro.pm 54 | STDIN: 5.008001 / 5.006 55 | 56 | Analyze from expression 57 | 58 | $ perlver-fast -e '$a //= 42' 59 | -e: 5.010 / 5.010 60 | 61 | $ perlver-fast -v -e '$a //= 42' 62 | -e: 5.010 / 5.010 63 | 5.010 //= operator 64 | 65 | $ perlver-fast -e 'use 5.24.1; $a //= 42' 66 | -e: 5.24 / 5.010 67 | -------------------------------------------------------------------------------- /META.json: -------------------------------------------------------------------------------- 1 | { 2 | "abstract" : "Find a minimum required version of perl for Perl code", 3 | "author" : [ 4 | "tokuhirom " 5 | ], 6 | "dynamic_config" : 0, 7 | "generated_by" : "Minilla/v3.1.10, CPAN::Meta::Converter version 2.150010", 8 | "license" : [ 9 | "perl_5" 10 | ], 11 | "meta-spec" : { 12 | "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", 13 | "version" : 2 14 | }, 15 | "name" : "Perl-MinimumVersion-Fast", 16 | "no_index" : { 17 | "directory" : [ 18 | "t", 19 | "xt", 20 | "inc", 21 | "share", 22 | "eg", 23 | "examples", 24 | "author", 25 | "builder" 26 | ] 27 | }, 28 | "prereqs" : { 29 | "configure" : { 30 | "requires" : { 31 | "Module::Build::Tiny" : "0.035" 32 | } 33 | }, 34 | "develop" : { 35 | "requires" : { 36 | "Test::CPAN::Meta" : "0", 37 | "Test::MinimumVersion::Fast" : "0.04", 38 | "Test::PAUSE::Permissions" : "0.07", 39 | "Test::Pod" : "1.41", 40 | "Test::Spellunker" : "v0.2.7" 41 | } 42 | }, 43 | "runtime" : { 44 | "requires" : { 45 | "Compiler::Lexer" : "0.23", 46 | "perl" : "5.008005" 47 | } 48 | }, 49 | "test" : { 50 | "requires" : { 51 | "Test::More" : "0.98" 52 | } 53 | } 54 | }, 55 | "release_status" : "unstable", 56 | "resources" : { 57 | "bugtracker" : { 58 | "web" : "https://github.com/tokuhirom/Perl-MinimumVersion-Fast/issues" 59 | }, 60 | "homepage" : "https://github.com/tokuhirom/Perl-MinimumVersion-Fast", 61 | "repository" : { 62 | "type" : "git", 63 | "url" : "git://github.com/tokuhirom/Perl-MinimumVersion-Fast.git", 64 | "web" : "https://github.com/tokuhirom/Perl-MinimumVersion-Fast" 65 | } 66 | }, 67 | "version" : "0.19", 68 | "x_contributors" : [ 69 | "Ahmad M. Zawawi ", 70 | "H.Merijn Brand - Tux ", 71 | "Karen Etheridge ", 72 | "Kenichi Ishigaki ", 73 | "brian d foy " 74 | ], 75 | "x_serialization_backend" : "JSON::PP version 4.02", 76 | "x_static_install" : 1 77 | } 78 | -------------------------------------------------------------------------------- /t/sample/Padre-SVN.pm: -------------------------------------------------------------------------------- 1 | package Padre::SVN; 2 | 3 | # Utility functions needed for basic SVN introspection 4 | 5 | use 5.008; 6 | use strict; 7 | use warnings; 8 | use File::Spec (); 9 | our $VERSION = '0.18'; 10 | 11 | # Find the mime type for a file 12 | sub file_mimetype { 13 | my $hash = file_props(shift); 14 | return $hash->{'svn:mime-type'}; 15 | } 16 | 17 | # Find and parse the properties file 18 | sub file_props { 19 | my $file = shift; 20 | my $base = find_props($file) or return undef; 21 | return parse_props($base); 22 | } 23 | 24 | # Find the props-base for a file 25 | sub find_props { 26 | my $file = shift; 27 | my ( $v, $d, $f ) = File::Spec->splitpath($file); 28 | my $path = File::Spec->catpath( 29 | $v, 30 | File::Spec->catdir( $d, '.svn', 'props' ), 31 | $f . '.svn-work', 32 | ); 33 | return $path if -f $path; 34 | $path = File::Spec->catpath( 35 | $v, 36 | File::Spec->catdir( $d, '.svn', 'prop-base' ), 37 | $f . '.svn-base', 38 | ); 39 | return $path if -f $path; 40 | return undef; 41 | } 42 | 43 | # Parse a property file 44 | sub parse_props { 45 | my $file = shift; 46 | open( my $fh, '<', $file ) or die "Failed to open '$file'"; 47 | 48 | # Simple state parser 49 | my %hash = (); 50 | my $kbytes = 0; 51 | my $vbytes = 0; 52 | my $key = undef; 53 | my $value = undef; 54 | while ( my $line = <$fh> ) { 55 | if ($vbytes) { 56 | my $l = length $line; 57 | if ( $l == $vbytes + 1 ) { 58 | 59 | # Perfect content length 60 | chomp($line); 61 | $hash{$key} = $value . $line; 62 | $vbytes = 0; 63 | $key = undef; 64 | $value = undef; 65 | next; 66 | } 67 | if ( $l > $vbytes ) { 68 | $value .= $line; 69 | $vbytes -= $l; 70 | next; 71 | } 72 | die "Found value longer than specified length"; 73 | } 74 | 75 | if ($kbytes) { 76 | my $l = length $line; 77 | if ( $l == $kbytes + 1 ) { 78 | 79 | # Perfect content length 80 | chomp($line); 81 | $key .= $line; 82 | $kbytes = 0; 83 | next; 84 | } 85 | if ( $l > $kbytes ) { 86 | $key .= $line; 87 | $kbytes -= $l; 88 | next; 89 | } 90 | die "Found key longer than specified length"; 91 | } 92 | 93 | if ( defined $key ) { 94 | $line =~ /^V\s(\d+)/ or die "Failed to find expected V line"; 95 | $vbytes = $1; 96 | $value = ''; 97 | next; 98 | } 99 | 100 | last if $line =~ /^END/; 101 | 102 | # We should have a K line indicating key size 103 | $line =~ /^K\s(\d+)/ or die "Failed to find expected K line"; 104 | $kbytes = $1; 105 | $key = ''; 106 | } 107 | 108 | close $fh; 109 | 110 | return \%hash; 111 | } 112 | 113 | 1; 114 | 115 | # Copyright 2008-2013 The Padre development team as listed in Padre.pm. 116 | # LICENSE 117 | # This program is free software; you can redistribute it and/or 118 | # modify it under the same terms as Perl 5 itself. 119 | -------------------------------------------------------------------------------- /Changes: -------------------------------------------------------------------------------- 1 | Revision history for Perl extension Perl-MinimumVersion-Fast 2 | 3 | {{$NEXT}} 4 | 5 | 0.19 2020-04-15T05:27:20Z 6 | 7 | - Depends on Compiler::Lexer 0.23 8 | 9 | 0.18 2015-07-22T00:33:00Z 10 | 11 | - Support Perl 5.6 12 | (tokuhirom) 13 | 14 | 0.17 2015-02-13T23:41:10Z 15 | 16 | commit 402c83db1371634474b8810687273c57c3949a6f 17 | Author: H.Merijn Brand - Tux 18 | Date: Fri Feb 13 08:54:37 2015 +0100 19 | 20 | Check if pack format requires 5.10 21 | 22 | commit a67a8e19f754e1f29bfc89d8eb48e2a7e2352956 23 | Author: brian d foy 24 | Date: Sat Jan 24 14:09:38 2015 -0500 25 | 26 | Recognize PostDeref 27 | 28 | I just sent a pull request for Compiler::Lexer 29 | which will produce these names. When that module 30 | is updated, I'll grab the version number and 31 | adjust the required version. 32 | 33 | 0.16 2015-01-22T10:31:00Z 34 | 35 | commit 44553ef0c4bdbfb7e85052bdcdaab161c80b2c59 36 | Author: brian d foy 37 | Date: Wed Jan 14 06:29:41 2015 -0500 38 | 39 | I think you meant the processed @tokens, not the one passed in 40 | 41 | commit f5031ab2819aa1a094d0a05d4b972e1cb9b83c1e 42 | Author: brian d foy 43 | Date: Wed Jan 14 04:53:28 2015 -0500 44 | 45 | The next token might be VersionString 46 | 47 | 0.15 2014-10-29T05:57:40Z 48 | - Support push($arrayref, ...) and the likes 49 | (Reported by apocalypse++, with help from moznion++) 50 | 51 | 0.14 2014-03-26T02:59:38Z 52 | 53 | - You can use mro.pm with Perl 5.8! 54 | There is MRO::Compat. 55 | 56 | 0.13 2014-03-25T05:42:43Z 57 | 58 | - Added workaround for `if (//) { }` 59 | 60 | 0.12 2014-03-25T05:39:29Z 61 | 62 | - Detects empty regex as defined-or #7 63 | (Reported by dagolden++) 64 | 65 | 0.11 2013-06-25T08:03:05Z 66 | 67 | - Supoprt Compiler::Lexer 0.13 68 | (tokuhirom) 69 | 70 | 0.10 2013-05-29T08:24:23Z 71 | 72 | - removed debugging stmt. 73 | 74 | 0.09 2013-05-29T05:41:09Z 75 | 76 | - Support /(each|values|keys) (@array|$ref)/. 77 | (suggested by hanekomu++) 78 | 79 | 0.08 2013-05-27T23:13:16Z 80 | 81 | - Detect version from the 'use feature' args. 82 | (tokuhirom) 83 | 84 | 0.07 2013-05-26T10:15:03Z 85 | 86 | - Fixed postfix when detection 87 | https://github.com/tokuhirom/Perl-MinimumVersion-Fast/issues/3 88 | (Reported by bowtie++) 89 | 90 | 0.06 2013-05-23T09:54:19Z 91 | 92 | - Compiler::Lexer 0.06 supports v-string. 93 | 94 | 0.05 2013-05-23T06:55:54Z 95 | 96 | - Support 'package NAME BLOCK' syntax, introduced from 5.14. 97 | (tokuhirom) 98 | 99 | 0.04 2013-05-22T11:07:53Z 100 | 101 | - Suppress warnings 102 | (tokuhirom) 103 | 104 | 0.03 2013-05-22T10:11:34Z 105 | 106 | - Suppress warnings 107 | (tokuhirom) 108 | 109 | 0.02 2013-05-22T09:56:41Z 110 | 111 | - Added minimum_explicit_version, minimum_syntax_version, version_markers. 112 | (tokuhirom) 113 | 114 | 0.01 2013-05-22T05:25:17Z 115 | 116 | - original version 117 | 118 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # NAME 2 | 3 | Perl::MinimumVersion::Fast - Find a minimum required version of perl for Perl code 4 | 5 | # SYNOPSIS 6 | 7 | use Perl::MinimumVersion::Fast; 8 | 9 | my $p = Perl::MinimumVersion::Fast->new($filename); 10 | print $p->minimum_version, "\n"; 11 | 12 | # DESCRIPTION 13 | 14 | "Perl::MinimumVersion::Fast" takes Perl source code and calculates the minimum 15 | version of perl required to be able to run it. Because it is based on goccy's [Compiler::Lexer](https://metacpan.org/pod/Compiler%3A%3ALexer), 16 | it can do this without having to actually load the code. 17 | 18 | Perl::MinimumVersion::Fast is an alternative fast & lightweight implementation of Perl::MinimumVersion. 19 | 20 | This module supports only Perl 5.8.1+. 21 | If you want to support **Perl 5.6**, use [Perl::MinimumVersion](https://metacpan.org/pod/Perl%3A%3AMinimumVersion) instead. 22 | 23 | In 2013, you don't need to support Perl 5.6 in most of case. 24 | 25 | # METHODS 26 | 27 | - `my $p = Perl::MinimumVersion::Fast->new($filename);` 28 | - `my $p = Perl::MinimumVersion::Fast->new(\$src);` 29 | 30 | Create new instance. You can create object from `$filename` and `\$src` in string. 31 | 32 | - `$p->minimum_version();` 33 | 34 | Get a minimum perl version the code required. 35 | 36 | - `$p->minimum_explicit_version()` 37 | 38 | The `minimum_explicit_version` method checks through Perl code for the 39 | use of explicit version dependencies such as. 40 | 41 | use 5.006; 42 | require 5.005_03; 43 | 44 | Although there is almost always only one of these in a file, if more than 45 | one are found, the highest version dependency will be returned. 46 | 47 | Returns a [version](https://metacpan.org/pod/version) object, `undef` if no dependencies could be found. 48 | 49 | - `$p->minimum_syntax_version()` 50 | 51 | The `minimum_syntax_version` method will explicitly test only the 52 | Document's syntax to determine it's minimum version, to the extent 53 | that this is possible. 54 | 55 | Returns a [version](https://metacpan.org/pod/version) object, `undef` if no dependencies could be found. 56 | 57 | - version\_markers 58 | 59 | This method returns a list of pairs in the form: 60 | 61 | ($version, \@markers) 62 | 63 | Each pair represents all the markers that could be found indicating that the 64 | version was the minimum needed version. `@markers` is an array of strings. 65 | Currently, these strings are not as clear as they might be, but this may be 66 | changed in the future. In other words: don't rely on them as specific 67 | identifiers. 68 | 69 | # BENCHMARK 70 | 71 | Perl::MinimumVersion::Fast is faster than Perl::MinimumVersion. 72 | Because Perl::MinimumVersion::Fast uses [Compiler::Lexer](https://metacpan.org/pod/Compiler%3A%3ALexer), that is a Perl5 lexer implemented in C++. 73 | And Perl::MinimumVersion::Fast omits some features implemented in Perl::MinimumVersion. 74 | 75 | But, but, [Perl::MinimumVersion::Fast](https://metacpan.org/pod/Perl%3A%3AMinimumVersion%3A%3AFast) is really fast. 76 | 77 | Rate Perl::MinimumVersion Perl::MinimumVersion::Fast 78 | Perl::MinimumVersion 5.26/s -- -97% 79 | Perl::MinimumVersion::Fast 182/s 3365% -- 80 | 81 | # LICENSE 82 | 83 | Copyright (C) tokuhirom. 84 | 85 | This library is free software; you can redistribute it and/or modify 86 | it under the same terms as Perl itself. 87 | 88 | # THANKS TO 89 | 90 | Most of documents are taken from [Perl::MinimumVersion](https://metacpan.org/pod/Perl%3A%3AMinimumVersion). 91 | 92 | # AUTHOR 93 | 94 | tokuhirom 95 | 96 | # SEE ALSO 97 | 98 | This module using [Compiler::Lexer](https://metacpan.org/pod/Compiler%3A%3ALexer) as a lexer for Perl5 code. 99 | 100 | This module is inspired from [Perl::MinimumVersion](https://metacpan.org/pod/Perl%3A%3AMinimumVersion). 101 | -------------------------------------------------------------------------------- /t/01_simple.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | use utf8; 4 | use Test::More; 5 | 6 | use Perl::MinimumVersion::Fast; 7 | 8 | diag "Compiler::Lexer: $Compiler::Lexer::VERSION"; 9 | 10 | note '--- minimum_version'; 11 | for ( 12 | ['-1', '5.006'], 13 | ['use utf8', '5.008'], 14 | ['each %hash', '5.006'], 15 | ['my %hash; each %hash', '5.006'], 16 | ['each $hashref', '5.014'], 17 | ['my $hashref; each $hashref', '5.014'], 18 | ['each @array', '5.012'], 19 | ['my @array; each @array', '5.012'], 20 | ['keys @array', '5.012'], 21 | ['my @array; keys @array', '5.012'], 22 | ['keys $hashref', '5.014'], 23 | ['my $hashref; keys $hashref', '5.014'], 24 | ['my @array; each @array', '5.012'], 25 | ['values @array', '5.012'], 26 | ['my @array; values @array', '5.012'], 27 | ['values $hashref', '5.014'], 28 | ['my $hashref; values $hashref', '5.014'], 29 | ['push @array', '5.006'], 30 | ['my @array; push @array', '5.006'], 31 | ['push $arrayref', '5.014'], 32 | ['push($arrayref, 1)', '5.014'], 33 | ['push(($arrayref, 1)', '5.014'], 34 | ['my $arrayref; push $arrayref', '5.014'], 35 | ['my $arrayref; push($arrayref', '5.014'], 36 | ['unshift @array', '5.006'], 37 | ['my @array; unshift @array', '5.006'], 38 | ['unshift $arrayref', '5.014'], 39 | ['unshift($arrayref', '5.014'], 40 | ['my $arrayref; unshift $arrayref', '5.014'], 41 | ['my $arrayref; unshift($arrayref', '5.014'], 42 | ['pop @array', '5.006'], 43 | ['my @array; pop @array', '5.006'], 44 | ['pop $arrayref', '5.014'], 45 | ['pop($arrayref', '5.014'], 46 | ['my $arrayref; pop $arrayref', '5.014'], 47 | ['my $arrayref; pop($arrayref', '5.014'], 48 | ['shift @array', '5.006'], 49 | ['my @array; shift @array', '5.006'], 50 | ['shift $arrayref', '5.014'], 51 | ['shift($arrayref', '5.014'], 52 | ['my $arrayref; shift $arrayref', '5.014'], 53 | ['my $arrayref; shift($arrayref', '5.014'], 54 | ['splice @array', '5.006'], 55 | ['my @array; splice @array', '5.006'], 56 | ['splice $arrayref', '5.014'], 57 | ['splice($arrayref', '5.014'], 58 | ['my $arrayref; splice $arrayref', '5.014'], 59 | ['my $arrayref; splice($arrayref', '5.014'], 60 | ['...', '5.012'], 61 | ['package Foo', '5.006'], 62 | ['package Foo;', '5.006'], 63 | ['package Foo 3', '5.012'], 64 | ['package Foo 3.14', '5.012'], 65 | ['package Foo 3.14_01', '5.012'], 66 | ['package Foo v0.0.1', '5.012'], 67 | ['package Foo { }', '5.014'], 68 | ['package Foo 3 { }', '5.014'], 69 | ['package Foo 3.14 { }', '5.014'], 70 | ['package Foo v0.0.1 { }', '5.014'], 71 | ['package Foo; { }', '5.006'], 72 | 73 | # mro.pm is 5.10+ feature. But there is MRO::Compat. 74 | # MRO::Compat do `$INC{'mro.pm'} = 1 `. 75 | # MRO::Compat supports 5.6 76 | ['require mro', '5.006'], 77 | ['use mro', '5.006'], 78 | 79 | ['use feature', '5.010'], 80 | ['use feature;', '5.010'], 81 | ['use feature "unicode_strings"', '5.012'], 82 | ['use feature "unicode_eval"', '5.016'], 83 | ['use feature "current_sub"', '5.016'], 84 | ['use feature "fc"', '5.016'], 85 | ['use feature "experimental::lexical_subs"', '5.018'], 86 | ['use feature ":5.14"', '5.014'], 87 | ['use feature ":5.16"', '5.016'], 88 | ['use feature ":5.18"', '5.018'], 89 | ['require feature', '5.010'], 90 | ['use Data::Dumper', '5.006'], 91 | ['require Data::Dumper', '5.006'], 92 | ['require strict', '5.006'], 93 | ['use strict', '5.006'], 94 | ['use 5', '5.006'], 95 | ['require 5', '5.006'], 96 | ['1 // 2', '5.010'], 97 | ['1 ~~ 2', '5.010'], 98 | ['$x //= 2', '5.010'], 99 | ['%+', '5.010'], 100 | ['$+{"a"}', '5.010'], 101 | ['@+{"a"}', '5.010'], 102 | ['warn %-', '5.010'], 103 | ['$-{"a"}', '5.010'], 104 | ['@-{"a"}', '5.010'], 105 | ['when (1) {}', '5.010'], 106 | ['when ([1,2,3]) {}', '5.010'], 107 | [q{print "$_," when [1,2,3];}, '5.012'], 108 | [q{print "$_," when([1,2,3]);}, '5.012'], 109 | [q{print "$_," when 1}, '5.012'], 110 | [q!warn; when (1) { }!, '5.010'], 111 | [q!use 5.010!, '5.010'], 112 | [q!use 5.010_001!, '5.010_001'], 113 | [q!split // => 3!, '5.006'], 114 | [q!split //, 3!, '5.006'], 115 | [q!split //!, '5.006'], 116 | [q!(split //)!, '5.006'], 117 | [q!{split //}!, '5.006'], 118 | [q!{split(//)}!, '5.006'], 119 | [q!if (//) { }!, '5.006'], 120 | [q!map //, 3!, '5.006'], 121 | [q!grep //, 3!, '5.006'], 122 | [q!time // time!, '5.010'], 123 | ) { 124 | my ($src, $version) = @$_; 125 | my $p = Perl::MinimumVersion::Fast->new(\$src); 126 | is($p->minimum_version, $version, $src) or die; 127 | dump_version_markers($p); 128 | } 129 | 130 | subtest 'minimum_explict_version/minimum_syntax_version' => sub { 131 | for ( 132 | # code explict syntax 133 | [q!use 5.010_001!, '5.010_001', '5.006'], 134 | [q!require 5.010_001!, '5.010_001', '5.006'], 135 | ['...', undef, '5.012'], 136 | ) { 137 | my ($src, $explicit_version, $syntax_version) = @$_; 138 | my $p = Perl::MinimumVersion::Fast->new(\$src); 139 | is($p->minimum_explicit_version, $explicit_version, "$src - explicit"); 140 | is($p->minimum_syntax_version, $syntax_version, "$src - syntax"); 141 | } 142 | }; 143 | 144 | subtest 'version markers' => sub { 145 | { 146 | my $p = Perl::MinimumVersion::Fast->new(\'use 5.010_001'); 147 | is_deeply( 148 | [$p->version_markers], [ 149 | '5.010_001' => [ 150 | 'explicit', 151 | ], 152 | ], 153 | ); 154 | } 155 | 156 | { 157 | my $p = Perl::MinimumVersion::Fast->new(\'...'); 158 | is_deeply( 159 | [$p->version_markers], [ 160 | '5.012' => [ 161 | 'yada-yada-yada operator(...)', 162 | ], 163 | ], 164 | ); 165 | } 166 | }; 167 | 168 | done_testing; 169 | 170 | sub dump_version_markers { 171 | my $p = shift; 172 | my @rv = $p->version_markers; 173 | for (my $i=0; $i<@rv; $i+=2) { 174 | note $rv[$i] . ":\n" . join("\n", map { " - $_" } @{$rv[$i+1]}); 175 | } 176 | } 177 | -------------------------------------------------------------------------------- /lib/Perl/MinimumVersion/Fast.pm: -------------------------------------------------------------------------------- 1 | package Perl::MinimumVersion::Fast; 2 | use 5.008005; 3 | use strict; 4 | use warnings; 5 | 6 | use version (); 7 | 8 | use Compiler::Lexer 0.13; 9 | use List::Util qw(max); 10 | 11 | our $VERSION = "0.19"; 12 | 13 | my $MIN_VERSION = version->new('5.006'); 14 | my $VERSION_5_020 = version->new('5.020'); 15 | my $VERSION_5_018 = version->new('5.018'); 16 | my $VERSION_5_016 = version->new('5.016'); 17 | my $VERSION_5_014 = version->new('5.014'); 18 | my $VERSION_5_012 = version->new('5.012'); 19 | my $VERSION_5_010 = version->new('5.010'); 20 | my $VERSION_5_008 = version->new('5.008'); 21 | 22 | sub new { 23 | my ($class, $stuff) = @_; 24 | 25 | my $filename; 26 | my $src; 27 | if (ref $stuff ne 'SCALAR') { 28 | $filename = $stuff; 29 | open my $fh, '<', $filename 30 | or die "Unknown file: $filename"; 31 | $src = do { local $/; <$fh> }; 32 | } else { 33 | $filename = '-'; 34 | $src = $$stuff; 35 | } 36 | 37 | my $lexer = Compiler::Lexer->new($filename); 38 | my @tokens = $lexer->tokenize($src); 39 | 40 | my $self = bless { }, $class; 41 | $self->{minimum_explicit_version} = $self->_build_minimum_explicit_version(\@tokens); 42 | $self->{minimum_syntax_version} = $self->_build_minimum_syntax_version(\@tokens); 43 | $self; 44 | } 45 | 46 | sub _build_minimum_explicit_version { 47 | my ($self, $tokens) = @_; 48 | my @tokens = map { @$_ } @{$tokens}; 49 | 50 | my $explicit_version; 51 | for my $i (0..@tokens-1) { 52 | if ($tokens[$i]->{name} eq 'UseDecl' || $tokens[$i]->{name} eq 'RequireDecl') { 53 | if (@tokens >= $i+1) { 54 | my $next_token = $tokens[$i+1]; 55 | if ($next_token->{name} eq 'Double' or $next_token->{name} eq 'VersionString') { 56 | $explicit_version = max($explicit_version || 0, version->new($next_token->{data})); 57 | } 58 | } 59 | } 60 | } 61 | return $explicit_version; 62 | } 63 | 64 | sub _build_minimum_syntax_version { 65 | my ($self, $tokens) = @_; 66 | my @tokens = map { @$_ } @{$tokens}; 67 | my $syntax_version = $MIN_VERSION; 68 | 69 | my $test = sub { 70 | my ($reason, $version) = @_; 71 | $syntax_version = max($syntax_version, $version); 72 | push @{$self->{version_markers}->{$version}}, $reason; 73 | }; 74 | 75 | for my $i (0..@tokens-1) { 76 | my $token = $tokens[$i]; 77 | if ($token->{name} eq 'ToDo') { 78 | # ... => 5.12 79 | $test->('yada-yada-yada operator(...)' => $VERSION_5_012); 80 | } elsif ($token->{name} eq 'Package') { 81 | if (@tokens > $i+2 && $tokens[$i+1]->name eq 'Class') { 82 | my $number = $tokens[$i+2]; 83 | if ($number->{name} eq 'Int' || $number->{name} eq 'Double' || $number->{name} eq 'VersionString') { 84 | # package NAME VERSION; => 5.012 85 | $test->('package NAME VERSION' => $VERSION_5_012); 86 | 87 | if (@tokens > $i+3 && $tokens[$i+3]->{name} eq 'LeftBrace') { 88 | $test->('package NAME VERSION BLOCK' => $VERSION_5_014); 89 | } 90 | } elsif ($tokens[$i+2]->{name} eq 'LeftBrace') { 91 | $test->('package NAME BLOCK' => $VERSION_5_014); 92 | } 93 | } 94 | } elsif ($token->{name} eq 'UseDecl' || $token->{name} eq 'RequireDecl') { 95 | if (@tokens >= $i+1) { 96 | # use feature => 5.010 97 | my $next_token = $tokens[$i+1]; 98 | if ($next_token->{data} eq 'feature') { 99 | if (@tokens > $i+2) { 100 | my $next_token = $tokens[$i+2]; 101 | if ($next_token->name eq 'String') { 102 | my $arg = $next_token->data; 103 | my $ver = do { 104 | if ($arg eq 'fc' || $arg eq 'unicode_eval' || $arg eq 'current_sub') { 105 | $VERSION_5_016; 106 | } elsif ($arg eq 'unicode_strings') { 107 | $VERSION_5_012; 108 | } elsif ($arg eq 'experimental::lexical_subs') { 109 | $VERSION_5_018; 110 | } elsif ($arg =~ /\A:5\.(.*)\z/) { 111 | version->new("v5.$1"); 112 | } else { 113 | $VERSION_5_010; 114 | } 115 | }; 116 | $test->('use feature' => $ver); 117 | } else { 118 | $test->('use feature' => $VERSION_5_010); 119 | } 120 | } else { 121 | $test->('use feature' => $VERSION_5_010); 122 | } 123 | } elsif ($next_token->{data} eq 'utf8') { 124 | $test->('utf8 pragma included in 5.6. Broken until 5.8' => $VERSION_5_008); 125 | } 126 | } 127 | } elsif ($token->{name} eq 'DefaultOperator') { 128 | if ($token->{data} eq '//' && $i >= 1) { 129 | my $prev_token = $tokens[$i-1]; 130 | unless ( 131 | ($prev_token->name eq 'BuiltinFunc' && $prev_token->data =~ m{\A(?:split|grep|map)\z}) 132 | || $prev_token->name eq 'LeftParenthesis') { 133 | $test->('// operator' => $VERSION_5_010); 134 | } 135 | } 136 | } elsif ($token->{name} eq 'PolymorphicCompare') { 137 | if ($token->{data} eq '~~') { 138 | $test->('~~ operator' => $VERSION_5_010); 139 | } 140 | } elsif ($token->{name} eq 'DefaultEqual') { 141 | if ($token->{data} eq '//=') { 142 | $test->('//= operator' => $VERSION_5_010); 143 | } 144 | } elsif ($token->{name} eq 'GlobalHashVar') { 145 | if ($token->{data} eq '%-' || $token->{data} eq '%+') { 146 | $test->('%-/%+' => $VERSION_5_010); 147 | } 148 | } elsif ($token->{name} eq 'SpecificValue') { 149 | # $-{"a"} 150 | # $+{"a"} 151 | if ($token->{data} eq '$-' || $token->{data} eq '$+') { 152 | $test->('%-/%+' => $VERSION_5_010); 153 | } 154 | } elsif ($token->{name} eq 'GlobalArrayVar') { 155 | if ($token->{data} eq '@-' || $token->{data} eq '@+') { 156 | $test->('%-/%+' => $VERSION_5_010); 157 | } 158 | } elsif ($token->{name} eq 'WhenStmt') { 159 | if ($i >= 1 && ( 160 | $tokens[$i-1]->{name} ne 'SemiColon' 161 | && $tokens[$i-1]->{name} ne 'RightBrace' 162 | && $tokens[$i-1]->{name} ne 'LeftBrace' 163 | )) { 164 | $test->("postfix when" => $VERSION_5_012); 165 | } else { 166 | $test->("normal when" => $VERSION_5_010); 167 | } 168 | } elsif ($token->{name} eq 'BuiltinFunc') { 169 | if ($token->data eq 'each' || $token->data eq 'keys' || $token->data eq 'values') { 170 | my $func = $token->data; 171 | if (@tokens >= $i+1) { 172 | my $next_token = $tokens[$i+1]; 173 | if ($next_token->name eq 'GlobalVar' || $next_token->name eq 'Var') { 174 | # each $hashref 175 | # each $arrayref 176 | $test->("$func \$hashref, $func \$arrayref" => $VERSION_5_014); 177 | } elsif ($next_token->name eq 'GlobalArrayVar' || $next_token->name eq 'ArrayVar') { 178 | $test->("$func \@array" => $VERSION_5_012); 179 | } 180 | } 181 | } 182 | if ($token->data eq 'push' || $token->data eq 'unshift' || $token->data eq 'pop' || $token->data eq 'shift' || $token->data eq 'splice') { 183 | my $func = $token->data; 184 | if (@tokens >= $i+1) { 185 | my $offset = 1; 186 | my $next_token; 187 | do { 188 | $next_token = $tokens[$i+$offset++]; 189 | } while $next_token->name eq 'LeftParenthesis'; 190 | if ($next_token->name eq 'GlobalVar' || $next_token->name eq 'Var') { 191 | # shift $arrayref 192 | # shift($arrayref, ...) 193 | $test->("$func \$arrayref" => $VERSION_5_014); 194 | } 195 | } 196 | } 197 | if ($token->data eq 'pack' || $token->data eq 'unpack') { 198 | if (@tokens >= $i+1 and my $next_token = $tokens[$i+1]) { 199 | if ($next_token->{name} eq 'String' && $next_token->data =~ m/[<>]/) { 200 | $test->($token->data." uses < or >" => $VERSION_5_010); 201 | } 202 | } 203 | } 204 | } elsif ($token->{name} eq 'PostDeref' || $token->{name} eq 'PostDerefStar') { 205 | $test->("postfix dereference" => $VERSION_5_020); 206 | } 207 | } 208 | return $syntax_version; 209 | } 210 | 211 | sub minimum_version { 212 | my $self = shift; 213 | return $self->{minimum_explicit_version} > $self->{minimum_syntax_version} 214 | ? $self->{minimum_explicit_version} 215 | : $self->{minimum_syntax_version}; 216 | } 217 | 218 | sub minimum_syntax_version { 219 | my $self = shift; 220 | return $self->{minimum_syntax_version}; 221 | } 222 | 223 | sub minimum_explicit_version { 224 | my $self = shift; 225 | return $self->{minimum_explicit_version}; 226 | } 227 | 228 | sub version_markers { 229 | my $self = shift; 230 | 231 | if ( my $explicit = $self->minimum_explicit_version ) { 232 | $self->{version_markers}->{$explicit} = [ 'explicit' ]; 233 | } 234 | 235 | my @rv; 236 | 237 | foreach my $ver ( sort { version->new($a) <=> version->new($b) } keys %{$self->{version_markers}} ) { 238 | push @rv, version->new($ver) => $self->{version_markers}->{$ver}; 239 | } 240 | 241 | return @rv; 242 | } 243 | 244 | 1; 245 | __END__ 246 | 247 | =encoding utf-8 248 | 249 | =head1 NAME 250 | 251 | Perl::MinimumVersion::Fast - Find a minimum required version of perl for Perl code 252 | 253 | =head1 SYNOPSIS 254 | 255 | use Perl::MinimumVersion::Fast; 256 | 257 | my $p = Perl::MinimumVersion::Fast->new($filename); 258 | print $p->minimum_version, "\n"; 259 | 260 | =head1 DESCRIPTION 261 | 262 | "Perl::MinimumVersion::Fast" takes Perl source code and calculates the minimum 263 | version of perl required to be able to run it. Because it is based on goccy's L, 264 | it can do this without having to actually load the code. 265 | 266 | Perl::MinimumVersion::Fast is an alternative fast & lightweight implementation of Perl::MinimumVersion. 267 | 268 | This module supports only Perl 5.8.1+. 269 | If you want to support B, use L instead. 270 | 271 | In 2013, you don't need to support Perl 5.6 in most of case. 272 | 273 | =head1 METHODS 274 | 275 | =over 4 276 | 277 | =item C<< my $p = Perl::MinimumVersion::Fast->new($filename); >> 278 | 279 | =item C<< my $p = Perl::MinimumVersion::Fast->new(\$src); >> 280 | 281 | Create new instance. You can create object from C<< $filename >> and C<< \$src >> in string. 282 | 283 | =item C<< $p->minimum_version(); >> 284 | 285 | Get a minimum perl version the code required. 286 | 287 | =item C<< $p->minimum_explicit_version() >> 288 | 289 | The C method checks through Perl code for the 290 | use of explicit version dependencies such as. 291 | 292 | use 5.006; 293 | require 5.005_03; 294 | 295 | Although there is almost always only one of these in a file, if more than 296 | one are found, the highest version dependency will be returned. 297 | 298 | Returns a L object, C if no dependencies could be found. 299 | 300 | =item C<< $p->minimum_syntax_version() >> 301 | 302 | The C method will explicitly test only the 303 | Document's syntax to determine it's minimum version, to the extent 304 | that this is possible. 305 | 306 | Returns a L object, C if no dependencies could be found. 307 | 308 | =item version_markers 309 | 310 | This method returns a list of pairs in the form: 311 | 312 | ($version, \@markers) 313 | 314 | Each pair represents all the markers that could be found indicating that the 315 | version was the minimum needed version. C<@markers> is an array of strings. 316 | Currently, these strings are not as clear as they might be, but this may be 317 | changed in the future. In other words: don't rely on them as specific 318 | identifiers. 319 | 320 | =back 321 | 322 | =head1 BENCHMARK 323 | 324 | Perl::MinimumVersion::Fast is faster than Perl::MinimumVersion. 325 | Because Perl::MinimumVersion::Fast uses L, that is a Perl5 lexer implemented in C++. 326 | And Perl::MinimumVersion::Fast omits some features implemented in Perl::MinimumVersion. 327 | 328 | But, but, L is really fast. 329 | 330 | Rate Perl::MinimumVersion Perl::MinimumVersion::Fast 331 | Perl::MinimumVersion 5.26/s -- -97% 332 | Perl::MinimumVersion::Fast 182/s 3365% -- 333 | 334 | =head1 LICENSE 335 | 336 | Copyright (C) tokuhirom. 337 | 338 | This library is free software; you can redistribute it and/or modify 339 | it under the same terms as Perl itself. 340 | 341 | =head1 THANKS TO 342 | 343 | Most of documents are taken from L. 344 | 345 | =head1 AUTHOR 346 | 347 | tokuhirom Etokuhirom@gmail.comE 348 | 349 | =head1 SEE ALSO 350 | 351 | This module using L as a lexer for Perl5 code. 352 | 353 | This module is inspired from L. 354 | 355 | =cut 356 | 357 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This software is copyright (c) 2013 by tokuhirom . 2 | 3 | This is free software; you can redistribute it and/or modify it under 4 | the same terms as the Perl 5 programming language system itself. 5 | 6 | Terms of the Perl programming language system itself 7 | 8 | a) the GNU General Public License as published by the Free 9 | Software Foundation; either version 1, or (at your option) any 10 | later version, or 11 | b) the "Artistic License" 12 | 13 | --- The GNU General Public License, Version 1, February 1989 --- 14 | 15 | This software is Copyright (c) 2013 by tokuhirom . 16 | 17 | This is free software, licensed under: 18 | 19 | The GNU General Public License, Version 1, February 1989 20 | 21 | GNU GENERAL PUBLIC LICENSE 22 | Version 1, February 1989 23 | 24 | Copyright (C) 1989 Free Software Foundation, Inc. 25 | 51 Franklin St, Suite 500, Boston, MA 02110-1335 USA 26 | 27 | Everyone is permitted to copy and distribute verbatim copies 28 | of this license document, but changing it is not allowed. 29 | 30 | Preamble 31 | 32 | The license agreements of most software companies try to keep users 33 | at the mercy of those companies. By contrast, our General Public 34 | License is intended to guarantee your freedom to share and change free 35 | software--to make sure the software is free for all its users. The 36 | General Public License applies to the Free Software Foundation's 37 | software and to any other program whose authors commit to using it. 38 | You can use it for your programs, too. 39 | 40 | When we speak of free software, we are referring to freedom, not 41 | price. Specifically, the General Public License is designed to make 42 | sure that you have the freedom to give away or sell copies of free 43 | software, that you receive source code or can get it if you want it, 44 | that you can change the software or use pieces of it in new free 45 | programs; and that you know you can do these things. 46 | 47 | To protect your rights, we need to make restrictions that forbid 48 | anyone to deny you these rights or to ask you to surrender the rights. 49 | These restrictions translate to certain responsibilities for you if you 50 | distribute copies of the software, or if you modify it. 51 | 52 | For example, if you distribute copies of a such a program, whether 53 | gratis or for a fee, you must give the recipients all the rights that 54 | you have. You must make sure that they, too, receive or can get the 55 | source code. And you must tell them their rights. 56 | 57 | We protect your rights with two steps: (1) copyright the software, and 58 | (2) offer you this license which gives you legal permission to copy, 59 | distribute and/or modify the software. 60 | 61 | Also, for each author's protection and ours, we want to make certain 62 | that everyone understands that there is no warranty for this free 63 | software. If the software is modified by someone else and passed on, we 64 | want its recipients to know that what they have is not the original, so 65 | that any problems introduced by others will not reflect on the original 66 | authors' reputations. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | GNU GENERAL PUBLIC LICENSE 72 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 73 | 74 | 0. This License Agreement applies to any program or other work which 75 | contains a notice placed by the copyright holder saying it may be 76 | distributed under the terms of this General Public License. The 77 | "Program", below, refers to any such program or work, and a "work based 78 | on the Program" means either the Program or any work containing the 79 | Program or a portion of it, either verbatim or with modifications. Each 80 | licensee is addressed as "you". 81 | 82 | 1. You may copy and distribute verbatim copies of the Program's source 83 | code as you receive it, in any medium, provided that you conspicuously and 84 | appropriately publish on each copy an appropriate copyright notice and 85 | disclaimer of warranty; keep intact all the notices that refer to this 86 | General Public License and to the absence of any warranty; and give any 87 | other recipients of the Program a copy of this General Public License 88 | along with the Program. You may charge a fee for the physical act of 89 | transferring a copy. 90 | 91 | 2. You may modify your copy or copies of the Program or any portion of 92 | it, and copy and distribute such modifications under the terms of Paragraph 93 | 1 above, provided that you also do the following: 94 | 95 | a) cause the modified files to carry prominent notices stating that 96 | you changed the files and the date of any change; and 97 | 98 | b) cause the whole of any work that you distribute or publish, that 99 | in whole or in part contains the Program or any part thereof, either 100 | with or without modifications, to be licensed at no charge to all 101 | third parties under the terms of this General Public License (except 102 | that you may choose to grant warranty protection to some or all 103 | third parties, at your option). 104 | 105 | c) If the modified program normally reads commands interactively when 106 | run, you must cause it, when started running for such interactive use 107 | in the simplest and most usual way, to print or display an 108 | announcement including an appropriate copyright notice and a notice 109 | that there is no warranty (or else, saying that you provide a 110 | warranty) and that users may redistribute the program under these 111 | conditions, and telling the user how to view a copy of this General 112 | Public License. 113 | 114 | d) You may charge a fee for the physical act of transferring a 115 | copy, and you may at your option offer warranty protection in 116 | exchange for a fee. 117 | 118 | Mere aggregation of another independent work with the Program (or its 119 | derivative) on a volume of a storage or distribution medium does not bring 120 | the other work under the scope of these terms. 121 | 122 | 3. You may copy and distribute the Program (or a portion or derivative of 123 | it, under Paragraph 2) in object code or executable form under the terms of 124 | Paragraphs 1 and 2 above provided that you also do one of the following: 125 | 126 | a) accompany it with the complete corresponding machine-readable 127 | source code, which must be distributed under the terms of 128 | Paragraphs 1 and 2 above; or, 129 | 130 | b) accompany it with a written offer, valid for at least three 131 | years, to give any third party free (except for a nominal charge 132 | for the cost of distribution) a complete machine-readable copy of the 133 | corresponding source code, to be distributed under the terms of 134 | Paragraphs 1 and 2 above; or, 135 | 136 | c) accompany it with the information you received as to where the 137 | corresponding source code may be obtained. (This alternative is 138 | allowed only for noncommercial distribution and only if you 139 | received the program in object code or executable form alone.) 140 | 141 | Source code for a work means the preferred form of the work for making 142 | modifications to it. For an executable file, complete source code means 143 | all the source code for all modules it contains; but, as a special 144 | exception, it need not include source code for modules which are standard 145 | libraries that accompany the operating system on which the executable 146 | file runs, or for standard header files or definitions files that 147 | accompany that operating system. 148 | 149 | 4. You may not copy, modify, sublicense, distribute or transfer the 150 | Program except as expressly provided under this General Public License. 151 | Any attempt otherwise to copy, modify, sublicense, distribute or transfer 152 | the Program is void, and will automatically terminate your rights to use 153 | the Program under this License. However, parties who have received 154 | copies, or rights to use copies, from you under this General Public 155 | License will not have their licenses terminated so long as such parties 156 | remain in full compliance. 157 | 158 | 5. By copying, distributing or modifying the Program (or any work based 159 | on the Program) you indicate your acceptance of this license to do so, 160 | and all its terms and conditions. 161 | 162 | 6. Each time you redistribute the Program (or any work based on the 163 | Program), the recipient automatically receives a license from the original 164 | licensor to copy, distribute or modify the Program subject to these 165 | terms and conditions. You may not impose any further restrictions on the 166 | recipients' exercise of the rights granted herein. 167 | 168 | 7. The Free Software Foundation may publish revised and/or new versions 169 | of the General Public License from time to time. Such new versions will 170 | be similar in spirit to the present version, but may differ in detail to 171 | address new problems or concerns. 172 | 173 | Each version is given a distinguishing version number. If the Program 174 | specifies a version number of the license which applies to it and "any 175 | later version", you have the option of following the terms and conditions 176 | either of that version or of any later version published by the Free 177 | Software Foundation. If the Program does not specify a version number of 178 | the license, you may choose any version ever published by the Free Software 179 | Foundation. 180 | 181 | 8. If you wish to incorporate parts of the Program into other free 182 | programs whose distribution conditions are different, write to the author 183 | to ask for permission. For software which is copyrighted by the Free 184 | Software Foundation, write to the Free Software Foundation; we sometimes 185 | make exceptions for this. Our decision will be guided by the two goals 186 | of preserving the free status of all derivatives of our free software and 187 | of promoting the sharing and reuse of software generally. 188 | 189 | NO WARRANTY 190 | 191 | 9. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 192 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 193 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 194 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 195 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 196 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 197 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 198 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 199 | REPAIR OR CORRECTION. 200 | 201 | 10. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 202 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 203 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 204 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 205 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 206 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 207 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 208 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 209 | POSSIBILITY OF SUCH DAMAGES. 210 | 211 | END OF TERMS AND CONDITIONS 212 | 213 | Appendix: How to Apply These Terms to Your New Programs 214 | 215 | If you develop a new program, and you want it to be of the greatest 216 | possible use to humanity, the best way to achieve this is to make it 217 | free software which everyone can redistribute and change under these 218 | terms. 219 | 220 | To do so, attach the following notices to the program. It is safest to 221 | attach them to the start of each source file to most effectively convey 222 | the exclusion of warranty; and each file should have at least the 223 | "copyright" line and a pointer to where the full notice is found. 224 | 225 | 226 | Copyright (C) 19yy 227 | 228 | This program is free software; you can redistribute it and/or modify 229 | it under the terms of the GNU General Public License as published by 230 | the Free Software Foundation; either version 1, or (at your option) 231 | any later version. 232 | 233 | This program is distributed in the hope that it will be useful, 234 | but WITHOUT ANY WARRANTY; without even the implied warranty of 235 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 236 | GNU General Public License for more details. 237 | 238 | You should have received a copy of the GNU General Public License 239 | along with this program; if not, write to the Free Software 240 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA 241 | 242 | 243 | Also add information on how to contact you by electronic and paper mail. 244 | 245 | If the program is interactive, make it output a short notice like this 246 | when it starts in an interactive mode: 247 | 248 | Gnomovision version 69, Copyright (C) 19xx name of author 249 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 250 | This is free software, and you are welcome to redistribute it 251 | under certain conditions; type `show c' for details. 252 | 253 | The hypothetical commands `show w' and `show c' should show the 254 | appropriate parts of the General Public License. Of course, the 255 | commands you use may be called something other than `show w' and `show 256 | c'; they could even be mouse-clicks or menu items--whatever suits your 257 | program. 258 | 259 | You should also get your employer (if you work as a programmer) or your 260 | school, if any, to sign a "copyright disclaimer" for the program, if 261 | necessary. Here a sample; alter the names: 262 | 263 | Yoyodyne, Inc., hereby disclaims all copyright interest in the 264 | program `Gnomovision' (a program to direct compilers to make passes 265 | at assemblers) written by James Hacker. 266 | 267 | , 1 April 1989 268 | Ty Coon, President of Vice 269 | 270 | That's all there is to it! 271 | 272 | 273 | --- The Artistic License 1.0 --- 274 | 275 | This software is Copyright (c) 2013 by tokuhirom . 276 | 277 | This is free software, licensed under: 278 | 279 | The Artistic License 1.0 280 | 281 | The Artistic License 282 | 283 | Preamble 284 | 285 | The intent of this document is to state the conditions under which a Package 286 | may be copied, such that the Copyright Holder maintains some semblance of 287 | artistic control over the development of the package, while giving the users of 288 | the package the right to use and distribute the Package in a more-or-less 289 | customary fashion, plus the right to make reasonable modifications. 290 | 291 | Definitions: 292 | 293 | - "Package" refers to the collection of files distributed by the Copyright 294 | Holder, and derivatives of that collection of files created through 295 | textual modification. 296 | - "Standard Version" refers to such a Package if it has not been modified, 297 | or has been modified in accordance with the wishes of the Copyright 298 | Holder. 299 | - "Copyright Holder" is whoever is named in the copyright or copyrights for 300 | the package. 301 | - "You" is you, if you're thinking about copying or distributing this Package. 302 | - "Reasonable copying fee" is whatever you can justify on the basis of media 303 | cost, duplication charges, time of people involved, and so on. (You will 304 | not be required to justify it to the Copyright Holder, but only to the 305 | computing community at large as a market that must bear the fee.) 306 | - "Freely Available" means that no fee is charged for the item itself, though 307 | there may be fees involved in handling the item. It also means that 308 | recipients of the item may redistribute it under the same conditions they 309 | received it. 310 | 311 | 1. You may make and give away verbatim copies of the source form of the 312 | Standard Version of this Package without restriction, provided that you 313 | duplicate all of the original copyright notices and associated disclaimers. 314 | 315 | 2. You may apply bug fixes, portability fixes and other modifications derived 316 | from the Public Domain or from the Copyright Holder. A Package modified in such 317 | a way shall still be considered the Standard Version. 318 | 319 | 3. You may otherwise modify your copy of this Package in any way, provided that 320 | you insert a prominent notice in each changed file stating how and when you 321 | changed that file, and provided that you do at least ONE of the following: 322 | 323 | a) place your modifications in the Public Domain or otherwise make them 324 | Freely Available, such as by posting said modifications to Usenet or an 325 | equivalent medium, or placing the modifications on a major archive site 326 | such as ftp.uu.net, or by allowing the Copyright Holder to include your 327 | modifications in the Standard Version of the Package. 328 | 329 | b) use the modified Package only within your corporation or organization. 330 | 331 | c) rename any non-standard executables so the names do not conflict with 332 | standard executables, which must also be provided, and provide a separate 333 | manual page for each non-standard executable that clearly documents how it 334 | differs from the Standard Version. 335 | 336 | d) make other distribution arrangements with the Copyright Holder. 337 | 338 | 4. You may distribute the programs of this Package in object code or executable 339 | form, provided that you do at least ONE of the following: 340 | 341 | a) distribute a Standard Version of the executables and library files, 342 | together with instructions (in the manual page or equivalent) on where to 343 | get the Standard Version. 344 | 345 | b) accompany the distribution with the machine-readable source of the Package 346 | with your modifications. 347 | 348 | c) accompany any non-standard executables with their corresponding Standard 349 | Version executables, giving the non-standard executables non-standard 350 | names, and clearly documenting the differences in manual pages (or 351 | equivalent), together with instructions on where to get the Standard 352 | Version. 353 | 354 | d) make other distribution arrangements with the Copyright Holder. 355 | 356 | 5. You may charge a reasonable copying fee for any distribution of this 357 | Package. You may charge any fee you choose for support of this Package. You 358 | may not charge a fee for this Package itself. However, you may distribute this 359 | Package in aggregate with other (possibly commercial) programs as part of a 360 | larger (possibly commercial) software distribution provided that you do not 361 | advertise this Package as a product of your own. 362 | 363 | 6. The scripts and library files supplied as input to or produced as output 364 | from the programs of this Package do not automatically fall under the copyright 365 | of this Package, but belong to whomever generated them, and may be sold 366 | commercially, and may be aggregated with this Package. 367 | 368 | 7. C or perl subroutines supplied by you and linked into this Package shall not 369 | be considered part of this Package. 370 | 371 | 8. The name of the Copyright Holder may not be used to endorse or promote 372 | products derived from this software without specific prior written permission. 373 | 374 | 9. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED 375 | WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 376 | MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 377 | 378 | The End 379 | --------------------------------------------------------------------------------