1*b39c5158Smillertpackage AutoSplit; 2*b39c5158Smillert 3*b39c5158Smillertuse Exporter (); 4*b39c5158Smillertuse Config qw(%Config); 5*b39c5158Smillertuse File::Basename (); 6*b39c5158Smillertuse File::Path qw(mkpath); 7*b39c5158Smillertuse File::Spec::Functions qw(curdir catfile catdir); 8*b39c5158Smillertuse strict; 9*b39c5158Smillertour($VERSION, @ISA, @EXPORT, @EXPORT_OK, $Verbose, $Keep, $Maxlen, 10*b39c5158Smillert $CheckForAutoloader, $CheckModTime); 11*b39c5158Smillert 12*b39c5158Smillert$VERSION = "1.06"; 13*b39c5158Smillert@ISA = qw(Exporter); 14*b39c5158Smillert@EXPORT = qw(&autosplit &autosplit_lib_modules); 15*b39c5158Smillert@EXPORT_OK = qw($Verbose $Keep $Maxlen $CheckForAutoloader $CheckModTime); 16*b39c5158Smillert 17*b39c5158Smillert=head1 NAME 18*b39c5158Smillert 19*b39c5158SmillertAutoSplit - split a package for autoloading 20*b39c5158Smillert 21*b39c5158Smillert=head1 SYNOPSIS 22*b39c5158Smillert 23*b39c5158Smillert autosplit($file, $dir, $keep, $check, $modtime); 24*b39c5158Smillert 25*b39c5158Smillert autosplit_lib_modules(@modules); 26*b39c5158Smillert 27*b39c5158Smillert=head1 DESCRIPTION 28*b39c5158Smillert 29*b39c5158SmillertThis function will split up your program into files that the AutoLoader 30*b39c5158Smillertmodule can handle. It is used by both the standard perl libraries and by 31*b39c5158Smillertthe MakeMaker utility, to automatically configure libraries for autoloading. 32*b39c5158Smillert 33*b39c5158SmillertThe C<autosplit> interface splits the specified file into a hierarchy 34*b39c5158Smillertrooted at the directory C<$dir>. It creates directories as needed to reflect 35*b39c5158Smillertclass hierarchy, and creates the file F<autosplit.ix>. This file acts as 36*b39c5158Smillertboth forward declaration of all package routines, and as timestamp for the 37*b39c5158Smillertlast update of the hierarchy. 38*b39c5158Smillert 39*b39c5158SmillertThe remaining three arguments to C<autosplit> govern other options to 40*b39c5158Smillertthe autosplitter. 41*b39c5158Smillert 42*b39c5158Smillert=over 2 43*b39c5158Smillert 44*b39c5158Smillert=item $keep 45*b39c5158Smillert 46*b39c5158SmillertIf the third argument, I<$keep>, is false, then any 47*b39c5158Smillertpre-existing C<*.al> files in the autoload directory are removed if 48*b39c5158Smillertthey are no longer part of the module (obsoleted functions). 49*b39c5158Smillert$keep defaults to 0. 50*b39c5158Smillert 51*b39c5158Smillert=item $check 52*b39c5158Smillert 53*b39c5158SmillertThe 54*b39c5158Smillertfourth argument, I<$check>, instructs C<autosplit> to check the module 55*b39c5158Smillertcurrently being split to ensure that it includes a C<use> 56*b39c5158Smillertspecification for the AutoLoader module, and skips the module if 57*b39c5158SmillertAutoLoader is not detected. 58*b39c5158Smillert$check defaults to 1. 59*b39c5158Smillert 60*b39c5158Smillert=item $modtime 61*b39c5158Smillert 62*b39c5158SmillertLastly, the I<$modtime> argument specifies 63*b39c5158Smillertthat C<autosplit> is to check the modification time of the module 64*b39c5158Smillertagainst that of the C<autosplit.ix> file, and only split the module if 65*b39c5158Smillertit is newer. 66*b39c5158Smillert$modtime defaults to 1. 67*b39c5158Smillert 68*b39c5158Smillert=back 69*b39c5158Smillert 70*b39c5158SmillertTypical use of AutoSplit in the perl MakeMaker utility is via the command-line 71*b39c5158Smillertwith: 72*b39c5158Smillert 73*b39c5158Smillert perl -e 'use AutoSplit; autosplit($ARGV[0], $ARGV[1], 0, 1, 1)' 74*b39c5158Smillert 75*b39c5158SmillertDefined as a Make macro, it is invoked with file and directory arguments; 76*b39c5158SmillertC<autosplit> will split the specified file into the specified directory and 77*b39c5158Smillertdelete obsolete C<.al> files, after checking first that the module does use 78*b39c5158Smillertthe AutoLoader, and ensuring that the module is not already currently split 79*b39c5158Smillertin its current form (the modtime test). 80*b39c5158Smillert 81*b39c5158SmillertThe C<autosplit_lib_modules> form is used in the building of perl. It takes 82*b39c5158Smillertas input a list of files (modules) that are assumed to reside in a directory 83*b39c5158SmillertB<lib> relative to the current directory. Each file is sent to the 84*b39c5158Smillertautosplitter one at a time, to be split into the directory B<lib/auto>. 85*b39c5158Smillert 86*b39c5158SmillertIn both usages of the autosplitter, only subroutines defined following the 87*b39c5158Smillertperl I<__END__> token are split out into separate files. Some 88*b39c5158Smillertroutines may be placed prior to this marker to force their immediate loading 89*b39c5158Smillertand parsing. 90*b39c5158Smillert 91*b39c5158Smillert=head2 Multiple packages 92*b39c5158Smillert 93*b39c5158SmillertAs of version 1.01 of the AutoSplit module it is possible to have 94*b39c5158Smillertmultiple packages within a single file. Both of the following cases 95*b39c5158Smillertare supported: 96*b39c5158Smillert 97*b39c5158Smillert package NAME; 98*b39c5158Smillert __END__ 99*b39c5158Smillert sub AAA { ... } 100*b39c5158Smillert package NAME::option1; 101*b39c5158Smillert sub BBB { ... } 102*b39c5158Smillert package NAME::option2; 103*b39c5158Smillert sub BBB { ... } 104*b39c5158Smillert 105*b39c5158Smillert package NAME; 106*b39c5158Smillert __END__ 107*b39c5158Smillert sub AAA { ... } 108*b39c5158Smillert sub NAME::option1::BBB { ... } 109*b39c5158Smillert sub NAME::option2::BBB { ... } 110*b39c5158Smillert 111*b39c5158Smillert=head1 DIAGNOSTICS 112*b39c5158Smillert 113*b39c5158SmillertC<AutoSplit> will inform the user if it is necessary to create the 114*b39c5158Smillerttop-level directory specified in the invocation. It is preferred that 115*b39c5158Smillertthe script or installation process that invokes C<AutoSplit> have 116*b39c5158Smillertcreated the full directory path ahead of time. This warning may 117*b39c5158Smillertindicate that the module is being split into an incorrect path. 118*b39c5158Smillert 119*b39c5158SmillertC<AutoSplit> will warn the user of all subroutines whose name causes 120*b39c5158Smillertpotential file naming conflicts on machines with drastically limited 121*b39c5158Smillert(8 characters or less) file name length. Since the subroutine name is 122*b39c5158Smillertused as the file name, these warnings can aid in portability to such 123*b39c5158Smillertsystems. 124*b39c5158Smillert 125*b39c5158SmillertWarnings are issued and the file skipped if C<AutoSplit> cannot locate 126*b39c5158Smillerteither the I<__END__> marker or a "package Name;"-style specification. 127*b39c5158Smillert 128*b39c5158SmillertC<AutoSplit> will also emit general diagnostics for inability to 129*b39c5158Smillertcreate directories or files. 130*b39c5158Smillert 131*b39c5158Smillert=head1 AUTHOR 132*b39c5158Smillert 133*b39c5158SmillertC<AutoSplit> is maintained by the perl5-porters. Please direct 134*b39c5158Smillertany questions to the canonical mailing list. Anything that 135*b39c5158Smillertis applicable to the CPAN release can be sent to its maintainer, 136*b39c5158Smillertthough. 137*b39c5158Smillert 138*b39c5158SmillertAuthor and Maintainer: The Perl5-Porters <perl5-porters@perl.org> 139*b39c5158Smillert 140*b39c5158SmillertMaintainer of the CPAN release: Steffen Mueller <smueller@cpan.org> 141*b39c5158Smillert 142*b39c5158Smillert=head1 COPYRIGHT AND LICENSE 143*b39c5158Smillert 144*b39c5158SmillertThis package has been part of the perl core since the first release 145*b39c5158Smillertof perl5. It has been released separately to CPAN so older installations 146*b39c5158Smillertcan benefit from bug fixes. 147*b39c5158Smillert 148*b39c5158SmillertThis package has the same copyright and license as the perl core: 149*b39c5158Smillert 150*b39c5158Smillert Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 151*b39c5158Smillert 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 152*b39c5158Smillert by Larry Wall and others 153*b39c5158Smillert 154*b39c5158Smillert All rights reserved. 155*b39c5158Smillert 156*b39c5158Smillert This program is free software; you can redistribute it and/or modify 157*b39c5158Smillert it under the terms of either: 158*b39c5158Smillert 159*b39c5158Smillert a) the GNU General Public License as published by the Free 160*b39c5158Smillert Software Foundation; either version 1, or (at your option) any 161*b39c5158Smillert later version, or 162*b39c5158Smillert 163*b39c5158Smillert b) the "Artistic License" which comes with this Kit. 164*b39c5158Smillert 165*b39c5158Smillert This program is distributed in the hope that it will be useful, 166*b39c5158Smillert but WITHOUT ANY WARRANTY; without even the implied warranty of 167*b39c5158Smillert MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See either 168*b39c5158Smillert the GNU General Public License or the Artistic License for more details. 169*b39c5158Smillert 170*b39c5158Smillert You should have received a copy of the Artistic License with this 171*b39c5158Smillert Kit, in the file named "Artistic". If not, I'll be glad to provide one. 172*b39c5158Smillert 173*b39c5158Smillert You should also have received a copy of the GNU General Public License 174*b39c5158Smillert along with this program in the file named "Copying". If not, write to the 175*b39c5158Smillert Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 176*b39c5158Smillert 02111-1307, USA or visit their web page on the internet at 177*b39c5158Smillert http://www.gnu.org/copyleft/gpl.html. 178*b39c5158Smillert 179*b39c5158Smillert For those of you that choose to use the GNU General Public License, 180*b39c5158Smillert my interpretation of the GNU General Public License is that no Perl 181*b39c5158Smillert script falls under the terms of the GPL unless you explicitly put 182*b39c5158Smillert said script under the terms of the GPL yourself. Furthermore, any 183*b39c5158Smillert object code linked with perl does not automatically fall under the 184*b39c5158Smillert terms of the GPL, provided such object code only adds definitions 185*b39c5158Smillert of subroutines and variables, and does not otherwise impair the 186*b39c5158Smillert resulting interpreter from executing any standard Perl script. I 187*b39c5158Smillert consider linking in C subroutines in this manner to be the moral 188*b39c5158Smillert equivalent of defining subroutines in the Perl language itself. You 189*b39c5158Smillert may sell such an object file as proprietary provided that you provide 190*b39c5158Smillert or offer to provide the Perl source, as specified by the GNU General 191*b39c5158Smillert Public License. (This is merely an alternate way of specifying input 192*b39c5158Smillert to the program.) You may also sell a binary produced by the dumping of 193*b39c5158Smillert a running Perl script that belongs to you, provided that you provide or 194*b39c5158Smillert offer to provide the Perl source as specified by the GPL. (The 195*b39c5158Smillert fact that a Perl interpreter and your code are in the same binary file 196*b39c5158Smillert is, in this case, a form of mere aggregation.) This is my interpretation 197*b39c5158Smillert of the GPL. If you still have concerns or difficulties understanding 198*b39c5158Smillert my intent, feel free to contact me. Of course, the Artistic License 199*b39c5158Smillert spells all this out for your protection, so you may prefer to use that. 200*b39c5158Smillert 201*b39c5158Smillert=cut 202*b39c5158Smillert 203*b39c5158Smillert# for portability warn about names longer than $maxlen 204*b39c5158Smillert$Maxlen = 8; # 8 for dos, 11 (14-".al") for SYSVR3 205*b39c5158Smillert$Verbose = 1; # 0=none, 1=minimal, 2=list .al files 206*b39c5158Smillert$Keep = 0; 207*b39c5158Smillert$CheckForAutoloader = 1; 208*b39c5158Smillert$CheckModTime = 1; 209*b39c5158Smillert 210*b39c5158Smillertmy $IndexFile = "autosplit.ix"; # file also serves as timestamp 211*b39c5158Smillertmy $maxflen = 255; 212*b39c5158Smillert$maxflen = 14 if $Config{'d_flexfnam'} ne 'define'; 213*b39c5158Smillertif (defined (&Dos::UseLFN)) { 214*b39c5158Smillert $maxflen = Dos::UseLFN() ? 255 : 11; 215*b39c5158Smillert} 216*b39c5158Smillertmy $Is_VMS = ($^O eq 'VMS'); 217*b39c5158Smillert 218*b39c5158Smillert# allow checking for valid ': attrlist' attachments. 219*b39c5158Smillert# extra jugglery required to support both 5.8 and 5.9/5.10 features 220*b39c5158Smillert# (support for 5.8 required for cross-compiling environments) 221*b39c5158Smillert 222*b39c5158Smillertmy $attr_list = 223*b39c5158Smillert $] >= 5.009005 ? 224*b39c5158Smillert eval <<'__QR__' 225*b39c5158Smillert qr{ 226*b39c5158Smillert \s* : \s* 227*b39c5158Smillert (?: 228*b39c5158Smillert # one attribute 229*b39c5158Smillert (?> # no backtrack 230*b39c5158Smillert (?! \d) \w+ 231*b39c5158Smillert (?<nested> \( (?: [^()]++ | (?&nested)++ )*+ \) ) ? 232*b39c5158Smillert ) 233*b39c5158Smillert (?: \s* : \s* | \s+ (?! :) ) 234*b39c5158Smillert )* 235*b39c5158Smillert }x 236*b39c5158Smillert__QR__ 237*b39c5158Smillert : 238*b39c5158Smillert do { 239*b39c5158Smillert # In pre-5.9.5 world we have to do dirty tricks. 240*b39c5158Smillert # (we use 'our' rather than 'my' here, due to the rather complex and buggy 241*b39c5158Smillert # behaviour of lexicals with qr// and (??{$lex}) ) 242*b39c5158Smillert our $trick1; # yes, cannot our and assign at the same time. 243*b39c5158Smillert $trick1 = qr{ \( (?: (?> [^()]+ ) | (??{ $trick1 }) )* \) }x; 244*b39c5158Smillert our $trick2 = qr{ (?> (?! \d) \w+ (?:$trick1)? ) (?:\s*\:\s*|\s+(?!\:)) }x; 245*b39c5158Smillert qr{ \s* : \s* (?: $trick2 )* }x; 246*b39c5158Smillert }; 247*b39c5158Smillert 248*b39c5158Smillertsub autosplit{ 249*b39c5158Smillert my($file, $autodir, $keep, $ckal, $ckmt) = @_; 250*b39c5158Smillert # $file - the perl source file to be split (after __END__) 251*b39c5158Smillert # $autodir - the ".../auto" dir below which to write split subs 252*b39c5158Smillert # Handle optional flags: 253*b39c5158Smillert $keep = $Keep unless defined $keep; 254*b39c5158Smillert $ckal = $CheckForAutoloader unless defined $ckal; 255*b39c5158Smillert $ckmt = $CheckModTime unless defined $ckmt; 256*b39c5158Smillert autosplit_file($file, $autodir, $keep, $ckal, $ckmt); 257*b39c5158Smillert} 258*b39c5158Smillert 259*b39c5158Smillertsub carp{ 260*b39c5158Smillert require Carp; 261*b39c5158Smillert goto &Carp::carp; 262*b39c5158Smillert} 263*b39c5158Smillert 264*b39c5158Smillert# This function is used during perl building/installation 265*b39c5158Smillert# ./miniperl -e 'use AutoSplit; autosplit_lib_modules(@ARGV)' ... 266*b39c5158Smillert 267*b39c5158Smillertsub autosplit_lib_modules { 268*b39c5158Smillert my(@modules) = @_; # list of Module names 269*b39c5158Smillert local $_; # Avoid clobber. 270*b39c5158Smillert while (defined($_ = shift @modules)) { 271*b39c5158Smillert while (m#([^:]+)::([^:].*)#) { # in case specified as ABC::XYZ 272*b39c5158Smillert $_ = catfile($1, $2); 273*b39c5158Smillert } 274*b39c5158Smillert s|\\|/|g; # bug in ksh OS/2 275*b39c5158Smillert s#^lib/##s; # incase specified as lib/*.pm 276*b39c5158Smillert my($lib) = catfile(curdir(), "lib"); 277*b39c5158Smillert if ($Is_VMS) { # may need to convert VMS-style filespecs 278*b39c5158Smillert $lib =~ s#^\[\]#.\/#; 279*b39c5158Smillert } 280*b39c5158Smillert s#^$lib\W+##s; # incase specified as ./lib/*.pm 281*b39c5158Smillert if ($Is_VMS && /[:>\]]/) { # may need to convert VMS-style filespecs 282*b39c5158Smillert my ($dir,$name) = (/(.*])(.*)/s); 283*b39c5158Smillert $dir =~ s/.*lib[\.\]]//s; 284*b39c5158Smillert $dir =~ s#[\.\]]#/#g; 285*b39c5158Smillert $_ = $dir . $name; 286*b39c5158Smillert } 287*b39c5158Smillert autosplit_file(catfile($lib, $_), catfile($lib, "auto"), 288*b39c5158Smillert $Keep, $CheckForAutoloader, $CheckModTime); 289*b39c5158Smillert } 290*b39c5158Smillert 0; 291*b39c5158Smillert} 292*b39c5158Smillert 293*b39c5158Smillert 294*b39c5158Smillert# private functions 295*b39c5158Smillert 296*b39c5158Smillertmy $self_mod_time = (stat __FILE__)[9]; 297*b39c5158Smillert 298*b39c5158Smillertsub autosplit_file { 299*b39c5158Smillert my($filename, $autodir, $keep, $check_for_autoloader, $check_mod_time) 300*b39c5158Smillert = @_; 301*b39c5158Smillert my(@outfiles); 302*b39c5158Smillert local($_); 303*b39c5158Smillert local($/) = "\n"; 304*b39c5158Smillert 305*b39c5158Smillert # where to write output files 306*b39c5158Smillert $autodir ||= catfile(curdir(), "lib", "auto"); 307*b39c5158Smillert if ($Is_VMS) { 308*b39c5158Smillert ($autodir = VMS::Filespec::unixpath($autodir)) =~ s|/\z||; 309*b39c5158Smillert $filename = VMS::Filespec::unixify($filename); # may have dirs 310*b39c5158Smillert } 311*b39c5158Smillert unless (-d $autodir){ 312*b39c5158Smillert mkpath($autodir,0,0755); 313*b39c5158Smillert # We should never need to create the auto dir 314*b39c5158Smillert # here. installperl (or similar) should have done 315*b39c5158Smillert # it. Expecting it to exist is a valuable sanity check against 316*b39c5158Smillert # autosplitting into some random directory by mistake. 317*b39c5158Smillert print "Warning: AutoSplit had to create top-level " . 318*b39c5158Smillert "$autodir unexpectedly.\n"; 319*b39c5158Smillert } 320*b39c5158Smillert 321*b39c5158Smillert # allow just a package name to be used 322*b39c5158Smillert $filename .= ".pm" unless ($filename =~ m/\.pm\z/); 323*b39c5158Smillert 324*b39c5158Smillert open(my $in, "<$filename") or die "AutoSplit: Can't open $filename: $!\n"; 325*b39c5158Smillert my($pm_mod_time) = (stat($filename))[9]; 326*b39c5158Smillert my($autoloader_seen) = 0; 327*b39c5158Smillert my($in_pod) = 0; 328*b39c5158Smillert my($def_package,$last_package,$this_package,$fnr); 329*b39c5158Smillert while (<$in>) { 330*b39c5158Smillert # Skip pod text. 331*b39c5158Smillert $fnr++; 332*b39c5158Smillert $in_pod = 1 if /^=\w/; 333*b39c5158Smillert $in_pod = 0 if /^=cut/; 334*b39c5158Smillert next if ($in_pod || /^=cut/); 335*b39c5158Smillert next if /^\s*#/; 336*b39c5158Smillert 337*b39c5158Smillert # record last package name seen 338*b39c5158Smillert $def_package = $1 if (m/^\s*package\s+([\w:]+)\s*;/); 339*b39c5158Smillert ++$autoloader_seen if m/^\s*(use|require)\s+AutoLoader\b/; 340*b39c5158Smillert ++$autoloader_seen if m/\bISA\s*=.*\bAutoLoader\b/; 341*b39c5158Smillert last if /^__END__/; 342*b39c5158Smillert } 343*b39c5158Smillert if ($check_for_autoloader && !$autoloader_seen){ 344*b39c5158Smillert print "AutoSplit skipped $filename: no AutoLoader used\n" 345*b39c5158Smillert if ($Verbose>=2); 346*b39c5158Smillert return 0; 347*b39c5158Smillert } 348*b39c5158Smillert $_ or die "Can't find __END__ in $filename\n"; 349*b39c5158Smillert 350*b39c5158Smillert $def_package or die "Can't find 'package Name;' in $filename\n"; 351*b39c5158Smillert 352*b39c5158Smillert my($modpname) = _modpname($def_package); 353*b39c5158Smillert 354*b39c5158Smillert # this _has_ to match so we have a reasonable timestamp file 355*b39c5158Smillert die "Package $def_package ($modpname.pm) does not ". 356*b39c5158Smillert "match filename $filename" 357*b39c5158Smillert unless ($filename =~ m/\Q$modpname.pm\E$/ or 358*b39c5158Smillert ($^O eq 'dos') or ($^O eq 'MSWin32') or ($^O eq 'NetWare') or 359*b39c5158Smillert $Is_VMS && $filename =~ m/$modpname.pm/i); 360*b39c5158Smillert 361*b39c5158Smillert my($al_idx_file) = catfile($autodir, $modpname, $IndexFile); 362*b39c5158Smillert 363*b39c5158Smillert if ($check_mod_time){ 364*b39c5158Smillert my($al_ts_time) = (stat("$al_idx_file"))[9] || 1; 365*b39c5158Smillert if ($al_ts_time >= $pm_mod_time and 366*b39c5158Smillert $al_ts_time >= $self_mod_time){ 367*b39c5158Smillert print "AutoSplit skipped ($al_idx_file newer than $filename)\n" 368*b39c5158Smillert if ($Verbose >= 2); 369*b39c5158Smillert return undef; # one undef, not a list 370*b39c5158Smillert } 371*b39c5158Smillert } 372*b39c5158Smillert 373*b39c5158Smillert my($modnamedir) = catdir($autodir, $modpname); 374*b39c5158Smillert print "AutoSplitting $filename ($modnamedir)\n" 375*b39c5158Smillert if $Verbose; 376*b39c5158Smillert 377*b39c5158Smillert unless (-d $modnamedir){ 378*b39c5158Smillert mkpath($modnamedir,0,0777); 379*b39c5158Smillert } 380*b39c5158Smillert 381*b39c5158Smillert # We must try to deal with some SVR3 systems with a limit of 14 382*b39c5158Smillert # characters for file names. Sadly we *cannot* simply truncate all 383*b39c5158Smillert # file names to 14 characters on these systems because we *must* 384*b39c5158Smillert # create filenames which exactly match the names used by AutoLoader.pm. 385*b39c5158Smillert # This is a problem because some systems silently truncate the file 386*b39c5158Smillert # names while others treat long file names as an error. 387*b39c5158Smillert 388*b39c5158Smillert my $Is83 = $maxflen==11; # plain, case INSENSITIVE dos filenames 389*b39c5158Smillert 390*b39c5158Smillert my(@subnames, $subname, %proto, %package); 391*b39c5158Smillert my @cache = (); 392*b39c5158Smillert my $caching = 1; 393*b39c5158Smillert $last_package = ''; 394*b39c5158Smillert my $out; 395*b39c5158Smillert while (<$in>) { 396*b39c5158Smillert $fnr++; 397*b39c5158Smillert $in_pod = 1 if /^=\w/; 398*b39c5158Smillert $in_pod = 0 if /^=cut/; 399*b39c5158Smillert next if ($in_pod || /^=cut/); 400*b39c5158Smillert # the following (tempting) old coding gives big troubles if a 401*b39c5158Smillert # cut is forgotten at EOF: 402*b39c5158Smillert # next if /^=\w/ .. /^=cut/; 403*b39c5158Smillert if (/^package\s+([\w:]+)\s*;/) { 404*b39c5158Smillert $this_package = $def_package = $1; 405*b39c5158Smillert } 406*b39c5158Smillert 407*b39c5158Smillert if (/^sub\s+([\w:]+)(\s*(?:\(.*?\))?(?:$attr_list)?)/) { 408*b39c5158Smillert print $out "# end of $last_package\::$subname\n1;\n" 409*b39c5158Smillert if $last_package; 410*b39c5158Smillert $subname = $1; 411*b39c5158Smillert my $proto = $2 || ''; 412*b39c5158Smillert if ($subname =~ s/(.*):://){ 413*b39c5158Smillert $this_package = $1; 414*b39c5158Smillert } else { 415*b39c5158Smillert $this_package = $def_package; 416*b39c5158Smillert } 417*b39c5158Smillert my $fq_subname = "$this_package\::$subname"; 418*b39c5158Smillert $package{$fq_subname} = $this_package; 419*b39c5158Smillert $proto{$fq_subname} = $proto; 420*b39c5158Smillert push(@subnames, $fq_subname); 421*b39c5158Smillert my($lname, $sname) = ($subname, substr($subname,0,$maxflen-3)); 422*b39c5158Smillert $modpname = _modpname($this_package); 423*b39c5158Smillert my($modnamedir) = catdir($autodir, $modpname); 424*b39c5158Smillert mkpath($modnamedir,0,0777); 425*b39c5158Smillert my($lpath) = catfile($modnamedir, "$lname.al"); 426*b39c5158Smillert my($spath) = catfile($modnamedir, "$sname.al"); 427*b39c5158Smillert my $path; 428*b39c5158Smillert 429*b39c5158Smillert if (!$Is83 and open($out, ">$lpath")){ 430*b39c5158Smillert $path=$lpath; 431*b39c5158Smillert print " writing $lpath\n" if ($Verbose>=2); 432*b39c5158Smillert } else { 433*b39c5158Smillert open($out, ">$spath") or die "Can't create $spath: $!\n"; 434*b39c5158Smillert $path=$spath; 435*b39c5158Smillert print " writing $spath (with truncated name)\n" 436*b39c5158Smillert if ($Verbose>=1); 437*b39c5158Smillert } 438*b39c5158Smillert push(@outfiles, $path); 439*b39c5158Smillert my $lineno = $fnr - @cache; 440*b39c5158Smillert print $out <<EOT; 441*b39c5158Smillert# NOTE: Derived from $filename. 442*b39c5158Smillert# Changes made here will be lost when autosplit is run again. 443*b39c5158Smillert# See AutoSplit.pm. 444*b39c5158Smillertpackage $this_package; 445*b39c5158Smillert 446*b39c5158Smillert#line $lineno "$filename (autosplit into $path)" 447*b39c5158SmillertEOT 448*b39c5158Smillert print $out @cache; 449*b39c5158Smillert @cache = (); 450*b39c5158Smillert $caching = 0; 451*b39c5158Smillert } 452*b39c5158Smillert if($caching) { 453*b39c5158Smillert push(@cache, $_) if @cache || /\S/; 454*b39c5158Smillert } else { 455*b39c5158Smillert print $out $_; 456*b39c5158Smillert } 457*b39c5158Smillert if(/^\}/) { 458*b39c5158Smillert if($caching) { 459*b39c5158Smillert print $out @cache; 460*b39c5158Smillert @cache = (); 461*b39c5158Smillert } 462*b39c5158Smillert print $out "\n"; 463*b39c5158Smillert $caching = 1; 464*b39c5158Smillert } 465*b39c5158Smillert $last_package = $this_package if defined $this_package; 466*b39c5158Smillert } 467*b39c5158Smillert if ($subname) { 468*b39c5158Smillert print $out @cache,"1;\n# end of $last_package\::$subname\n"; 469*b39c5158Smillert close($out); 470*b39c5158Smillert } 471*b39c5158Smillert close($in); 472*b39c5158Smillert 473*b39c5158Smillert if (!$keep){ # don't keep any obsolete *.al files in the directory 474*b39c5158Smillert my(%outfiles); 475*b39c5158Smillert # @outfiles{@outfiles} = @outfiles; 476*b39c5158Smillert # perl downcases all filenames on VMS (which upcases all filenames) so 477*b39c5158Smillert # we'd better downcase the sub name list too, or subs with upper case 478*b39c5158Smillert # letters in them will get their .al files deleted right after they're 479*b39c5158Smillert # created. (The mixed case sub name won't match the all-lowercase 480*b39c5158Smillert # filename, and so be cleaned up as a scrap file) 481*b39c5158Smillert if ($Is_VMS or $Is83) { 482*b39c5158Smillert %outfiles = map {lc($_) => lc($_) } @outfiles; 483*b39c5158Smillert } else { 484*b39c5158Smillert @outfiles{@outfiles} = @outfiles; 485*b39c5158Smillert } 486*b39c5158Smillert my(%outdirs,@outdirs); 487*b39c5158Smillert for (@outfiles) { 488*b39c5158Smillert $outdirs{File::Basename::dirname($_)}||=1; 489*b39c5158Smillert } 490*b39c5158Smillert for my $dir (keys %outdirs) { 491*b39c5158Smillert opendir(my $outdir,$dir); 492*b39c5158Smillert foreach (sort readdir($outdir)){ 493*b39c5158Smillert next unless /\.al\z/; 494*b39c5158Smillert my($file) = catfile($dir, $_); 495*b39c5158Smillert $file = lc $file if $Is83 or $Is_VMS; 496*b39c5158Smillert next if $outfiles{$file}; 497*b39c5158Smillert print " deleting $file\n" if ($Verbose>=2); 498*b39c5158Smillert my($deleted,$thistime); # catch all versions on VMS 499*b39c5158Smillert do { $deleted += ($thistime = unlink $file) } while ($thistime); 500*b39c5158Smillert carp ("Unable to delete $file: $!") unless $deleted; 501*b39c5158Smillert } 502*b39c5158Smillert closedir($outdir); 503*b39c5158Smillert } 504*b39c5158Smillert } 505*b39c5158Smillert 506*b39c5158Smillert open(my $ts,">$al_idx_file") or 507*b39c5158Smillert carp ("AutoSplit: unable to create timestamp file ($al_idx_file): $!"); 508*b39c5158Smillert print $ts "# Index created by AutoSplit for $filename\n"; 509*b39c5158Smillert print $ts "# (file acts as timestamp)\n"; 510*b39c5158Smillert $last_package = ''; 511*b39c5158Smillert for my $fqs (@subnames) { 512*b39c5158Smillert my($subname) = $fqs; 513*b39c5158Smillert $subname =~ s/.*:://; 514*b39c5158Smillert print $ts "package $package{$fqs};\n" 515*b39c5158Smillert unless $last_package eq $package{$fqs}; 516*b39c5158Smillert print $ts "sub $subname $proto{$fqs};\n"; 517*b39c5158Smillert $last_package = $package{$fqs}; 518*b39c5158Smillert } 519*b39c5158Smillert print $ts "1;\n"; 520*b39c5158Smillert close($ts); 521*b39c5158Smillert 522*b39c5158Smillert _check_unique($filename, $Maxlen, 1, @outfiles); 523*b39c5158Smillert 524*b39c5158Smillert @outfiles; 525*b39c5158Smillert} 526*b39c5158Smillert 527*b39c5158Smillertsub _modpname ($) { 528*b39c5158Smillert my($package) = @_; 529*b39c5158Smillert my $modpname = $package; 530*b39c5158Smillert if ($^O eq 'MSWin32') { 531*b39c5158Smillert $modpname =~ s#::#\\#g; 532*b39c5158Smillert } else { 533*b39c5158Smillert my @modpnames = (); 534*b39c5158Smillert while ($modpname =~ m#(.*?[^:])::([^:].*)#) { 535*b39c5158Smillert push @modpnames, $1; 536*b39c5158Smillert $modpname = $2; 537*b39c5158Smillert } 538*b39c5158Smillert $modpname = catfile(@modpnames, $modpname); 539*b39c5158Smillert } 540*b39c5158Smillert if ($Is_VMS) { 541*b39c5158Smillert $modpname = VMS::Filespec::unixify($modpname); # may have dirs 542*b39c5158Smillert } 543*b39c5158Smillert $modpname; 544*b39c5158Smillert} 545*b39c5158Smillert 546*b39c5158Smillertsub _check_unique { 547*b39c5158Smillert my($filename, $maxlen, $warn, @outfiles) = @_; 548*b39c5158Smillert my(%notuniq) = (); 549*b39c5158Smillert my(%shorts) = (); 550*b39c5158Smillert my(@toolong) = grep( 551*b39c5158Smillert length(File::Basename::basename($_)) 552*b39c5158Smillert > $maxlen, 553*b39c5158Smillert @outfiles 554*b39c5158Smillert ); 555*b39c5158Smillert 556*b39c5158Smillert foreach (@toolong){ 557*b39c5158Smillert my($dir) = File::Basename::dirname($_); 558*b39c5158Smillert my($file) = File::Basename::basename($_); 559*b39c5158Smillert my($trunc) = substr($file,0,$maxlen); 560*b39c5158Smillert $notuniq{$dir}{$trunc} = 1 if $shorts{$dir}{$trunc}; 561*b39c5158Smillert $shorts{$dir}{$trunc} = $shorts{$dir}{$trunc} ? 562*b39c5158Smillert "$shorts{$dir}{$trunc}, $file" : $file; 563*b39c5158Smillert } 564*b39c5158Smillert if (%notuniq && $warn){ 565*b39c5158Smillert print "$filename: some names are not unique when " . 566*b39c5158Smillert "truncated to $maxlen characters:\n"; 567*b39c5158Smillert foreach my $dir (sort keys %notuniq){ 568*b39c5158Smillert print " directory $dir:\n"; 569*b39c5158Smillert foreach my $trunc (sort keys %{$notuniq{$dir}}) { 570*b39c5158Smillert print " $shorts{$dir}{$trunc} truncate to $trunc\n"; 571*b39c5158Smillert } 572*b39c5158Smillert } 573*b39c5158Smillert } 574*b39c5158Smillert} 575*b39c5158Smillert 576*b39c5158Smillert1; 577*b39c5158Smillert__END__ 578*b39c5158Smillert 579*b39c5158Smillert# test functions so AutoSplit.pm can be applied to itself: 580*b39c5158Smillertsub test1 ($) { "test 1\n"; } 581*b39c5158Smillertsub test2 ($$) { "test 2\n"; } 582*b39c5158Smillertsub test3 ($$$) { "test 3\n"; } 583*b39c5158Smillertsub testtesttesttest4_1 { "test 4\n"; } 584*b39c5158Smillertsub testtesttesttest4_2 { "duplicate test 4\n"; } 585*b39c5158Smillertsub Just::Another::test5 { "another test 5\n"; } 586*b39c5158Smillertsub test6 { return join ":", __FILE__,__LINE__; } 587*b39c5158Smillertpackage Yet::Another::AutoSplit; 588*b39c5158Smillertsub testtesttesttest4_1 ($) { "another test 4\n"; } 589*b39c5158Smillertsub testtesttesttest4_2 ($$) { "another duplicate test 4\n"; } 590*b39c5158Smillertpackage Yet::More::Attributes; 591*b39c5158Smillertsub test_a1 ($) : locked :locked { 1; } 592*b39c5158Smillertsub test_a2 : locked { 1; } 593