xref: /openbsd-src/gnu/usr.bin/perl/cpan/AutoLoader/lib/AutoSplit.pm (revision b39c515898423c8d899e35282f4b395f7cad3298)
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