diff options
Diffstat (limited to 'lib/AutoSplit.pm')
-rw-r--r-- | lib/AutoSplit.pm | 137 |
1 files changed, 112 insertions, 25 deletions
diff --git a/lib/AutoSplit.pm b/lib/AutoSplit.pm index f9e3ad6dc4..2fd0cac32d 100644 --- a/lib/AutoSplit.pm +++ b/lib/AutoSplit.pm @@ -5,6 +5,7 @@ require Exporter; use Config; use Carp; +use File::Path qw(mkpath); @ISA = qw(Exporter); @EXPORT = qw(&autosplit &autosplit_lib_modules); @@ -16,14 +17,81 @@ AutoSplit - split a package for autoloading =head1 SYNOPSIS - perl -e 'use AutoSplit; autosplit_modules(@ARGV)' ... + perl -e 'use AutoSplit; autosplit_lib_modules(@ARGV)' ... + + use AutoSplit; autosplit($file, $dir, $keep, $check, $modtime); + +for perl versions 5.002 and later: + + perl -MAutoSplit -e 'autosplit($ARGV[0], $ARGV[1], $k, $chk, $modtime)' ... =head1 DESCRIPTION This function will split up your program into files that the AutoLoader -module can handle. Normally only used to build autoloading Perl library -modules, especially extensions (like POSIX). You should look at how -they're built out for details. +module can handle. It is used by both the standard perl libraries and by +the MakeMaker utility, to automatically configure libraries for autoloading. + +The C<autosplit> interface splits the specified file into a hierarchy +rooted at the directory C<$dir>. It creates directories as needed to reflect +class hierarchy, and creates the file F<autosplit.ix>. This file acts as +both forward declaration of all package routines, and as timestamp for the +last update of the hierarchy. + +The remaining three arguments to C<autosplit> govern other options to the +autosplitter. If the third argument, I<$keep>, is false, then any pre-existing +C<*.al> files in the autoload directory are removed if they are no longer +part of the module (obsoleted functions). The fourth argument, I<$check>, +instructs C<autosplit> to check the module currently being split to ensure +that it does include a C<use> specification for the AutoLoader module, and +skips the module if AutoLoader is not detected. Lastly, the I<$modtime> +argument specifies that C<autosplit> is to check the modification time of the +module against that of the C<autosplit.ix> file, and only split the module +if it is newer. + +Typical use of AutoSplit in the perl MakeMaker utility is via the command-line +with: + + perl -e 'use AutoSplit; autosplit($ARGV[0], $ARGV[1], 0, 1, 1)' + +Defined as a Make macro, it is invoked with file and directory arguments; +C<autosplit> will split the specified file into the specified directory and +delete obsolete C<.al> files, after checking first that the module does use +the AutoLoader, and ensuring that the module is not already currently split +in its current form (the modtime test). + +The C<autosplit_lib_modules> form is used in the building of perl. It takes +as input a list of files (modules) that are assumed to reside in a directory +B<lib> relative to the current directory. Each file is sent to the +autosplitter one at a time, to be split into the directory B<lib/auto>. + +In both usages of the autosplitter, only subroutines defined following the +perl special marker I<__END__> are split out into separate files. Some +routines may be placed prior to this marker to force their immediate loading +and parsing. + +=head1 CAVEATS + +Currently, C<AutoSplit> cannot handle multiple package specifications +within one file. + +=head1 DIAGNOSTICS + +C<AutoSplit> will inform the user if it is necessary to create the top-level +directory specified in the invocation. It is preferred that the script or +installation process that invokes C<AutoSplit> have created the full directory +path ahead of time. This warning may indicate that the module is being split +into an incorrect path. + +C<AutoSplit> will warn the user of all subroutines whose name causes potential +file naming conflicts on machines with drastically limited (8 characters or +less) file name length. Since the subroutine name is used as the file name, +these warnings can aid in portability to such systems. + +Warnings are issued and the file skipped if C<AutoSplit> cannot locate either +the I<__END__> marker or a "package Name;"-style specification. + +C<AutoSplit> will also emit general diagnostics for inability to create +directories or files. =cut @@ -53,7 +121,7 @@ sub autosplit{ # This function is used during perl building/installation -# ./miniperl -e 'use AutoSplit; autosplit_modules(@ARGV)' ... +# ./miniperl -e 'use AutoSplit; autosplit_lib_modules(@ARGV)' ... sub autosplit_lib_modules{ my(@modules) = @_; # list of Module names @@ -82,14 +150,12 @@ sub autosplit_file{ # where to write output files $autodir = "lib/auto" unless $autodir; - ($autodir = VMS::Filespec::unixpath($autodir)) =~ s#/$## if $Is_VMS; + if ($Is_VMS) { + ($autodir = VMS::Filespec::unixpath($autodir)) =~ s{/$}{}; + $filename = VMS::Filespec::unixify($filename); # may have dirs + } unless (-d $autodir){ - local($", @p)="/"; - foreach(split(/\//,$autodir)){ - push(@p, $_); - next if -d "@p/"; - mkdir("@p",0755) or die "AutoSplit unable to mkdir @p: $!"; - } + mkpath($autodir,0,0755); # We should never need to create the auto dir here. installperl # (or similar) should have done it. Expecting it to exist is a valuable # sanity check against autosplitting into some random directory by mistake. @@ -123,13 +189,20 @@ sub autosplit_file{ $package or die "Can't find 'package Name;' in $filename\n"; - my($modpname) = $package; $modpname =~ s#::#/#g; - my($al_idx_file) = "$autodir/$modpname/$IndexFile"; + my($modpname) = $package; + if ($^O eq 'MSWin32') { + $modpname =~ s#::#\\#g; + } else { + $modpname =~ s#::#/#g; + } - die "Package $package does not match filename $filename" - unless ($filename =~ m/$modpname.pm$/ or + die "Package $package ($modpname.pm) does not match filename $filename" + unless ($filename =~ m/\Q$modpname.pm\E$/ or + ($^O eq "msdos") or ($^O eq 'MSWin32') or $Is_VMS && $filename =~ m/$modpname.pm/i); + my($al_idx_file) = "$autodir/$modpname/$IndexFile"; + if ($check_mod_time){ my($al_ts_time) = (stat("$al_idx_file"))[9] || 1; if ($al_ts_time >= $pm_mod_time){ @@ -144,12 +217,7 @@ sub autosplit_file{ if $Verbose; unless (-d "$autodir/$modpname"){ - local($", @p)="/"; - foreach(split(/\//,"$autodir/$modpname")){ - push(@p, $_); - next if -d "@p/"; - mkdir("@p",0777) or die "AutoSplit unable to mkdir @p: $!"; - } + mkpath("$autodir/$modpname",0,0777); } # We must try to deal with some SVR3 systems with a limit of 14 @@ -180,14 +248,17 @@ sub autosplit_file{ open(OUT,">/dev/null") || open(OUT,">nla0:"); # avoid 'not opened' warning my(@subnames, %proto); + my @cache = (); + my $caching = 1; while (<IN>) { + next if /^=\w/ .. /^=cut/; if (/^package ([\w:]+)\s*;/) { warn "package $1; in AutoSplit section ignored. Not currently supported."; } if (/^sub\s+([\w:]+)(\s*\(.*?\))?/) { print OUT "1;\n"; my $subname = $1; - $proto{$1} = $2 or ''; + $proto{$1} = $2 || ''; if ($subname =~ m/::/){ warn "subs with package names not currently supported in AutoSplit section"; } @@ -207,10 +278,26 @@ sub autosplit_file{ print OUT "# NOTE: Derived from $filename. ", "Changes made here will be lost.\n"; print OUT "package $package;\n\n"; + print OUT @cache; + @cache = (); + $caching = 0; + } + if($caching) { + push(@cache, $_) if @cache || /\S/; + } + else { + print OUT $_; + } + if(/^}/) { + if($caching) { + print OUT @cache; + @cache = (); + } + print OUT "\n"; + $caching = 1; } - print OUT $_; } - print OUT "1;\n"; + print OUT @cache,"1;\n"; close(OUT); close(IN); |