home *** CD-ROM | disk | FTP | other *** search
/ PC Professionell 2004 December / PCpro_2004_12.ISO / files / webserver / tsw / TSW_3.4.0.exe / Apache2 / perl / par.pl < prev    next >
Encoding:
Perl Script  |  2003-09-03  |  18.6 KB  |  676 lines

  1. #!/usr/bin/perl
  2. # $File: //member/autrijus/PAR/script/par.pl $ $Author: joker $
  3. # $Revision: 1.1.1.1 $ $Change: 6169 $ $DateTime: 2003/05/29 18:53:54 $ vim: expandtab shiftwidth=4
  4.  
  5. package __par_pl;
  6.  
  7. # --- This script must not use any modules at compile time ---
  8. #use strict;
  9.  
  10. =head1 NAME
  11.  
  12. par.pl - Make and run Perl Archives
  13.  
  14. =head1 SYNOPSIS
  15.  
  16. (Please see L<pp> for convenient ways to make self-contained
  17. executables, scripts or PAR archives from perl programs.)
  18.  
  19. To use F<Hello.pm> from F<./foo.par>:
  20.  
  21.     % par.pl -A./foo.par -MHello 
  22.     % par.pl -A./foo -MHello    # the .par part is optional
  23.  
  24. Same thing, but search F<foo.par> in the F<@INC>;
  25.  
  26.     % par.pl -Ifoo.par -MHello 
  27.     % par.pl -Ifoo -MHello      # ditto
  28.  
  29. Run F<test.pl> or F<script/test.pl> from F<foo.par>:
  30.  
  31.     % par.pl foo.par test.pl    # looks for 'main.pl' by default,
  32.                                 # otherwise run 'test.pl' 
  33.  
  34. To make a self-containing script containing a PAR file :
  35.  
  36.     % par.pl -O./foo.pl foo.par
  37.     % ./foo.pl test.pl          # same as above
  38.  
  39. To embed the necessary non-core modules and shared objects for PAR's
  40. execution (like C<Zlib>, C<IO>, C<Cwd>, etc), use the B<-b> flag:
  41.  
  42.     % par.pl -b -O./foo.pl foo.par
  43.     % ./foo.pl test.pl          # runs anywhere with core modules installed
  44.  
  45. If you also wish to embed I<core> modules along, use the B<-B> flag
  46. instead:
  47.  
  48.     % par.pl -B -O./foo.pl foo.par
  49.     % ./foo.pl test.pl          # runs anywhere with the perl interpreter
  50.  
  51. This is particularly useful when making stand-alone binary
  52. executables; see L<pp> for details.
  53.  
  54. =head1 DESCRIPTION
  55.  
  56. This stand-alone command offers roughly the same feature as C<perl
  57. -MPAR>, except that it takes the pre-loaded F<.par> files via
  58. C<-Afoo.par> instead of C<-MPAR=foo.par>.
  59.  
  60. =head2 Binary PAR loader (L<parl>)
  61.  
  62. If you have a C compiler, or a pre-built binary package of B<PAR> is
  63. available for your platform, a binary version of B<par.pl> will also be
  64. automatically installed as B<parl>.  You can use it to run F<.par> files:
  65.  
  66.     # runs script/run.pl in archive, uses its lib/* as libraries
  67.     % parl myapp.par run.pl     # runs run.pl or script/run.pl in myapp.par
  68.     % parl otherapp.pl          # also runs normal perl scripts
  69.  
  70. However, if the F<.par> archive contains either F<main.pl> or
  71. F<script/main.pl>, it is used instead:
  72.  
  73.     % parl myapp.par run.pl     # runs main.pl, with 'run.pl' as @ARGV
  74.  
  75. Finally, the C<-O> option makes a stand-alone binary executable from a
  76. PAR file:
  77.  
  78.     % parl -B -Omyapp myapp.par
  79.     % ./myapp                   # run it anywhere without perl binaries
  80.  
  81. With the C<--par-options> flag, generated binaries can act as C<parl>
  82. to pack new binaries: 
  83.  
  84.     % ./myapp --par-options -Omyap2 myapp.par   # identical to ./myapp
  85.     % ./myapp --par-options -Omyap3 myap3.par   # now with different PAR
  86.  
  87. =head2 Stand-alone executable format
  88.  
  89. The format for the stand-alone executable is simply concatenating the
  90. following elements:
  91.  
  92. =over 4
  93.  
  94. =item * The executable itself
  95.  
  96. Either in plain-text (F<par.pl>) or native executable format (F<parl>
  97. or F<parl.exe>).
  98.  
  99. =item * Any number of embedded files
  100.  
  101. These are typically used for bootstrapping PAR's various XS dependencies.
  102. Each section contains:
  103.  
  104. =over 4
  105.  
  106. =item The magic string "C<FILE>"
  107.  
  108. =item Length of file name in C<pack('N')> format plus 9
  109.  
  110. =item 8 bytes of hex-encoded CRC32 of file content
  111.  
  112. =item A single slash ("C</>")
  113.  
  114. =item The file name (without path)
  115.  
  116. =item File length in C<pack('N')> format
  117.  
  118. =item The file's content (not compressed)
  119.  
  120. =back
  121.  
  122. =item * One PAR file
  123.  
  124. This is just a zip file beginning with the magic string "C<PK\003\004>".
  125.  
  126. =item * Ending section
  127.  
  128. A pack('N') number of the total length of FILE and PAR sections,
  129. followed by a 8-bytes magic string: "C<\012PAR.pm\012>".
  130.  
  131. =back
  132.  
  133. =cut
  134.  
  135. $ENV{PAR_CLEARTEMP} = 1 unless exists $ENV{PAR_CLEARTEMP};
  136. my $quiet = !$ENV{PAR_DEBUG};
  137.  
  138. # fix $0 if invoked from PATH
  139. my %Config = (
  140.     path_sep    => ($^O =~ /^MSWin/ ? ';' : ':'),
  141.     _exe        => ($^O =~ /^(?:MSWin|OS2|cygwin)/ ? '.exe' : ''),
  142.     _delim      => ($^O =~ /^MSWin|OS2/ ? '\\' : '/'),
  143. );
  144.  
  145. if (-s "$0$Config{_exe}") {
  146.     $0 = "$0$Config{_exe}";
  147. }
  148. elsif (!-s $0) {
  149.     foreach my $dir (split /\Q$Config{path_sep}\E/, $ENV{PATH}) {
  150.         $dir =~ s/\Q$Config{_delim}\E$//;
  151.         (($0 = "$dir$Config{_delim}$0$Config{_exe}"), last)
  152.             if -s "$dir$Config{_delim}$0$Config{_exe}";
  153.         (($0 = "$dir$Config{_delim}$0"), last)
  154.             if -s "$dir$Config{_delim}$0";
  155.     }
  156. }
  157.  
  158. # Magic string checking and extracting bundled modules {{{
  159. my ($start_pos, $data_pos);
  160. {
  161.     # Check file type, get start of data section {{{
  162.     open _FH, $0 or last;
  163.     binmode(_FH);
  164.  
  165.     my $buf;
  166.     seek _FH, -8, 2;
  167.     read _FH, $buf, 8;
  168.     last unless $buf eq "\nPAR.pm\n";
  169.  
  170.     seek _FH, -12, 2;
  171.     read _FH, $buf, 4;
  172.     seek _FH, -12 - unpack("N", $buf), 2;
  173.     read _FH, $buf, 4;
  174.  
  175.     $data_pos = (tell _FH) - 4;
  176.     # }}}
  177.  
  178.     # Extracting each file into memory {{{
  179.     my %require_list;
  180.     while ($buf eq "FILE") {
  181.         read _FH, $buf, 4;
  182.         read _FH, $buf, unpack("N", $buf);
  183.  
  184.         my $fullname = $buf;
  185.         outs(qq(Unpacking file "$fullname"...));
  186.         my $crc = ( $fullname =~ s|^([a-f\d]{8})/|| ) ? $1 : undef;
  187.         my ($basename, $ext) = ($buf =~ m|(?:.*/)?(.*)(\..*)|);
  188.  
  189.         read _FH, $buf, 4;
  190.         read _FH, $buf, unpack("N", $buf);
  191.  
  192.         if (defined($ext) and $ext !~ /\.(?:pm|ix|al)$/i) {
  193.             my ($out, $filename) = _tempfile($ext, $crc);
  194.             if ($out) {
  195.                 binmode($out);
  196.                 print $out $buf;
  197.                 close $out;
  198.                 chmod 0755, $filename;
  199.             }
  200.             $PAR::Heavy::DLCache{$filename}++;
  201.             $PAR::Heavy::DLCache{$basename}   =
  202.             $PAR::Heavy::FullCache{$fullname} = $filename;
  203.             $PAR::Heavy::FullCache{$filename} = $fullname;
  204.         }
  205.         elsif ( $fullname =~ m|^/?shlib/| and defined $ENV{PAR_TEMP} ) {
  206.             # should be moved to _tempfile()
  207.             $filename = "$ENV{PAR_TEMP}/$basename$ext";
  208.             print "SHLIB: $filename\n";
  209.             open $out, '>', $filename or die $!;
  210.             binmode($out);
  211.             print $out $buf;
  212.             close $out;
  213.         }
  214.         else {
  215.             $require_list{$fullname} =
  216.             $PAR::Heavy::ModuleCache{$fullname} = \"$buf";
  217.         }
  218.         read _FH, $buf, 4;
  219.     }
  220.     # }}}
  221.  
  222.     local @INC = (sub {
  223.         my ($self, $module) = @_;
  224.  
  225.         return if ref $module or !$module;
  226.  
  227.         my $filename = delete $require_list{$module} || do {
  228.             my $key;
  229.             foreach (keys %require_list) {
  230.                 next unless /\Q$module\E$/;
  231.                 $key = $_; last;
  232.             }
  233.             delete $require_list{$key};
  234.         } or return;
  235.  
  236.         $INC{$module} = "/loader/$filename/$module";
  237.  
  238.         if (defined(&IO::File::new)) {
  239.             my $fh = IO::File->new_tmpfile or die $!;
  240.             binmode($fh);
  241.             print $fh $$filename;
  242.             seek($fh, 0, 0);
  243.             return $fh;
  244.         }
  245.         else {
  246.             my ($out, $name) = _tempfile('.pm');
  247.             if ($out) {
  248.                 binmode($out);
  249.                 print $out $$filename;
  250.                 close $out;
  251.             }
  252.             open my $fh, $name or die $!;
  253.             binmode($fh);
  254.             return $fh;
  255.         }
  256.  
  257.         die "Bootstrapping failed: cannot find $module!\n";
  258.     }, @INC);
  259.     # }}}
  260.  
  261.     # Now load all bundled files {{{
  262.  
  263.     # initialize shared object processing
  264.     require XSLoader;
  265.     require PAR::Heavy;
  266.     require Carp::Heavy;
  267.     require Exporter::Heavy;
  268.     PAR::Heavy::_init_dynaloader();
  269.  
  270.     # now let's try getting helper modules from within
  271.     require IO::File;
  272.  
  273.     # load rest of the group in
  274.     while (my $filename = (sort keys %require_list)[0]) {
  275.         require $filename unless $INC{$filename} or $filename =~ /BSDPAN/;
  276.         delete $require_list{$filename};
  277.     }
  278.  
  279.     # }}}
  280.  
  281.     last unless $buf eq "PK\003\004";
  282.     $start_pos = (tell _FH) - 4;
  283. }
  284. # }}}
  285.  
  286. # Argument processing {{{
  287. my @par_args;
  288. my ($out, $bundle);
  289.  
  290. $quiet = 0 unless $ENV{PAR_DEBUG};
  291.  
  292. # Don't swallow arguments for compiled executables without --par-options
  293. if (!$start_pos or ($ARGV[0] eq '--par-options' && shift)) {
  294.     while (@ARGV) {
  295.         $ARGV[0] =~ /^-([AIMOBbq])(.*)/ or last;
  296.  
  297.         if ($1 eq 'I') {
  298.             unshift @INC, $2;
  299.         }
  300.         elsif ($1 eq 'M') {
  301.             eval "use $2";
  302.         }
  303.         elsif ($1 eq 'A') {
  304.             unshift @par_args, $2;
  305.         }
  306.         elsif ($1 eq 'O') {
  307.             $out = $2;
  308.         }
  309.         elsif ($1 eq 'b') {
  310.             $bundle = 'site';
  311.         }
  312.         elsif ($1 eq 'B') {
  313.             $bundle = 'all';
  314.         }
  315.         elsif ($1 eq 'q') {
  316.             $quiet = 1;
  317.         }
  318.  
  319.         shift(@ARGV);
  320.     }
  321. }
  322.  
  323. # XXX -- add --par-debug support!
  324.  
  325. # }}}
  326.  
  327. # Output mode (-O) handling {{{
  328. if ($out) {
  329.     my $par = shift(@ARGV);
  330.  
  331.     # Open input and output files {{{
  332.     local $/ = \4;
  333.  
  334.     if (defined $par) {
  335.         open PAR, '<', $par or die "$!: $par";
  336.         binmode(PAR);
  337.         die "$par is not a PAR file" unless <PAR> eq "PK\003\004";
  338.     }
  339.  
  340.     open OUT, '>', $out or die $!;
  341.     binmode(OUT);
  342.  
  343.     $/ = (defined $data_pos) ? \$data_pos : undef;
  344.     seek _FH, 0, 0;
  345.     my $loader = scalar <_FH>;
  346.     if (!$ENV{PAR_VERBATIM} and $loader =~ /^(?:#!|\@rem)/) {
  347.         print OUT pod_strip($loader, $0);
  348.     }
  349.     else {
  350.         print OUT $loader;
  351.     }
  352.     $/ = undef;
  353.     # }}}
  354.  
  355.     # Write bundled modules {{{
  356.     my $data_len = 0;
  357.     if ($bundle) {
  358.         require PAR::Heavy;
  359.         PAR::Heavy::_init_dynaloader();
  360.         require_modules();
  361.  
  362.         my @inc = sort {
  363.             length($b) <=> length($a)
  364.         } grep {
  365.             !/BSDPAN/
  366.         } grep {
  367.             ($bundle ne 'site') or 
  368.             ($_ ne $Config::Config{archlibexp} and
  369.              $_ ne $Config::Config{privlibexp});
  370.         } @INC;
  371.  
  372.         my %files;
  373.         /^_<(.+)$/ and $files{$1}++ for keys %::;
  374.         $files{$_}++ for values %INC;
  375.  
  376.         my $lib_ext = $Config::Config{lib_ext};
  377.         my %written;
  378.  
  379.         foreach (sort keys %files) {
  380.             my ($name, $file);
  381.  
  382.             foreach my $dir (@inc) {
  383.                 if ($name = $PAR::Heavy::FullCache{$_}) {
  384.                     $file = $_;
  385.                     last;
  386.                 }
  387.                 elsif (/^(\Q$dir\E\/(.*[^Cc]))\Z/) {
  388.                     ($file, $name) = ($1, $2);
  389.                     last;
  390.                 }
  391.                 elsif (m!^/loader/[^/]+/(.*[^Cc])\Z!) {
  392.                     if (my $ref = $PAR::Heavy::ModuleCache{$1}) {
  393.                         ($file, $name) = ($ref, $1);
  394.                         last;
  395.                     }
  396.                     elsif (-f "$dir/$1") {
  397.                         ($file, $name) = ("$dir/$1", $1);
  398.                         last;
  399.                     }
  400.                 }
  401.             }
  402.  
  403.             next unless defined $name and not $written{$name}++;
  404.             next if !ref($file) and $file =~ /\.\Q$lib_ext\E$/;
  405.             outs(qq(Packing "$file"...));
  406.  
  407.             my $content;
  408.             if (ref($file)) {
  409.                 $content = ${$file};
  410.             }
  411.             else {
  412.                 open FILE, "$file" or die "Can't open $file: $!";
  413.                 binmode(FILE);
  414.                 $content = <FILE>;
  415.                 close FILE;
  416.  
  417.                 $content = pod_strip($content, $file)
  418.                     if !$ENV{PAR_VERBATIM} and lc($name) =~ /\.(?:pm|ix|al)$/i;
  419.             }
  420.  
  421.             outs(qq(Written as "$name"));
  422.             print OUT "FILE";
  423.             print OUT pack('N', length($name) + 9);
  424.             print OUT sprintf(
  425.                 "%08x/%s", Archive::Zip::computeCRC32($content), $name
  426.             );
  427.             print OUT pack('N', length($content));
  428.             print OUT $content;
  429.  
  430.             $data_len += 12 + length($name) + 9 + length($content);
  431.         }
  432.     }
  433.     # }}}
  434.  
  435.     # Now write out the PAR and magic strings {{{
  436.     if (defined($par)) {
  437.         print OUT "PK\003\004";
  438.         print OUT <PAR>;
  439.         print OUT pack('N', $data_len + (stat($par))[7]);
  440.     }
  441.     else {
  442.         print OUT pack('N', $data_len);
  443.     }
  444.  
  445.     print OUT "\nPAR.pm\n";
  446.     close OUT;
  447.     chmod 0755, $out;
  448.     # }}}
  449.  
  450.     exit;
  451. }
  452. # }}}
  453.  
  454. # Prepare $0 into PAR file cache {{{
  455. {
  456.     last unless defined $start_pos;
  457.  
  458.     # Set up fake IO::File routines to point into the PAR subfile {{{
  459.     require IO::File;
  460.     my $fh = IO::File->new($0);
  461.     my $seek_ref  = $fh->can('seek');
  462.     my $tell_ref  = $fh->can('tell');
  463.  
  464.     *{'IO::File::seek'} = sub {
  465.         return $seek_ref->(@_) unless $PAR::__reading;
  466.         my ($fh, $pos, $whence) = @_;
  467.         $pos += $start_pos if $whence == 0;
  468.         $seek_ref->($fh, $pos, $whence);
  469.     };
  470.     *{'IO::File::tell'} = sub {
  471.         return $tell_ref->(@_) unless $PAR::__reading;
  472.         return $tell_ref->(@_) - $start_pos;
  473.     };
  474.     # }}}
  475.  
  476.     # Now load the PAR file and put it into PAR::LibCache {{{
  477.     require PAR;
  478.     PAR::Heavy::_init_dynaloader();
  479.     require Archive::Zip;
  480.  
  481.     local $PAR::__reading = 1;
  482.     my $zip = Archive::Zip->new;
  483.     $zip->readFromFileHandle($fh) == Archive::Zip::AZ_OK() or die "$!: $@";
  484.  
  485.     push @PAR::LibCache, $zip;
  486.     $PAR::LibCache{$0} = $zip;
  487.  
  488.     $quiet = !$ENV{PAR_DEBUG};
  489.     outs(qq(\$ENV{PAR_TEMP} = "$ENV{PAR_TEMP}"));
  490.  
  491.     foreach my $member ( $zip->members ) {
  492.         my $member_name = $member->fileName;
  493.         if ( $member_name =~ m|^/?shlib/(.+)$| and $ENV{PAR_TEMP} ) {
  494.             my $extract_name = $1;
  495.             my $dest_name = File::Spec->catfile($ENV{PAR_TEMP}, $extract_name);
  496.             $member->extractToFileNamed($dest_name);
  497.             outs(qq(Extracting "$member_name" to "$dest_name"));
  498.         }
  499.     }
  500.     # }}}
  501. }
  502. # }}}
  503.  
  504. # If there's no main.pl to run, show usage {{{
  505. unless ($PAR::LibCache{$0}) {
  506.     die << "." unless @ARGV;
  507. Usage: $0 [ -Alib.par ] [ -Idir ] [ -Mmodule ] [ src.par ] [ program.pl ]
  508.        $0 [ -B|-b ] [-Ooutfile] src.par
  509. .
  510.     $0 = shift(@ARGV)
  511. }
  512. # }}}
  513.  
  514. sub require_modules {
  515.     require lib;
  516.     require DynaLoader;
  517.     require integer;
  518.     require strict;
  519.     require warnings;
  520.     require vars;
  521.     require Carp;
  522.     require Carp::Heavy;
  523.     require Exporter::Heavy;
  524.     require Exporter;
  525.     require Fcntl;
  526.     require Cwd;
  527.     require File::Temp;
  528.     require File::Spec;
  529.     require XSLoader;
  530.     require Config;
  531.     require IO::File;
  532.     require Compress::Zlib;
  533.     require Archive::Zip;
  534.     require PAR;
  535.     require PAR::Heavy;
  536. }
  537.  
  538. # N.B. we set PAR_TMP_DIR and PAR_TEMP in myldr/main.c
  539. my $tmpdir;
  540. sub tmpdir {
  541.     return $tmpdir if defined $tmpdir;
  542.     my @dirlist = (@ENV{qw(PAR_TEMP PAR_TMP_DIR TMPDIR TEMP TMP)}, qw(C:/temp /tmp /));
  543.     {
  544.         if (${"\cTAINT"}) { eval {
  545.             require Scalar::Util;
  546.             @dirlist = grep { ! Scalar::Util::tainted $_ } @dirlist;
  547.         } }
  548.     }
  549.     foreach (@dirlist) {
  550.         next unless defined && -d;
  551.         $tmpdir = $_;
  552.         last;
  553.     }
  554.     $tmpdir = '' unless defined $tmpdir;
  555.     return $tmpdir;
  556. }
  557.  
  558. my ($tmpfile, @tmpfiles);
  559. sub _tempfile {
  560.     my ($ext, $crc) = @_;
  561.     my ($fh, $filename);
  562.     
  563.     if (defined $crc and !$ENV{PAR_CLEARTEMP}) {
  564.         $filename = tmpdir() . "/$crc$ext";
  565.         return (undef, $filename) if (-r $filename);
  566.  
  567.         open $fh, '>', $filename or die $!;
  568.     }
  569.     elsif (defined &File::Temp::tempfile) {
  570.         # under Win32, the file is created with O_TEMPORARY,
  571.         # and will be deleted by the C runtime; having File::Temp
  572.         # delete it has the only effect of giving an ugly warnings
  573.         ($fh, $filename) = File::Temp::tempfile(
  574.             SUFFIX      => $ext,
  575.             UNLINK      => ($^O ne 'MSWin32'),
  576.         ) or die $!;
  577.     }
  578.     else {
  579.         my $tmpdir = tmpdir();
  580.         $tmpfile ||= ($$ . '0000');
  581.         do { $tmpfile++ } while -e ($filename = "$tmpdir/$tmpfile$ext");
  582.         push @tmpfiles, $filename;
  583.         open $fh, ">", $filename or die $!;
  584.     }
  585.  
  586.     binmode($fh);
  587.     return ($fh, $filename);
  588. }
  589. END { unlink @tmpfiles if @tmpfiles }
  590.  
  591. sub outs { warn("@_\n") unless $quiet }
  592.  
  593. sub pod_strip {
  594.     my ($pl_text, $filename) = @_;
  595.  
  596.     local $^W;
  597.     my $line = 1;
  598.     if ($pl_text =~ /^=(?:head\d|pod|begin|item|over|for|back|end)\b/) {
  599.         $pl_text = "\n$pl_text";
  600.         $line--;
  601.     }
  602.     $pl_text =~ s{(
  603.     (.*?\n)
  604.     =(?:head\d|pod|begin|item|over|for|back|end)\b
  605.     .*?\n
  606.     (?:=cut[\t ]*[\r\n]*?|\Z)
  607.     (\r?\n)?
  608.     )}{
  609.     my ($pre, $post) = ($2, $3);
  610.         "$pre#line " . (
  611.         $line += ( () = ( $1 =~ /\n/g ) )
  612.     ) . $post;
  613.     }gsex;
  614.     $pl_text = '#line 1 "' . ($filename) . "\"\n" . $pl_text
  615.         if length $filename;
  616.  
  617.     return $pl_text;
  618. }
  619.  
  620. ########################################################################
  621. # The main package for script execution
  622.  
  623. package main;
  624.  
  625. require PAR;
  626. unshift @INC, \&PAR::find_par;
  627. PAR->import(@par_args);
  628.  
  629. die qq(Can't open perl script "$0": No such file or directory\n)
  630.     unless -e $0;
  631.  
  632. do $0;
  633. die $@ if $@;
  634. exit;
  635.  
  636. =head1 SEE ALSO
  637.  
  638. L<PAR>, L<parl>, L<pp>
  639.  
  640. =head1 AUTHORS
  641.  
  642. Autrijus Tang E<lt>autrijus@autrijus.orgE<gt>
  643.  
  644. PAR has a mailing list, E<lt>par@perl.orgE<gt>, that you can write to;
  645. send an empty mail to E<lt>par-subscribe@perl.orgE<gt> to join the list
  646. and participate in the discussion.
  647.  
  648. Please send bug reports to E<lt>bug-par@rt.cpan.orgE<gt>.
  649.  
  650. =head1 COPYRIGHT
  651.  
  652. Copyright 2002, 2003 by Autrijus Tang E<lt>autrijus@autrijus.orgE<gt>.
  653.  
  654. Neither this program nor the associated L<parl> program impose any
  655. licensing restrictions on files generated by their execution, in
  656. accordance with the 8th article of the Artistic License:
  657.  
  658.     "Aggregation of this Package with a commercial distribution is
  659.     always permitted provided that the use of this Package is embedded;
  660.     that is, when no overt attempt is made to make this Package's
  661.     interfaces visible to the end user of the commercial distribution.
  662.     Such use shall not be construed as a distribution of this Package."
  663.  
  664. Therefore, you are absolutely free to place any license on the resulting
  665. executable, as long as the packed 3rd-party libraries are also available
  666. under the Artistic License.
  667.  
  668. This program is free software; you can redistribute it and/or modify it
  669. under the same terms as Perl itself.
  670.  
  671. See L<http://www.perl.com/perl/misc/Artistic.html>
  672.  
  673. =cut
  674.  
  675. __END__
  676.