ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/staticperl/perl/lib/ExtUtils/MM_VMS.pm
Revision: 1.1
Committed: Thu Jun 30 14:27:11 2005 UTC (21 years, 4 months ago) by root
Branch: MAIN
CVS Tags: HEAD
Branch point for: PERL
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.1 # MM_VMS.pm
2     # MakeMaker default methods for VMS
3     #
4     # Author: Charles Bailey bailey@newman.upenn.edu
5    
6     package ExtUtils::MM_VMS;
7    
8     use strict;
9    
10     use Config;
11     require Exporter;
12    
13     BEGIN {
14     # so we can compile the thing on non-VMS platforms.
15     if( $^O eq 'VMS' ) {
16     require VMS::Filespec;
17     VMS::Filespec->import;
18     }
19     }
20    
21     use File::Basename;
22     use vars qw($Revision @ISA $VERSION);
23     ($VERSION) = '5.70';
24     ($Revision) = q$Revision: 1.110 $ =~ /Revision:\s+(\S+)/;
25    
26     require ExtUtils::MM_Any;
27     require ExtUtils::MM_Unix;
28     @ISA = qw( ExtUtils::MM_Any ExtUtils::MM_Unix );
29    
30     use ExtUtils::MakeMaker qw($Verbose neatvalue);
31    
32    
33     =head1 NAME
34    
35     ExtUtils::MM_VMS - methods to override UN*X behaviour in ExtUtils::MakeMaker
36    
37     =head1 SYNOPSIS
38    
39     Do not use this directly.
40     Instead, use ExtUtils::MM and it will figure out which MM_*
41     class to use for you.
42    
43     =head1 DESCRIPTION
44    
45     See ExtUtils::MM_Unix for a documentation of the methods provided
46     there. This package overrides the implementation of these methods, not
47     the semantics.
48    
49     =head2 Methods always loaded
50    
51     =over 4
52    
53     =item wraplist
54    
55     Converts a list into a string wrapped at approximately 80 columns.
56    
57     =cut
58    
59     sub wraplist {
60     my($self) = shift;
61     my($line,$hlen) = ('',0);
62    
63     foreach my $word (@_) {
64     # Perl bug -- seems to occasionally insert extra elements when
65     # traversing array (scalar(@array) doesn't show them, but
66     # foreach(@array) does) (5.00307)
67     next unless $word =~ /\w/;
68     $line .= ' ' if length($line);
69     if ($hlen > 80) { $line .= "\\\n\t"; $hlen = 0; }
70     $line .= $word;
71     $hlen += length($word) + 2;
72     }
73     $line;
74     }
75    
76    
77     # This isn't really an override. It's just here because ExtUtils::MM_VMS
78     # appears in @MM::ISA before ExtUtils::Liblist::Kid, so if there isn't an ext()
79     # in MM_VMS, then AUTOLOAD is called, and bad things happen. So, we just
80     # mimic inheritance here and hand off to ExtUtils::Liblist::Kid.
81     # XXX This hackery will die soon. --Schwern
82     sub ext {
83     require ExtUtils::Liblist::Kid;
84     goto &ExtUtils::Liblist::Kid::ext;
85     }
86    
87     =back
88    
89     =head2 Methods
90    
91     Those methods which override default MM_Unix methods are marked
92     "(override)", while methods unique to MM_VMS are marked "(specific)".
93     For overridden methods, documentation is limited to an explanation
94     of why this method overrides the MM_Unix method; see the ExtUtils::MM_Unix
95     documentation for more details.
96    
97     =over 4
98    
99     =item guess_name (override)
100    
101     Try to determine name of extension being built. We begin with the name
102     of the current directory. Since VMS filenames are case-insensitive,
103     however, we look for a F<.pm> file whose name matches that of the current
104     directory (presumably the 'main' F<.pm> file for this extension), and try
105     to find a C<package> statement from which to obtain the Mixed::Case
106     package name.
107    
108     =cut
109    
110     sub guess_name {
111     my($self) = @_;
112     my($defname,$defpm,@pm,%xs,$pm);
113     local *PM;
114    
115     $defname = basename(fileify($ENV{'DEFAULT'}));
116     $defname =~ s![\d\-_]*\.dir.*$!!; # Clip off .dir;1 suffix, and package version
117     $defpm = $defname;
118     # Fallback in case for some reason a user has copied the files for an
119     # extension into a working directory whose name doesn't reflect the
120     # extension's name. We'll use the name of a unique .pm file, or the
121     # first .pm file with a matching .xs file.
122     if (not -e "${defpm}.pm") {
123     @pm = map { s/.pm$//; $_ } glob('*.pm');
124     if (@pm == 1) { ($defpm = $pm[0]) =~ s/.pm$//; }
125     elsif (@pm) {
126     %xs = map { s/.xs$//; ($_,1) } glob('*.xs');
127     if (keys %xs) {
128     foreach $pm (@pm) {
129     $defpm = $pm, last if exists $xs{$pm};
130     }
131     }
132     }
133     }
134     if (open(PM,"${defpm}.pm")){
135     while (<PM>) {
136     if (/^\s*package\s+([^;]+)/i) {
137     $defname = $1;
138     last;
139     }
140     }
141     print STDOUT "Warning (non-fatal): Couldn't find package name in ${defpm}.pm;\n\t",
142     "defaulting package name to $defname\n"
143     if eof(PM);
144     close PM;
145     }
146     else {
147     print STDOUT "Warning (non-fatal): Couldn't find ${defpm}.pm;\n\t",
148     "defaulting package name to $defname\n";
149     }
150     $defname =~ s#[\d.\-_]+$##;
151     $defname;
152     }
153    
154     =item find_perl (override)
155    
156     Use VMS file specification syntax and CLI commands to find and
157     invoke Perl images.
158    
159     =cut
160    
161     sub find_perl {
162     my($self, $ver, $names, $dirs, $trace) = @_;
163     my($name,$dir,$vmsfile,@sdirs,@snames,@cand);
164     my($rslt);
165     my($inabs) = 0;
166     local *TCF;
167    
168     if( $self->{PERL_CORE} ) {
169     # Check in relative directories first, so we pick up the current
170     # version of Perl if we're running MakeMaker as part of the main build.
171     @sdirs = sort { my($absa) = $self->file_name_is_absolute($a);
172     my($absb) = $self->file_name_is_absolute($b);
173     if ($absa && $absb) { return $a cmp $b }
174     else { return $absa ? 1 : ($absb ? -1 : ($a cmp $b)); }
175     } @$dirs;
176     # Check miniperl before perl, and check names likely to contain
177     # version numbers before "generic" names, so we pick up an
178     # executable that's less likely to be from an old installation.
179     @snames = sort { my($ba) = $a =~ m!([^:>\]/]+)$!; # basename
180     my($bb) = $b =~ m!([^:>\]/]+)$!;
181     my($ahasdir) = (length($a) - length($ba) > 0);
182     my($bhasdir) = (length($b) - length($bb) > 0);
183     if ($ahasdir and not $bhasdir) { return 1; }
184     elsif ($bhasdir and not $ahasdir) { return -1; }
185     else { $bb =~ /\d/ <=> $ba =~ /\d/
186     or substr($ba,0,1) cmp substr($bb,0,1)
187     or length($bb) <=> length($ba) } } @$names;
188     }
189     else {
190     @sdirs = @$dirs;
191     @snames = @$names;
192     }
193    
194     # Image names containing Perl version use '_' instead of '.' under VMS
195     foreach $name (@snames) { $name =~ s/\.(\d+)$/_$1/; }
196     if ($trace >= 2){
197     print "Looking for perl $ver by these names:\n";
198     print "\t@snames,\n";
199     print "in these dirs:\n";
200     print "\t@sdirs\n";
201     }
202     foreach $dir (@sdirs){
203     next unless defined $dir; # $self->{PERL_SRC} may be undefined
204     $inabs++ if $self->file_name_is_absolute($dir);
205     if ($inabs == 1) {
206     # We've covered relative dirs; everything else is an absolute
207     # dir (probably an installed location). First, we'll try potential
208     # command names, to see whether we can avoid a long MCR expression.
209     foreach $name (@snames) { push(@cand,$name) if $name =~ /^[\w\-\$]+$/; }
210     $inabs++; # Should happen above in next $dir, but just in case . . .
211     }
212     foreach $name (@snames){
213     if ($name !~ m![/:>\]]!) { push(@cand,$self->catfile($dir,$name)); }
214     else { push(@cand,$self->fixpath($name,0)); }
215     }
216     }
217     foreach $name (@cand) {
218     print "Checking $name\n" if ($trace >= 2);
219     # If it looks like a potential command, try it without the MCR
220     if ($name =~ /^[\w\-\$]+$/) {
221     open(TCF,">temp_mmvms.com") || die('unable to open temp file');
222     print TCF "\$ set message/nofacil/nosever/noident/notext\n";
223     print TCF "\$ $name -e \"require $ver; print \"\"VER_OK\\n\"\"\"\n";
224     close TCF;
225     $rslt = `\@temp_mmvms.com` ;
226     unlink('temp_mmvms.com');
227     if ($rslt =~ /VER_OK/) {
228     print "Using PERL=$name\n" if $trace;
229     return $name;
230     }
231     }
232     next unless $vmsfile = $self->maybe_command($name);
233     $vmsfile =~ s/;[\d\-]*$//; # Clip off version number; we can use a newer version as well
234     print "Executing $vmsfile\n" if ($trace >= 2);
235     open(TCF,">temp_mmvms.com") || die('unable to open temp file');
236     print TCF "\$ set message/nofacil/nosever/noident/notext\n";
237     print TCF "\$ mcr $vmsfile -e \"require $ver; print \"\"VER_OK\\n\"\"\" \n";
238     close TCF;
239     $rslt = `\@temp_mmvms.com`;
240     unlink('temp_mmvms.com');
241     if ($rslt =~ /VER_OK/) {
242     print "Using PERL=MCR $vmsfile\n" if $trace;
243     return "MCR $vmsfile";
244     }
245     }
246     print STDOUT "Unable to find a perl $ver (by these names: @$names, in these dirs: @$dirs)\n";
247     0; # false and not empty
248     }
249    
250     =item maybe_command (override)
251    
252     Follows VMS naming conventions for executable files.
253     If the name passed in doesn't exactly match an executable file,
254     appends F<.Exe> (or equivalent) to check for executable image, and F<.Com>
255     to check for DCL procedure. If this fails, checks directories in DCL$PATH
256     and finally F<Sys$System:> for an executable file having the name specified,
257     with or without the F<.Exe>-equivalent suffix.
258    
259     =cut
260    
261     sub maybe_command {
262     my($self,$file) = @_;
263     return $file if -x $file && ! -d _;
264     my(@dirs) = ('');
265     my(@exts) = ('',$Config{'exe_ext'},'.exe','.com');
266     my($dir,$ext);
267     if ($file !~ m![/:>\]]!) {
268     for (my $i = 0; defined $ENV{"DCL\$PATH;$i"}; $i++) {
269     $dir = $ENV{"DCL\$PATH;$i"};
270     $dir .= ':' unless $dir =~ m%[\]:]$%;
271     push(@dirs,$dir);
272     }
273     push(@dirs,'Sys$System:');
274     foreach $dir (@dirs) {
275     my $sysfile = "$dir$file";
276     foreach $ext (@exts) {
277     return $file if -x "$sysfile$ext" && ! -d _;
278     }
279     }
280     }
281     return 0;
282     }
283    
284     =item perl_script (override)
285    
286     If name passed in doesn't specify a readable file, appends F<.com> or
287     F<.pl> and tries again, since it's customary to have file types on all files
288     under VMS.
289    
290     =cut
291    
292     sub perl_script {
293     my($self,$file) = @_;
294     return $file if -r $file && ! -d _;
295     return "$file.com" if -r "$file.com";
296     return "$file.pl" if -r "$file.pl";
297     return '';
298     }
299    
300     =item replace_manpage_separator
301    
302     Use as separator a character which is legal in a VMS-syntax file name.
303    
304     =cut
305    
306     sub replace_manpage_separator {
307     my($self,$man) = @_;
308     $man = unixify($man);
309     $man =~ s#/+#__#g;
310     $man;
311     }
312    
313     =item init_DEST
314    
315     (override) Because of the difficulty concatenating VMS filepaths we
316     must pre-expand the DEST* variables.
317    
318     =cut
319    
320     sub init_DEST {
321     my $self = shift;
322    
323     $self->SUPER::init_DEST;
324    
325     # Expand DEST variables.
326     foreach my $var ($self->installvars) {
327     my $destvar = 'DESTINSTALL'.$var;
328     $self->{$destvar} = File::Spec->eliminate_macros($self->{$destvar});
329     }
330     }
331    
332    
333     =item init_DIRFILESEP
334    
335     No seperator between a directory path and a filename on VMS.
336    
337     =cut
338    
339     sub init_DIRFILESEP {
340     my($self) = shift;
341    
342     $self->{DIRFILESEP} = '';
343     return 1;
344     }
345    
346    
347     =item init_main (override)
348    
349    
350     =cut
351    
352     sub init_main {
353     my($self) = shift;
354    
355     $self->SUPER::init_main;
356    
357     $self->{DEFINE} ||= '';
358     if ($self->{DEFINE} ne '') {
359     my(@terms) = split(/\s+/,$self->{DEFINE});
360     my(@defs,@udefs);
361     foreach my $def (@terms) {
362     next unless $def;
363     my $targ = \@defs;
364     if ($def =~ s/^-([DU])//) { # If it was a Unix-style definition
365     $targ = \@udefs if $1 eq 'U';
366     $def =~ s/='(.*)'$/=$1/; # then remove shell-protection ''
367     $def =~ s/^'(.*)'$/$1/; # from entire term or argument
368     }
369     if ($def =~ /=/) {
370     $def =~ s/"/""/g; # Protect existing " from DCL
371     $def = qq["$def"]; # and quote to prevent parsing of =
372     }
373     push @$targ, $def;
374     }
375    
376     $self->{DEFINE} = '';
377     if (@defs) {
378     $self->{DEFINE} = '/Define=(' . join(',',@defs) . ')';
379     }
380     if (@udefs) {
381     $self->{DEFINE} .= '/Undef=(' . join(',',@udefs) . ')';
382     }
383     }
384     }
385    
386     =item init_others (override)
387    
388     Provide VMS-specific forms of various utility commands, then hand
389     off to the default MM_Unix method.
390    
391     DEV_NULL should probably be overriden with something.
392    
393     Also changes EQUALIZE_TIMESTAMP to set revision date of target file to
394     one second later than source file, since MMK interprets precisely
395     equal revision dates for a source and target file as a sign that the
396     target needs to be updated.
397    
398     =cut
399    
400     sub init_others {
401     my($self) = @_;
402    
403     $self->{NOOP} = 'Continue';
404     $self->{NOECHO} ||= '@ ';
405    
406     $self->{MAKEFILE} ||= 'Descrip.MMS';
407     $self->{FIRST_MAKEFILE} ||= $self->{MAKEFILE};
408     $self->{MAKE_APERL_FILE} ||= 'Makeaperl.MMS';
409     $self->{MAKEFILE_OLD} ||= '$(FIRST_MAKEFILE)_old';
410    
411     $self->{ECHO} ||= '$(PERLRUN) -le "print qq{@ARGV}"';
412     $self->{ECHO_N} ||= '$(PERLRUN) -e "print qq{@ARGV}"';
413     $self->{TOUCH} ||= '$(PERLRUN) "-MExtUtils::Command" -e touch';
414     $self->{CHMOD} ||= '$(PERLRUN) "-MExtUtils::Command" -e chmod';
415     $self->{RM_F} ||= '$(PERLRUN) "-MExtUtils::Command" -e rm_f';
416     $self->{RM_RF} ||= '$(PERLRUN) "-MExtUtils::Command" -e rm_rf';
417     $self->{TEST_F} ||= '$(PERLRUN) "-MExtUtils::Command" -e test_f';
418     $self->{EQUALIZE_TIMESTAMP} ||= '$(PERLRUN) -we "open F,qq{>>$ARGV[1]};close F;utime(0,(stat($ARGV[0]))[9]+1,$ARGV[1])"';
419    
420     $self->{MOD_INSTALL} ||=
421     $self->oneliner(<<'CODE', ['-MExtUtils::Install']);
422     install({split(' ',<STDIN>)}, '$(VERBINST)', 0, '$(UNINST)');
423     CODE
424    
425     $self->{SHELL} ||= 'Posix';
426    
427     $self->{CP} = 'Copy/NoConfirm';
428     $self->{MV} = 'Rename/NoConfirm';
429     $self->{UMASK_NULL} = '! ';
430    
431     $self->SUPER::init_others;
432    
433     if ($self->{OBJECT} =~ /\s/) {
434     $self->{OBJECT} =~ s/(\\)?\n+\s+/ /g;
435     $self->{OBJECT} = $self->wraplist(
436     map $self->fixpath($_,0), split /,?\s+/, $self->{OBJECT}
437     );
438     }
439    
440     $self->{LDFROM} = $self->wraplist(
441     map $self->fixpath($_,0), split /,?\s+/, $self->{LDFROM}
442     );
443     }
444    
445    
446     =item init_platform (override)
447    
448     Add PERL_VMS, MM_VMS_REVISION and MM_VMS_VERSION.
449    
450     MM_VMS_REVISION is for backwards compatibility before MM_VMS had a
451     $VERSION.
452    
453     =cut
454    
455     sub init_platform {
456     my($self) = shift;
457    
458     $self->{MM_VMS_REVISION} = $Revision;
459     $self->{MM_VMS_VERSION} = $VERSION;
460     $self->{PERL_VMS} = $self->catdir($self->{PERL_SRC}, 'VMS')
461     if $self->{PERL_SRC};
462     }
463    
464    
465     =item platform_constants
466    
467     =cut
468    
469     sub platform_constants {
470     my($self) = shift;
471     my $make_frag = '';
472    
473     foreach my $macro (qw(PERL_VMS MM_VMS_REVISION MM_VMS_VERSION))
474     {
475     next unless defined $self->{$macro};
476     $make_frag .= "$macro = $self->{$macro}\n";
477     }
478    
479     return $make_frag;
480     }
481    
482    
483     =item init_VERSION (override)
484    
485     Override the *DEFINE_VERSION macros with VMS semantics. Translate the
486     MAKEMAKER filepath to VMS style.
487    
488     =cut
489    
490     sub init_VERSION {
491     my $self = shift;
492    
493     $self->SUPER::init_VERSION;
494    
495     $self->{DEFINE_VERSION} = '"$(VERSION_MACRO)=""$(VERSION)"""';
496     $self->{XS_DEFINE_VERSION} = '"$(XS_VERSION_MACRO)=""$(XS_VERSION)"""';
497     $self->{MAKEMAKER} = vmsify($INC{'ExtUtils/MakeMaker.pm'});
498     }
499    
500    
501     =item constants (override)
502    
503     Fixes up numerous file and directory macros to insure VMS syntax
504     regardless of input syntax. Also makes lists of files
505     comma-separated.
506    
507     =cut
508    
509     sub constants {
510     my($self) = @_;
511    
512     # Be kind about case for pollution
513     for (@ARGV) { $_ = uc($_) if /POLLUTE/i; }
514    
515     # Cleanup paths for directories in MMS macros.
516     foreach my $macro ( qw [
517     INST_BIN INST_SCRIPT INST_LIB INST_ARCHLIB
518     PERL_LIB PERL_ARCHLIB
519     PERL_INC PERL_SRC ],
520     (map { 'INSTALL'.$_ } $self->installvars)
521     )
522     {
523     next unless defined $self->{$macro};
524     next if $macro =~ /MAN/ && $self->{$macro} eq 'none';
525     $self->{$macro} = $self->fixpath($self->{$macro},1);
526     }
527    
528     # Cleanup paths for files in MMS macros.
529     foreach my $macro ( qw[LIBPERL_A FIRST_MAKEFILE MAKEFILE_OLD
530     MAKE_APERL_FILE MYEXTLIB] )
531     {
532     next unless defined $self->{$macro};
533     $self->{$macro} = $self->fixpath($self->{$macro},0);
534     }
535    
536     # Fixup files for MMS macros
537     # XXX is this list complete?
538     for my $macro (qw/
539     FULLEXT VERSION_FROM OBJECT LDFROM
540     / ) {
541     next unless defined $self->{$macro};
542     $self->{$macro} = $self->fixpath($self->{$macro},0);
543     }
544    
545    
546     for my $macro (qw/ XS MAN1PODS MAN3PODS PM /) {
547     # Where is the space coming from? --jhi
548     next unless $self ne " " && defined $self->{$macro};
549     my %tmp = ();
550     for my $key (keys %{$self->{$macro}}) {
551     $tmp{$self->fixpath($key,0)} =
552     $self->fixpath($self->{$macro}{$key},0);
553     }
554     $self->{$macro} = \%tmp;
555     }
556    
557     for my $macro (qw/ C O_FILES H /) {
558     next unless defined $self->{$macro};
559     my @tmp = ();
560     for my $val (@{$self->{$macro}}) {
561     push(@tmp,$self->fixpath($val,0));
562     }
563     $self->{$macro} = \@tmp;
564     }
565    
566     return $self->SUPER::constants;
567     }
568    
569    
570     =item special_targets
571    
572     Clear the default .SUFFIXES and put in our own list.
573    
574     =cut
575    
576     sub special_targets {
577     my $self = shift;
578    
579     my $make_frag .= <<'MAKE_FRAG';
580     .SUFFIXES :
581     .SUFFIXES : $(OBJ_EXT) .c .cpp .cxx .xs
582    
583     MAKE_FRAG
584    
585     return $make_frag;
586     }
587    
588     =item cflags (override)
589    
590     Bypass shell script and produce qualifiers for CC directly (but warn
591     user if a shell script for this extension exists). Fold multiple
592     /Defines into one, since some C compilers pay attention to only one
593     instance of this qualifier on the command line.
594    
595     =cut
596    
597     sub cflags {
598     my($self,$libperl) = @_;
599     my($quals) = $self->{CCFLAGS} || $Config{'ccflags'};
600     my($definestr,$undefstr,$flagoptstr) = ('','','');
601     my($incstr) = '/Include=($(PERL_INC)';
602     my($name,$sys,@m);
603    
604     ( $name = $self->{NAME} . "_cflags" ) =~ s/:/_/g ;
605     print STDOUT "Unix shell script ".$Config{"$self->{'BASEEXT'}_cflags"}.
606     " required to modify CC command for $self->{'BASEEXT'}\n"
607     if ($Config{$name});
608    
609     if ($quals =~ / -[DIUOg]/) {
610     while ($quals =~ / -([Og])(\d*)\b/) {
611     my($type,$lvl) = ($1,$2);
612     $quals =~ s/ -$type$lvl\b\s*//;
613     if ($type eq 'g') { $flagoptstr = '/NoOptimize'; }
614     else { $flagoptstr = '/Optimize' . (defined($lvl) ? "=$lvl" : ''); }
615     }
616     while ($quals =~ / -([DIU])(\S+)/) {
617     my($type,$def) = ($1,$2);
618     $quals =~ s/ -$type$def\s*//;
619     $def =~ s/"/""/g;
620     if ($type eq 'D') { $definestr .= qq["$def",]; }
621     elsif ($type eq 'I') { $incstr .= ',' . $self->fixpath($def,1); }
622     else { $undefstr .= qq["$def",]; }
623     }
624     }
625     if (length $quals and $quals !~ m!/!) {
626     warn "MM_VMS: Ignoring unrecognized CCFLAGS elements \"$quals\"\n";
627     $quals = '';
628     }
629     $definestr .= q["PERL_POLLUTE",] if $self->{POLLUTE};
630     if (length $definestr) { chop($definestr); $quals .= "/Define=($definestr)"; }
631     if (length $undefstr) { chop($undefstr); $quals .= "/Undef=($undefstr)"; }
632     # Deal with $self->{DEFINE} here since some C compilers pay attention
633     # to only one /Define clause on command line, so we have to
634     # conflate the ones from $Config{'ccflags'} and $self->{DEFINE}
635     # ($self->{DEFINE} has already been VMSified in constants() above)
636     if ($self->{DEFINE}) { $quals .= $self->{DEFINE}; }
637     for my $type (qw(Def Undef)) {
638     my(@terms);
639     while ($quals =~ m:/${type}i?n?e?=([^/]+):ig) {
640     my $term = $1;
641     $term =~ s:^\((.+)\)$:$1:;
642     push @terms, $term;
643     }
644     if ($type eq 'Def') {
645     push @terms, qw[ $(DEFINE_VERSION) $(XS_DEFINE_VERSION) ];
646     }
647     if (@terms) {
648     $quals =~ s:/${type}i?n?e?=[^/]+::ig;
649     $quals .= "/${type}ine=(" . join(',',@terms) . ')';
650     }
651     }
652    
653     $libperl or $libperl = $self->{LIBPERL_A} || "libperl.olb";
654    
655     # Likewise with $self->{INC} and /Include
656     if ($self->{'INC'}) {
657     my(@includes) = split(/\s+/,$self->{INC});
658     foreach (@includes) {
659     s/^-I//;
660     $incstr .= ','.$self->fixpath($_,1);
661     }
662     }
663     $quals .= "$incstr)";
664     # $quals =~ s/,,/,/g; $quals =~ s/\(,/(/g;
665     $self->{CCFLAGS} = $quals;
666    
667     $self->{PERLTYPE} ||= '';
668    
669     $self->{OPTIMIZE} ||= $flagoptstr || $Config{'optimize'};
670     if ($self->{OPTIMIZE} !~ m!/!) {
671     if ($self->{OPTIMIZE} =~ m!-g!) { $self->{OPTIMIZE} = '/Debug/NoOptimize' }
672     elsif ($self->{OPTIMIZE} =~ /-O(\d*)/) {
673     $self->{OPTIMIZE} = '/Optimize' . (defined($1) ? "=$1" : '');
674     }
675     else {
676     warn "MM_VMS: Can't parse OPTIMIZE \"$self->{OPTIMIZE}\"; using default\n" if length $self->{OPTIMIZE};
677     $self->{OPTIMIZE} = '/Optimize';
678     }
679     }
680    
681     return $self->{CFLAGS} = qq{
682     CCFLAGS = $self->{CCFLAGS}
683     OPTIMIZE = $self->{OPTIMIZE}
684     PERLTYPE = $self->{PERLTYPE}
685     };
686     }
687    
688     =item const_cccmd (override)
689    
690     Adds directives to point C preprocessor to the right place when
691     handling #include E<lt>sys/foo.hE<gt> directives. Also constructs CC
692     command line a bit differently than MM_Unix method.
693    
694     =cut
695    
696     sub const_cccmd {
697     my($self,$libperl) = @_;
698     my(@m);
699    
700     return $self->{CONST_CCCMD} if $self->{CONST_CCCMD};
701     return '' unless $self->needs_linking();
702     if ($Config{'vms_cc_type'} eq 'gcc') {
703     push @m,'
704     .FIRST
705     ',$self->{NOECHO},'If F$TrnLnm("Sys").eqs."" Then Define/NoLog SYS GNU_CC_Include:[VMS]';
706     }
707     elsif ($Config{'vms_cc_type'} eq 'vaxc') {
708     push @m,'
709     .FIRST
710     ',$self->{NOECHO},'If F$TrnLnm("Sys").eqs."" .and. F$TrnLnm("VAXC$Include").eqs."" Then Define/NoLog SYS Sys$Library
711     ',$self->{NOECHO},'If F$TrnLnm("Sys").eqs."" .and. F$TrnLnm("VAXC$Include").nes."" Then Define/NoLog SYS VAXC$Include';
712     }
713     else {
714     push @m,'
715     .FIRST
716     ',$self->{NOECHO},'If F$TrnLnm("Sys").eqs."" .and. F$TrnLnm("DECC$System_Include").eqs."" Then Define/NoLog SYS ',
717     ($Config{'archname'} eq 'VMS_AXP' ? 'Sys$Library' : 'DECC$Library_Include'),'
718     ',$self->{NOECHO},'If F$TrnLnm("Sys").eqs."" .and. F$TrnLnm("DECC$System_Include").nes."" Then Define/NoLog SYS DECC$System_Include';
719     }
720    
721     push(@m, "\n\nCCCMD = $Config{'cc'} \$(CCFLAGS)\$(OPTIMIZE)\n");
722    
723     $self->{CONST_CCCMD} = join('',@m);
724     }
725    
726    
727     =item tool_sxubpp (override)
728    
729     Use VMS-style quoting on xsubpp command line.
730    
731     =cut
732    
733     sub tool_xsubpp {
734     my($self) = @_;
735     return '' unless $self->needs_linking;
736    
737     my $xsdir;
738     foreach my $dir (@INC) {
739     $xsdir = $self->catdir($dir, 'ExtUtils');
740     if( -r $self->catfile($xsdir, "xsubpp") ) {
741     last;
742     }
743     }
744    
745     my $tmdir = File::Spec->catdir($self->{PERL_LIB},"ExtUtils");
746     my(@tmdeps) = $self->catfile($tmdir,'typemap');
747     if( $self->{TYPEMAPS} ){
748     my $typemap;
749     foreach $typemap (@{$self->{TYPEMAPS}}){
750     if( ! -f $typemap ){
751     warn "Typemap $typemap not found.\n";
752     }
753     else{
754     push(@tmdeps, $self->fixpath($typemap,0));
755     }
756     }
757     }
758     push(@tmdeps, "typemap") if -f "typemap";
759     my(@tmargs) = map("-typemap $_", @tmdeps);
760     if( exists $self->{XSOPT} ){
761     unshift( @tmargs, $self->{XSOPT} );
762     }
763    
764     if ($Config{'ldflags'} &&
765     $Config{'ldflags'} =~ m!/Debug!i &&
766     (!exists($self->{XSOPT}) || $self->{XSOPT} !~ /linenumbers/)) {
767     unshift(@tmargs,'-nolinenumbers');
768     }
769    
770    
771     $self->{XSPROTOARG} = '' unless defined $self->{XSPROTOARG};
772    
773     return "
774     XSUBPPDIR = $xsdir
775     XSUBPP = \$(PERLRUN) \$(XSUBPPDIR)xsubpp
776     XSPROTOARG = $self->{XSPROTOARG}
777     XSUBPPDEPS = @tmdeps
778     XSUBPPARGS = @tmargs
779     ";
780     }
781    
782    
783     =item tools_other (override)
784    
785     Throw in some dubious extra macros for Makefile args.
786    
787     Also keep around the old $(SAY) macro in case somebody's using it.
788    
789     =cut
790    
791     sub tools_other {
792     my($self) = @_;
793    
794     # XXX Are these necessary? Does anyone override them? They're longer
795     # than just typing the literal string.
796     my $extra_tools = <<'EXTRA_TOOLS';
797    
798     # Assumes $(MMS) invokes MMS or MMK
799     # (It is assumed in some cases later that the default makefile name
800     # (Descrip.MMS for MM[SK]) is used.)
801     USEMAKEFILE = /Descrip=
802     USEMACROS = /Macro=(
803     MACROEND = )
804    
805     # Just in case anyone is using the old macro.
806     SAY = $(ECHO)
807    
808     EXTRA_TOOLS
809    
810     return $self->SUPER::tools_other . $extra_tools;
811     }
812    
813     =item init_dist (override)
814    
815     VMSish defaults for some values.
816    
817     macro description default
818    
819     ZIPFLAGS flags to pass to ZIP -Vu
820    
821     COMPRESS compression command to gzip
822     use for tarfiles
823     SUFFIX suffix to put on -gz
824     compressed files
825    
826     SHAR shar command to use vms_share
827    
828     DIST_DEFAULT default target to use to tardist
829     create a distribution
830    
831     DISTVNAME Use VERSION_SYM instead of $(DISTNAME)-$(VERSION_SYM)
832     VERSION for the name
833    
834     =cut
835    
836     sub init_dist {
837     my($self) = @_;
838     $self->{ZIPFLAGS} ||= '-Vu';
839     $self->{COMPRESS} ||= 'gzip';
840     $self->{SUFFIX} ||= '-gz';
841     $self->{SHAR} ||= 'vms_share';
842     $self->{DIST_DEFAULT} ||= 'zipdist';
843    
844     $self->SUPER::init_dist;
845    
846     $self->{DISTVNAME} = "$self->{DISTNAME}-$self->{VERSION_SYM}";
847     }
848    
849     =item c_o (override)
850    
851     Use VMS syntax on command line. In particular, $(DEFINE) and
852     $(PERL_INC) have been pulled into $(CCCMD). Also use MM[SK] macros.
853    
854     =cut
855    
856     sub c_o {
857     my($self) = @_;
858     return '' unless $self->needs_linking();
859     '
860     .c$(OBJ_EXT) :
861     $(CCCMD) $(CCCDLFLAGS) $(MMS$TARGET_NAME).c
862    
863     .cpp$(OBJ_EXT) :
864     $(CCCMD) $(CCCDLFLAGS) $(MMS$TARGET_NAME).cpp
865    
866     .cxx$(OBJ_EXT) :
867     $(CCCMD) $(CCCDLFLAGS) $(MMS$TARGET_NAME).cxx
868    
869     ';
870     }
871    
872     =item xs_c (override)
873    
874     Use MM[SK] macros.
875    
876     =cut
877    
878     sub xs_c {
879     my($self) = @_;
880     return '' unless $self->needs_linking();
881     '
882     .xs.c :
883     $(XSUBPP) $(XSPROTOARG) $(XSUBPPARGS) $(MMS$TARGET_NAME).xs >$(MMS$TARGET)
884     ';
885     }
886    
887     =item xs_o (override)
888    
889     Use MM[SK] macros, and VMS command line for C compiler.
890    
891     =cut
892    
893     sub xs_o { # many makes are too dumb to use xs_c then c_o
894     my($self) = @_;
895     return '' unless $self->needs_linking();
896     '
897     .xs$(OBJ_EXT) :
898     $(XSUBPP) $(XSPROTOARG) $(XSUBPPARGS) $(MMS$TARGET_NAME).xs >$(MMS$TARGET_NAME).c
899     $(CCCMD) $(CCCDLFLAGS) $(MMS$TARGET_NAME).c
900     ';
901     }
902    
903    
904     =item dlsyms (override)
905    
906     Create VMS linker options files specifying universal symbols for this
907     extension's shareable image, and listing other shareable images or
908     libraries to which it should be linked.
909    
910     =cut
911    
912     sub dlsyms {
913     my($self,%attribs) = @_;
914    
915     return '' unless $self->needs_linking();
916    
917     my($funcs) = $attribs{DL_FUNCS} || $self->{DL_FUNCS} || {};
918     my($vars) = $attribs{DL_VARS} || $self->{DL_VARS} || [];
919     my($funclist) = $attribs{FUNCLIST} || $self->{FUNCLIST} || [];
920     my(@m);
921    
922     unless ($self->{SKIPHASH}{'dynamic'}) {
923     push(@m,'
924     dynamic :: $(INST_ARCHAUTODIR)$(BASEEXT).opt
925     $(NOECHO) $(NOOP)
926     ');
927     }
928    
929     push(@m,'
930     static :: $(INST_ARCHAUTODIR)$(BASEEXT).opt
931     $(NOECHO) $(NOOP)
932     ') unless $self->{SKIPHASH}{'static'};
933    
934     push @m,'
935     $(INST_ARCHAUTODIR)$(BASEEXT).opt : $(BASEEXT).opt
936     $(CP) $(MMS$SOURCE) $(MMS$TARGET)
937    
938     $(BASEEXT).opt : Makefile.PL
939     $(PERLRUN) -e "use ExtUtils::Mksymlists;" -
940     ',qq[-e "Mksymlists('NAME' => '$self->{NAME}', 'DL_FUNCS' => ],
941     neatvalue($funcs),q[, 'DL_VARS' => ],neatvalue($vars),
942     q[, 'FUNCLIST' => ],neatvalue($funclist),qq[)"\n];
943    
944     push @m, ' $(PERL) -e "print ""$(INST_STATIC)/Include=';
945     if ($self->{OBJECT} =~ /\bBASEEXT\b/ or
946     $self->{OBJECT} =~ /\b$self->{BASEEXT}\b/i) {
947     push @m, ($Config{d_vms_case_sensitive_symbols}
948     ? uc($self->{BASEEXT}) :'$(BASEEXT)');
949     }
950     else { # We don't have a "main" object file, so pull 'em all in
951     # Upcase module names if linker is being case-sensitive
952     my($upcase) = $Config{d_vms_case_sensitive_symbols};
953     my(@omods) = map { s/\.[^.]*$//; # Trim off file type
954     s[\$\(\w+_EXT\)][]; # even as a macro
955     s/.*[:>\/\]]//; # Trim off dir spec
956     $upcase ? uc($_) : $_;
957     } split ' ', $self->eliminate_macros($self->{OBJECT});
958     my($tmp,@lines,$elt) = '';
959     $tmp = shift @omods;
960     foreach $elt (@omods) {
961     $tmp .= ",$elt";
962     if (length($tmp) > 80) { push @lines, $tmp; $tmp = ''; }
963     }
964     push @lines, $tmp;
965     push @m, '(', join( qq[, -\\n\\t"";" >>\$(MMS\$TARGET)\n\t\$(PERL) -e "print ""], @lines),')';
966     }
967     push @m, '\n$(INST_STATIC)/Library\n"";" >>$(MMS$TARGET)',"\n";
968    
969     if (length $self->{LDLOADLIBS}) {
970     my($lib); my($line) = '';
971     foreach $lib (split ' ', $self->{LDLOADLIBS}) {
972     $lib =~ s%\$%\\\$%g; # Escape '$' in VMS filespecs
973     if (length($line) + length($lib) > 160) {
974     push @m, "\t\$(PERL) -e \"print qq{$line}\" >>\$(MMS\$TARGET)\n";
975     $line = $lib . '\n';
976     }
977     else { $line .= $lib . '\n'; }
978     }
979     push @m, "\t\$(PERL) -e \"print qq{$line}\" >>\$(MMS\$TARGET)\n" if $line;
980     }
981    
982     join('',@m);
983    
984     }
985    
986     =item dynamic_lib (override)
987    
988     Use VMS Link command.
989    
990     =cut
991    
992     sub dynamic_lib {
993     my($self, %attribs) = @_;
994     return '' unless $self->needs_linking(); #might be because of a subdir
995    
996     return '' unless $self->has_link_code();
997    
998     my($otherldflags) = $attribs{OTHERLDFLAGS} || "";
999     my($inst_dynamic_dep) = $attribs{INST_DYNAMIC_DEP} || "";
1000     my $shr = $Config{'dbgprefix'} . 'PerlShr';
1001     my(@m);
1002     push @m,"
1003    
1004     OTHERLDFLAGS = $otherldflags
1005     INST_DYNAMIC_DEP = $inst_dynamic_dep
1006    
1007     ";
1008     push @m, '
1009     $(INST_DYNAMIC) : $(INST_STATIC) $(PERL_INC)perlshr_attr.opt $(INST_ARCHAUTODIR)$(DIRFILESEP).exists $(EXPORT_LIST) $(PERL_ARCHIVE) $(INST_DYNAMIC_DEP)
1010     $(NOECHO) $(MKPATH) $(INST_ARCHAUTODIR)
1011     If F$TrnLNm("',$shr,'").eqs."" Then Define/NoLog/User ',"$shr Sys\$Share:$shr.$Config{'dlext'}",'
1012     Link $(LDFLAGS) /Shareable=$(MMS$TARGET)$(OTHERLDFLAGS) $(BASEEXT).opt/Option,$(PERL_INC)perlshr_attr.opt/Option
1013     ';
1014    
1015     push @m, $self->dir_target('$(INST_ARCHAUTODIR)');
1016     join('',@m);
1017     }
1018    
1019     =item dynamic_bs (override)
1020    
1021     Use VMS-style quoting on Mkbootstrap command line.
1022    
1023     =cut
1024    
1025     sub dynamic_bs {
1026     my($self, %attribs) = @_;
1027     return '
1028     BOOTSTRAP =
1029     ' unless $self->has_link_code();
1030     '
1031     BOOTSTRAP = '."$self->{BASEEXT}.bs".'
1032    
1033     # As MakeMaker mkbootstrap might not write a file (if none is required)
1034     # we use touch to prevent make continually trying to remake it.
1035     # The DynaLoader only reads a non-empty file.
1036     $(BOOTSTRAP) : $(FIRST_MAKEFILE) '."$self->{BOOTDEP}".' $(INST_ARCHAUTODIR)$(DIRFILESEP).exists
1037     $(NOECHO) $(ECHO) "Running mkbootstrap for $(NAME) ($(BSLOADLIBS))"
1038     $(NOECHO) $(PERLRUN) -
1039     -e "use ExtUtils::Mkbootstrap; Mkbootstrap(\'$(BASEEXT)\',\'$(BSLOADLIBS)\');"
1040     $(NOECHO) $(TOUCH) $(MMS$TARGET)
1041    
1042     $(INST_BOOT) : $(BOOTSTRAP) $(INST_ARCHAUTODIR)$(DIRFILESEP).exists
1043     $(NOECHO) $(RM_RF) $(INST_BOOT)
1044     - $(CP) $(BOOTSTRAP) $(INST_BOOT)
1045     ';
1046     }
1047    
1048     =item static_lib (override)
1049    
1050     Use VMS commands to manipulate object library.
1051    
1052     =cut
1053    
1054     sub static_lib {
1055     my($self) = @_;
1056     return '' unless $self->needs_linking();
1057    
1058     return '
1059     $(INST_STATIC) :
1060     $(NOECHO) $(NOOP)
1061     ' unless ($self->{OBJECT} or @{$self->{C} || []} or $self->{MYEXTLIB});
1062    
1063     my(@m,$lib);
1064     push @m,'
1065     # Rely on suffix rule for update action
1066     $(OBJECT) : $(INST_ARCHAUTODIR)$(DIRFILESEP).exists
1067    
1068     $(INST_STATIC) : $(OBJECT) $(MYEXTLIB)
1069     ';
1070     # If this extension has its own library (eg SDBM_File)
1071     # then copy that to $(INST_STATIC) and add $(OBJECT) into it.
1072     push(@m, "\t",'$(CP) $(MYEXTLIB) $(MMS$TARGET)',"\n") if $self->{MYEXTLIB};
1073    
1074     push(@m,"\t",'If F$Search("$(MMS$TARGET)").eqs."" Then Library/Object/Create $(MMS$TARGET)',"\n");
1075    
1076     # if there was a library to copy, then we can't use MMS$SOURCE_LIST,
1077     # 'cause it's a library and you can't stick them in other libraries.
1078     # In that case, we use $OBJECT instead and hope for the best
1079     if ($self->{MYEXTLIB}) {
1080     push(@m,"\t",'Library/Object/Replace $(MMS$TARGET) $(OBJECT)',"\n");
1081     } else {
1082     push(@m,"\t",'Library/Object/Replace $(MMS$TARGET) $(MMS$SOURCE_LIST)',"\n");
1083     }
1084    
1085     push @m, "\t\$(NOECHO) \$(PERL) -e 1 >\$(INST_ARCHAUTODIR)extralibs.ld\n";
1086     foreach $lib (split ' ', $self->{EXTRALIBS}) {
1087     push(@m,"\t",'$(NOECHO) $(PERL) -e "print qq{',$lib,'\n}" >>$(INST_ARCHAUTODIR)extralibs.ld',"\n");
1088     }
1089     push @m, $self->dir_target('$(INST_ARCHAUTODIR)');
1090     join('',@m);
1091     }
1092    
1093    
1094     =item processPL (override)
1095    
1096     Use VMS-style quoting on command line.
1097    
1098     =cut
1099    
1100     sub processPL {
1101     my($self) = @_;
1102     return "" unless $self->{PL_FILES};
1103     my(@m, $plfile);
1104     foreach $plfile (sort keys %{$self->{PL_FILES}}) {
1105     my $list = ref($self->{PL_FILES}->{$plfile})
1106     ? $self->{PL_FILES}->{$plfile}
1107     : [$self->{PL_FILES}->{$plfile}];
1108     foreach my $target (@$list) {
1109     my $vmsplfile = vmsify($plfile);
1110     my $vmsfile = vmsify($target);
1111     push @m, "
1112     all :: $vmsfile
1113     \$(NOECHO) \$(NOOP)
1114    
1115     $vmsfile :: $vmsplfile
1116     ",' $(PERLRUNINST) '," $vmsplfile $vmsfile
1117     ";
1118     }
1119     }
1120     join "", @m;
1121     }
1122    
1123     =item installbin (override)
1124    
1125     Stay under DCL's 255 character command line limit once again by
1126     splitting potentially long list of files across multiple lines
1127     in C<realclean> target.
1128    
1129     =cut
1130    
1131     sub installbin {
1132     my($self) = @_;
1133     return '' unless $self->{EXE_FILES} && ref $self->{EXE_FILES} eq "ARRAY";
1134     return '' unless @{$self->{EXE_FILES}};
1135     my(@m, $from, $to, %fromto, @to);
1136     my(@exefiles) = map { vmsify($_) } @{$self->{EXE_FILES}};
1137     for $from (@exefiles) {
1138     my($path) = '$(INST_SCRIPT)' . basename($from);
1139     local($_) = $path; # backward compatibility
1140     $to = $self->libscan($path);
1141     print "libscan($from) => '$to'\n" if ($Verbose >=2);
1142     $fromto{$from} = vmsify($to);
1143     }
1144     @to = values %fromto;
1145     push @m, "
1146     EXE_FILES = @exefiles
1147    
1148     pure_all :: @to
1149     \$(NOECHO) \$(NOOP)
1150    
1151     realclean ::
1152     ";
1153    
1154     my $line = '';
1155     foreach $to (@to) {
1156     if (length($line) + length($to) > 80) {
1157     push @m, "\t\$(RM_F) $line\n";
1158     $line = $to;
1159     }
1160     else { $line .= " $to"; }
1161     }
1162     push @m, "\t\$(RM_F) $line\n\n" if $line;
1163    
1164     while (($from,$to) = each %fromto) {
1165     last unless defined $from;
1166     my $todir;
1167     if ($to =~ m#[/>:\]]#) {
1168     $todir = dirname($to);
1169     }
1170     else {
1171     ($todir = $to) =~ s/[^\)]+$//;
1172     }
1173     $todir = $self->fixpath($todir,1);
1174     push @m, "
1175     $to : $from \$(FIRST_MAKEFILE) ${todir}\$(DIRFILESEP).exists
1176     \$(CP) $from $to
1177    
1178     ", $self->dir_target($todir);
1179     }
1180     join "", @m;
1181     }
1182    
1183     =item subdir_x (override)
1184    
1185     Use VMS commands to change default directory.
1186    
1187     =cut
1188    
1189     sub subdir_x {
1190     my($self, $subdir) = @_;
1191     my(@m,$key);
1192     $subdir = $self->fixpath($subdir,1);
1193     push @m, '
1194    
1195     subdirs ::
1196     olddef = F$Environment("Default")
1197     Set Default ',$subdir,'
1198     - $(MMS)$(MMSQUALIFIERS) all $(USEMACROS)$(PASTHRU)$(MACROEND)
1199     Set Default \'olddef\'
1200     ';
1201     join('',@m);
1202     }
1203    
1204     =item clean (override)
1205    
1206     Split potentially long list of files across multiple commands (in
1207     order to stay under the magic command line limit). Also use MM[SK]
1208     commands for handling subdirectories.
1209    
1210     =cut
1211    
1212     sub clean {
1213     my($self, %attribs) = @_;
1214     my(@m,$dir);
1215     push @m, '
1216     # Delete temporary files but do not touch installed files. We don\'t delete
1217     # the Descrip.MMS here so that a later make realclean still has it to use.
1218     clean :: clean_subdirs
1219     ';
1220     push @m, ' $(RM_F) *.Map *.Dmp *.Lis *.cpp *.$(DLEXT) *$(OBJ_EXT) *$(LIB_EXT) *.Opt $(BOOTSTRAP) $(BASEEXT).bso .MM_Tmp
1221     ';
1222    
1223     my(@otherfiles) = values %{$self->{XS}}; # .c files from *.xs files
1224     # Unlink realclean, $attribs{FILES} is a string here; it may contain
1225     # a list or a macro that expands to a list.
1226     if ($attribs{FILES}) {
1227     my @filelist = ref $attribs{FILES} eq 'ARRAY'
1228     ? @{$attribs{FILES}}
1229     : split /\s+/, $attribs{FILES};
1230    
1231     foreach my $word (@filelist) {
1232     if ($word =~ m#^\$\((.*)\)$# and
1233     ref $self->{$1} eq 'ARRAY')
1234     {
1235     push(@otherfiles, @{$self->{$1}});
1236     }
1237     else { push(@otherfiles, $word); }
1238     }
1239     }
1240     push(@otherfiles, qw[ blib $(MAKE_APERL_FILE)
1241     perlmain.c pm_to_blib pm_to_blib.ts ]);
1242     push(@otherfiles, $self->catfile('$(INST_ARCHAUTODIR)','extralibs.all'));
1243     push(@otherfiles, $self->catfile('$(INST_ARCHAUTODIR)','extralibs.ld'));
1244    
1245     # Occasionally files are repeated several times from different sources
1246     { my(%of) = map { ($_ => 1) } @otherfiles; @otherfiles = keys %of; }
1247    
1248     my $line = '';
1249     foreach my $file (@otherfiles) {
1250     $file = $self->fixpath($file);
1251     if (length($line) + length($file) > 80) {
1252     push @m, "\t\$(RM_RF) $line\n";
1253     $line = "$file";
1254     }
1255     else { $line .= " $file"; }
1256     }
1257     push @m, "\t\$(RM_RF) $line\n" if $line;
1258     push(@m, " $attribs{POSTOP}\n") if $attribs{POSTOP};
1259     join('', @m);
1260     }
1261    
1262    
1263     =item clean_subdirs_target
1264    
1265     my $make_frag = $MM->clean_subdirs_target;
1266    
1267     VMS semantics for changing directories and rerunning make very different.
1268    
1269     =cut
1270    
1271     sub clean_subdirs_target {
1272     my($self) = shift;
1273    
1274     # No subdirectories, no cleaning.
1275     return <<'NOOP_FRAG' unless @{$self->{DIR}};
1276     clean_subdirs :
1277     $(NOECHO) $(NOOP)
1278     NOOP_FRAG
1279    
1280    
1281     my $clean = "clean_subdirs :\n";
1282    
1283     foreach my $dir (@{$self->{DIR}}) { # clean subdirectories first
1284     $dir = $self->fixpath($dir,1);
1285    
1286     $clean .= sprintf <<'MAKE_FRAG', $dir, $dir;
1287     If F$Search("%s$(FIRST_MAKEFILE)").nes."" Then $(PERLRUN) -e "chdir '%s'; print `$(MMS)$(MMSQUALIFIERS) clean`;"
1288     MAKE_FRAG
1289     }
1290    
1291     return $clean;
1292     }
1293    
1294    
1295     =item realclean (override)
1296    
1297     Guess what we're working around? Also, use MM[SK] for subdirectories.
1298    
1299     =cut
1300    
1301     sub realclean {
1302     my($self, %attribs) = @_;
1303     my(@m);
1304     push(@m,'
1305     # Delete temporary files (via clean) and also delete installed files
1306     realclean :: clean
1307     ');
1308     foreach(@{$self->{DIR}}){
1309     my($vmsdir) = $self->fixpath($_,1);
1310     push(@m, ' If F$Search("'."$vmsdir".'$(FIRST_MAKEFILE)").nes."" Then \\',"\n\t",
1311     '$(PERL) -e "chdir ',"'$vmsdir'",'; print `$(MMS)$(MMSQUALIFIERS) realclean`;"',"\n");
1312     }
1313     push @m, " \$(RM_RF) \$(INST_AUTODIR) \$(INST_ARCHAUTODIR)\n";
1314     push @m, " \$(RM_RF) \$(DISTVNAME)\n";
1315     # We can't expand several of the MMS macros here, since they don't have
1316     # corresponding %$self keys (i.e. they're defined in Descrip.MMS as a
1317     # combination of macros). In order to stay below DCL's 255 char limit,
1318     # we put only 2 on a line.
1319     my($file,$fcnt);
1320     my(@files) = values %{$self->{PM}};
1321     push @files, qw{ $(FIRST_MAKEFILE) $(MAKEFILE_OLD) };
1322     if ($self->has_link_code) {
1323     push(@files,qw{ $(INST_DYNAMIC) $(INST_STATIC) $(INST_BOOT) $(OBJECT) });
1324     }
1325    
1326     # Occasionally files are repeated several times from different sources
1327     { my(%f) = map { ($_,1) } @files; @files = keys %f; }
1328    
1329     my $line = '';
1330     foreach $file (@files) {
1331     if (length($line) + length($file) > 80 || ++$fcnt >= 2) {
1332     push @m, "\t\$(RM_F) $line\n";
1333     $line = "$file";
1334     $fcnt = 0;
1335     }
1336     else { $line .= " $file"; }
1337     }
1338     push @m, "\t\$(RM_F) $line\n" if $line;
1339     if ($attribs{FILES}) {
1340     my($word,$key,@filist,@allfiles);
1341     if (ref $attribs{FILES} eq 'ARRAY') { @filist = @{$attribs{FILES}}; }
1342     else { @filist = split /\s+/, $attribs{FILES}; }
1343     foreach $word (@filist) {
1344     if (($key) = $word =~ m#^\$\((.*)\)$# and ref $self->{$key} eq 'ARRAY') {
1345     push(@allfiles, @{$self->{$key}});
1346     }
1347     else { push(@allfiles, $word); }
1348     }
1349     $line = '';
1350     # Occasionally files are repeated several times from different sources
1351     { my(%af) = map { ($_,1) } @allfiles; @allfiles = keys %af; }
1352     foreach $file (@allfiles) {
1353     $file = $self->fixpath($file);
1354     if (length($line) + length($file) > 80) {
1355     push @m, "\t\$(RM_RF) $line\n";
1356     $line = "$file";
1357     }
1358     else { $line .= " $file"; }
1359     }
1360     push @m, "\t\$(RM_RF) $line\n" if $line;
1361     }
1362     push(@m, " $attribs{POSTOP}\n") if $attribs{POSTOP};
1363     join('', @m);
1364     }
1365    
1366     =item zipfile_target (o)
1367    
1368     =item tarfile_target (o)
1369    
1370     =item shdist_target (o)
1371    
1372     Syntax for invoking shar, tar and zip differs from that for Unix.
1373    
1374     =cut
1375    
1376     sub zipfile_target {
1377     my($self) = shift;
1378    
1379     return <<'MAKE_FRAG';
1380     $(DISTVNAME).zip : distdir
1381     $(PREOP)
1382     $(ZIP) "$(ZIPFLAGS)" $(MMS$TARGET) [.$(DISTVNAME)...]*.*;
1383     $(RM_RF) $(DISTVNAME)
1384     $(POSTOP)
1385     MAKE_FRAG
1386     }
1387    
1388     sub tarfile_target {
1389     my($self) = shift;
1390    
1391     return <<'MAKE_FRAG';
1392     $(DISTVNAME).tar$(SUFFIX) : distdir
1393     $(PREOP)
1394     $(TO_UNIX)
1395     $(TAR) "$(TARFLAGS)" $(DISTVNAME).tar [.$(DISTVNAME)...]
1396     $(RM_RF) $(DISTVNAME)
1397     $(COMPRESS) $(DISTVNAME).tar
1398     $(POSTOP)
1399     MAKE_FRAG
1400     }
1401    
1402     sub shdist_target {
1403     my($self) = shift;
1404    
1405     return <<'MAKE_FRAG';
1406     shdist : distdir
1407     $(PREOP)
1408     $(SHAR) [.$(DISTVNAME)...]*.*; $(DISTVNAME).share
1409     $(RM_RF) $(DISTVNAME)
1410     $(POSTOP)
1411     MAKE_FRAG
1412     }
1413    
1414     =item dist_test (override)
1415    
1416     Use VMS commands to change default directory, and use VMS-style
1417     quoting on command line.
1418    
1419     =cut
1420    
1421     sub dist_test {
1422     my($self) = @_;
1423     q{
1424     disttest : distdir
1425     startdir = F$Environment("Default")
1426     Set Default [.$(DISTVNAME)]
1427     $(ABSPERLRUN) Makefile.PL
1428     $(MMS)$(MMSQUALIFIERS)
1429     $(MMS)$(MMSQUALIFIERS) test
1430     Set Default 'startdir'
1431     };
1432     }
1433    
1434     # --- Test and Installation Sections ---
1435    
1436     =item install (override)
1437    
1438     Work around DCL's 255 character limit several times,and use
1439     VMS-style command line quoting in a few cases.
1440    
1441     =cut
1442    
1443     sub install {
1444     my($self, %attribs) = @_;
1445     my(@m,@exe_files);
1446    
1447     if ($self->{EXE_FILES}) {
1448     my($line,$file) = ('','');
1449     foreach $file (@{$self->{EXE_FILES}}) {
1450     $line .= "$file ";
1451     if (length($line) > 128) {
1452     push(@exe_files,qq[\t\$(NOECHO) \$(ECHO) "$line" >>.MM_tmp\n]);
1453     $line = '';
1454     }
1455     }
1456     push(@exe_files,qq[\t\$(NOECHO) \$(ECHO) "$line" >>.MM_tmp\n]) if $line;
1457     }
1458    
1459     push @m, q[
1460     install :: all pure_install doc_install
1461     $(NOECHO) $(NOOP)
1462    
1463     install_perl :: all pure_perl_install doc_perl_install
1464     $(NOECHO) $(NOOP)
1465    
1466     install_site :: all pure_site_install doc_site_install
1467     $(NOECHO) $(NOOP)
1468    
1469     pure_install :: pure_$(INSTALLDIRS)_install
1470     $(NOECHO) $(NOOP)
1471    
1472     doc_install :: doc_$(INSTALLDIRS)_install
1473     $(NOECHO) $(NOOP)
1474    
1475     pure__install : pure_site_install
1476     $(NOECHO) $(ECHO) "INSTALLDIRS not defined, defaulting to INSTALLDIRS=site"
1477    
1478     doc__install : doc_site_install
1479     $(NOECHO) $(ECHO) "INSTALLDIRS not defined, defaulting to INSTALLDIRS=site"
1480    
1481     # This hack brought to you by DCL's 255-character command line limit
1482     pure_perl_install ::
1483     $(NOECHO) $(PERLRUN) "-MFile::Spec" -e "print 'read '.File::Spec->catfile('$(PERL_ARCHLIB)','auto','$(FULLEXT)','.packlist').' '" >.MM_tmp
1484     $(NOECHO) $(PERLRUN) "-MFile::Spec" -e "print 'write '.File::Spec->catfile('$(DESTINSTALLARCHLIB)','auto','$(FULLEXT)','.packlist').' '" >>.MM_tmp
1485     $(NOECHO) $(ECHO_N) "$(INST_LIB) $(DESTINSTALLPRIVLIB) " >>.MM_tmp
1486     $(NOECHO) $(ECHO_N) "$(INST_ARCHLIB) $(DESTINSTALLARCHLIB) " >>.MM_tmp
1487     $(NOECHO) $(ECHO_N) "$(INST_BIN) $(DESTINSTALLBIN) " >>.MM_tmp
1488     $(NOECHO) $(ECHO_N) "$(INST_SCRIPT) $(DESTINSTALLSCRIPT) " >>.MM_tmp
1489     $(NOECHO) $(ECHO_N) "$(INST_MAN1DIR) $(DESTINSTALLMAN1DIR) " >>.MM_tmp
1490     $(NOECHO) $(ECHO_N) "$(INST_MAN3DIR) $(DESTINSTALLMAN3DIR) " >>.MM_tmp
1491     $(NOECHO) $(MOD_INSTALL) <.MM_tmp
1492     $(NOECHO) $(RM_F) .MM_tmp
1493     $(NOECHO) $(WARN_IF_OLD_PACKLIST) ].$self->catfile($self->{SITEARCHEXP},'auto',$self->{FULLEXT},'.packlist').q[
1494    
1495     # Likewise
1496     pure_site_install ::
1497     $(NOECHO) $(PERLRUN) "-MFile::Spec" -e "print 'read '.File::Spec->catfile('$(SITEARCHEXP)','auto','$(FULLEXT)','.packlist').' '" >.MM_tmp
1498     $(NOECHO) $(PERLRUN) "-MFile::Spec" -e "print 'write '.File::Spec->catfile('$(DESTINSTALLSITEARCH)','auto','$(FULLEXT)','.packlist').' '" >>.MM_tmp
1499     $(NOECHO) $(ECHO_N) "$(INST_LIB) $(DESTINSTALLSITELIB) " >>.MM_tmp
1500     $(NOECHO) $(ECHO_N) "$(INST_ARCHLIB) $(DESTINSTALLSITEARCH) " >>.MM_tmp
1501     $(NOECHO) $(ECHO_N) "$(INST_BIN) $(DESTINSTALLSITEBIN) " >>.MM_tmp
1502     $(NOECHO) $(ECHO_N) "$(INST_SCRIPT) $(DESTINSTALLSCRIPT) " >>.MM_tmp
1503     $(NOECHO) $(ECHO_N) "$(INST_MAN1DIR) $(DESTINSTALLSITEMAN1DIR) " >>.MM_tmp
1504     $(NOECHO) $(ECHO_N) "$(INST_MAN3DIR) $(DESTINSTALLSITEMAN3DIR) " >>.MM_tmp
1505     $(NOECHO) $(MOD_INSTALL) <.MM_tmp
1506     $(NOECHO) $(RM_F) .MM_tmp
1507     $(NOECHO) $(WARN_IF_OLD_PACKLIST) ].$self->catfile($self->{PERL_ARCHLIB},'auto',$self->{FULLEXT},'.packlist').q[
1508    
1509     pure_vendor_install ::
1510     $(NOECHO) $(PERLRUN) "-MFile::Spec" -e "print 'read '.File::Spec->catfile('$(VENDORARCHEXP)','auto','$(FULLEXT)','.packlist').' '" >.MM_tmp
1511     $(NOECHO) $(PERLRUN) "-MFile::Spec" -e "print 'write '.File::Spec->catfile('$(DESTINSTALLVENDORARCH)','auto','$(FULLEXT)','.packlist').' '" >>.MM_tmp
1512     $(NOECHO) $(ECHO_N) "$(INST_LIB) $(DESTINSTALLVENDORLIB) " >>.MM_tmp
1513     $(NOECHO) $(ECHO_N) "$(INST_ARCHLIB) $(DESTINSTALLVENDORARCH) " >>.MM_tmp
1514     $(NOECHO) $(ECHO_N) "$(INST_BIN) $(DESTINSTALLVENDORBIN) " >>.MM_tmp
1515     $(NOECHO) $(ECHO_N) "$(INST_SCRIPT) $(DESTINSTALLSCRIPT) " >>.MM_tmp
1516     $(NOECHO) $(ECHO_N) "$(INST_MAN1DIR) $(DESTINSTALLVENDORMAN1DIR) " >>.MM_tmp
1517     $(NOECHO) $(ECHO_N) "$(INST_MAN3DIR) $(DESTINSTALLVENDORMAN3DIR) " >>.MM_tmp
1518     $(NOECHO) $(MOD_INSTALL) <.MM_tmp
1519     $(NOECHO) $(RM_F) .MM_tmp
1520    
1521     # Ditto
1522     doc_perl_install ::
1523     $(NOECHO) $(ECHO) "Appending installation info to ].$self->catfile($self->{DESTINSTALLARCHLIB}, 'perllocal.pod').q["
1524     $(NOECHO) $(MKPATH) $(DESTINSTALLARCHLIB)
1525     $(NOECHO) $(ECHO_N) "installed into|$(INSTALLPRIVLIB)|" >.MM_tmp
1526     $(NOECHO) $(ECHO_N) "LINKTYPE|$(LINKTYPE)|VERSION|$(VERSION)|EXE_FILES|$(EXE_FILES) " >>.MM_tmp
1527     ],@exe_files,
1528     q[ $(NOECHO) $(DOC_INSTALL) "Module" "$(NAME)" <.MM_tmp >>].$self->catfile($self->{DESTINSTALLARCHLIB},'perllocal.pod').q[
1529     $(NOECHO) $(RM_F) .MM_tmp
1530    
1531     # And again
1532     doc_site_install ::
1533     $(NOECHO) $(ECHO) "Appending installation info to ].$self->catfile($self->{DESTINSTALLARCHLIB}, 'perllocal.pod').q["
1534     $(NOECHO) $(MKPATH) $(DESTINSTALLARCHLIB)
1535     $(NOECHO) $(ECHO_N) "installed into|$(INSTALLSITELIB)|" >.MM_tmp
1536     $(NOECHO) $(ECHO_N) "LINKTYPE|$(LINKTYPE)|VERSION|$(VERSION)|EXE_FILES|$(EXE_FILES) " >>.MM_tmp
1537     ],@exe_files,
1538     q[ $(NOECHO) $(DOC_INSTALL) "Module" "$(NAME)" <.MM_tmp >>].$self->catfile($self->{DESTINSTALLARCHLIB},'perllocal.pod').q[
1539     $(NOECHO) $(RM_F) .MM_tmp
1540    
1541     doc_vendor_install ::
1542     $(NOECHO) $(ECHO) "Appending installation info to ].$self->catfile($self->{DESTINSTALLARCHLIB}, 'perllocal.pod').q["
1543     $(NOECHO) $(MKPATH) $(DESTINSTALLARCHLIB)
1544     $(NOECHO) $(ECHO_N) "installed into|$(INSTALLVENDORLIB)|" >.MM_tmp
1545     $(NOECHO) $(ECHO_N) "LINKTYPE|$(LINKTYPE)|VERSION|$(VERSION)|EXE_FILES|$(EXE_FILES) " >>.MM_tmp
1546     ],@exe_files,
1547     q[ $(NOECHO) $(DOC_INSTALL) "Module" "$(NAME)" <.MM_tmp >>].$self->catfile($self->{DESTINSTALLARCHLIB},'perllocal.pod').q[
1548     $(NOECHO) $(RM_F) .MM_tmp
1549    
1550     ];
1551    
1552     push @m, q[
1553     uninstall :: uninstall_from_$(INSTALLDIRS)dirs
1554     $(NOECHO) $(NOOP)
1555    
1556     uninstall_from_perldirs ::
1557     $(NOECHO) $(UNINSTALL) ].$self->catfile($self->{PERL_ARCHLIB},'auto',$self->{FULLEXT},'.packlist').q[
1558     $(NOECHO) $(ECHO) "Uninstall is now deprecated and makes no actual changes."
1559     $(NOECHO) $(ECHO) "Please check the list above carefully for errors, and manually remove"
1560     $(NOECHO) $(ECHO) "the appropriate files. Sorry for the inconvenience."
1561    
1562     uninstall_from_sitedirs ::
1563     $(NOECHO) $(UNINSTALL) ].$self->catfile($self->{SITEARCHEXP},'auto',$self->{FULLEXT},'.packlist').q[
1564     $(NOECHO) $(ECHO) "Uninstall is now deprecated and makes no actual changes."
1565     $(NOECHO) $(ECHO) "Please check the list above carefully for errors, and manually remove"
1566     $(NOECHO) $(ECHO) "the appropriate files. Sorry for the inconvenience."
1567     ];
1568    
1569     join('',@m);
1570     }
1571    
1572     =item perldepend (override)
1573    
1574     Use VMS-style syntax for files; it's cheaper to just do it directly here
1575     than to have the MM_Unix method call C<catfile> repeatedly. Also, if
1576     we have to rebuild Config.pm, use MM[SK] to do it.
1577    
1578     =cut
1579    
1580     sub perldepend {
1581     my($self) = @_;
1582     my(@m);
1583    
1584     push @m, '
1585     $(OBJECT) : $(PERL_INC)EXTERN.h, $(PERL_INC)INTERN.h, $(PERL_INC)XSUB.h
1586     $(OBJECT) : $(PERL_INC)av.h, $(PERL_INC)cc_runtime.h, $(PERL_INC)config.h
1587     $(OBJECT) : $(PERL_INC)cop.h, $(PERL_INC)cv.h, $(PERL_INC)embed.h
1588     $(OBJECT) : $(PERL_INC)embedvar.h, $(PERL_INC)form.h
1589     $(OBJECT) : $(PERL_INC)gv.h, $(PERL_INC)handy.h, $(PERL_INC)hv.h
1590     $(OBJECT) : $(PERL_INC)intrpvar.h, $(PERL_INC)iperlsys.h, $(PERL_INC)keywords.h
1591     $(OBJECT) : $(PERL_INC)mg.h, $(PERL_INC)nostdio.h, $(PERL_INC)op.h
1592     $(OBJECT) : $(PERL_INC)opcode.h, $(PERL_INC)patchlevel.h
1593     $(OBJECT) : $(PERL_INC)perl.h, $(PERL_INC)perlio.h
1594     $(OBJECT) : $(PERL_INC)perlsdio.h, $(PERL_INC)perlvars.h
1595     $(OBJECT) : $(PERL_INC)perly.h, $(PERL_INC)pp.h, $(PERL_INC)pp_proto.h
1596     $(OBJECT) : $(PERL_INC)proto.h, $(PERL_INC)regcomp.h, $(PERL_INC)regexp.h
1597     $(OBJECT) : $(PERL_INC)regnodes.h, $(PERL_INC)scope.h, $(PERL_INC)sv.h
1598     $(OBJECT) : $(PERL_INC)thrdvar.h, $(PERL_INC)thread.h
1599     $(OBJECT) : $(PERL_INC)util.h, $(PERL_INC)vmsish.h
1600    
1601     ' if $self->{OBJECT};
1602    
1603     if ($self->{PERL_SRC}) {
1604     my(@macros);
1605     my($mmsquals) = '$(USEMAKEFILE)[.vms]$(FIRST_MAKEFILE)';
1606     push(@macros,'__AXP__=1') if $Config{'archname'} eq 'VMS_AXP';
1607     push(@macros,'DECC=1') if $Config{'vms_cc_type'} eq 'decc';
1608     push(@macros,'GNUC=1') if $Config{'vms_cc_type'} eq 'gcc';
1609     push(@macros,'SOCKET=1') if $Config{'d_has_sockets'};
1610     push(@macros,qq["CC=$Config{'cc'}"]) if $Config{'cc'} =~ m!/!;
1611     $mmsquals .= '$(USEMACROS)' . join(',',@macros) . '$(MACROEND)' if @macros;
1612     push(@m,q[
1613     # Check for unpropagated config.sh changes. Should never happen.
1614     # We do NOT just update config.h because that is not sufficient.
1615     # An out of date config.h is not fatal but complains loudly!
1616     $(PERL_INC)config.h : $(PERL_SRC)config.sh
1617     $(NOOP)
1618    
1619     $(PERL_ARCHLIB)Config.pm : $(PERL_SRC)config.sh
1620     $(NOECHO) Write Sys$Error "$(PERL_ARCHLIB)Config.pm may be out of date with config.h or genconfig.pl"
1621     olddef = F$Environment("Default")
1622     Set Default $(PERL_SRC)
1623     $(MMS)],$mmsquals,);
1624     if ($self->{PERL_ARCHLIB} =~ m|\[-| && $self->{PERL_SRC} =~ m|(\[-+)|) {
1625     my($prefix,$target) = ($1,$self->fixpath('$(PERL_ARCHLIB)Config.pm',0));
1626     $target =~ s/\Q$prefix/[/;
1627     push(@m," $target");
1628     }
1629     else { push(@m,' $(MMS$TARGET)'); }
1630     push(@m,q[
1631     Set Default 'olddef'
1632     ]);
1633     }
1634    
1635     push(@m, join(" ", map($self->fixpath($_,0),values %{$self->{XS}}))." : \$(XSUBPPDEPS)\n")
1636     if %{$self->{XS}};
1637    
1638     join('',@m);
1639     }
1640    
1641     =item makefile (override)
1642    
1643     Use VMS commands and quoting.
1644    
1645     =cut
1646    
1647     sub makefile {
1648     my($self) = @_;
1649     my(@m,@cmd);
1650     # We do not know what target was originally specified so we
1651     # must force a manual rerun to be sure. But as it should only
1652     # happen very rarely it is not a significant problem.
1653     push @m, q[
1654     $(OBJECT) : $(FIRST_MAKEFILE)
1655     ] if $self->{OBJECT};
1656    
1657     push @m,q[
1658     # We take a very conservative approach here, but it's worth it.
1659     # We move $(FIRST_MAKEFILE) to $(MAKEFILE_OLD) here to avoid gnu make looping.
1660     $(FIRST_MAKEFILE) : Makefile.PL $(CONFIGDEP)
1661     $(NOECHO) $(ECHO) "$(FIRST_MAKEFILE) out-of-date with respect to $(MMS$SOURCE_LIST)"
1662     $(NOECHO) $(ECHO) "Cleaning current config before rebuilding $(FIRST_MAKEFILE) ..."
1663     - $(MV) $(FIRST_MAKEFILE) $(MAKEFILE_OLD)
1664     - $(MMS)$(MMSQUALIFIERS) $(USEMAKEFILE)$(MAKEFILE_OLD) clean
1665     $(PERLRUN) Makefile.PL ],join(' ',map(qq["$_"],@ARGV)),q[
1666     $(NOECHO) $(ECHO) "$(FIRST_MAKEFILE) has been rebuilt."
1667     $(NOECHO) $(ECHO) "Please run $(MMS) to build the extension."
1668     ];
1669    
1670     join('',@m);
1671     }
1672    
1673     =item find_tests (override)
1674    
1675     =cut
1676    
1677     sub find_tests {
1678     my $self = shift;
1679     return -d 't' ? 't/*.t' : '';
1680     }
1681    
1682     =item test (override)
1683    
1684     Use VMS commands for handling subdirectories.
1685    
1686     =cut
1687    
1688     sub test {
1689     my($self, %attribs) = @_;
1690     my($tests) = $attribs{TESTS} || $self->find_tests;
1691     my(@m);
1692     push @m,"
1693     TEST_VERBOSE = 0
1694     TEST_TYPE = test_\$(LINKTYPE)
1695     TEST_FILE = test.pl
1696     TESTDB_SW = -d
1697    
1698     test :: \$(TEST_TYPE)
1699     \$(NOECHO) \$(NOOP)
1700    
1701     testdb :: testdb_\$(LINKTYPE)
1702     \$(NOECHO) \$(NOOP)
1703    
1704     ";
1705     foreach(@{$self->{DIR}}){
1706     my($vmsdir) = $self->fixpath($_,1);
1707     push(@m, ' If F$Search("',$vmsdir,'$(FIRST_MAKEFILE)").nes."" Then $(PERL) -e "chdir ',"'$vmsdir'",
1708     '; print `$(MMS)$(MMSQUALIFIERS) $(PASTHRU2) test`'."\n");
1709     }
1710     push(@m, "\t\$(NOECHO) \$(ECHO) \"No tests defined for \$(NAME) extension.\"\n")
1711     unless $tests or -f "test.pl" or @{$self->{DIR}};
1712     push(@m, "\n");
1713    
1714     push(@m, "test_dynamic :: pure_all\n");
1715     push(@m, $self->test_via_harness('$(FULLPERLRUN)', $tests)) if $tests;
1716     push(@m, $self->test_via_script('$(FULLPERLRUN)', 'test.pl')) if -f "test.pl";
1717     push(@m, "\t\$(NOECHO) \$(NOOP)\n") if (!$tests && ! -f "test.pl");
1718     push(@m, "\n");
1719    
1720     push(@m, "testdb_dynamic :: pure_all\n");
1721     push(@m, $self->test_via_script('$(FULLPERLRUN) "$(TESTDB_SW)"', '$(TEST_FILE)'));
1722     push(@m, "\n");
1723    
1724     # Occasionally we may face this degenerate target:
1725     push @m, "test_ : test_dynamic\n\n";
1726    
1727     if ($self->needs_linking()) {
1728     push(@m, "test_static :: pure_all \$(MAP_TARGET)\n");
1729     push(@m, $self->test_via_harness('$(MAP_TARGET)', $tests)) if $tests;
1730     push(@m, $self->test_via_script('$(MAP_TARGET)', 'test.pl')) if -f 'test.pl';
1731     push(@m, "\n");
1732     push(@m, "testdb_static :: pure_all \$(MAP_TARGET)\n");
1733     push(@m, $self->test_via_script('$(MAP_TARGET) $(TESTDB_SW)', '$(TEST_FILE)'));
1734     push(@m, "\n");
1735     }
1736     else {
1737     push @m, "test_static :: test_dynamic\n\t\$(NOECHO) \$(NOOP)\n\n";
1738     push @m, "testdb_static :: testdb_dynamic\n\t\$(NOECHO) \$(NOOP)\n";
1739     }
1740    
1741     join('',@m);
1742     }
1743    
1744     =item makeaperl (override)
1745    
1746     Undertake to build a new set of Perl images using VMS commands. Since
1747     VMS does dynamic loading, it's not necessary to statically link each
1748     extension into the Perl image, so this isn't the normal build path.
1749     Consequently, it hasn't really been tested, and may well be incomplete.
1750    
1751     =cut
1752    
1753     use vars qw(%olbs);
1754    
1755     sub makeaperl {
1756     my($self, %attribs) = @_;
1757     my($makefilename, $searchdirs, $static, $extra, $perlinc, $target, $tmpdir, $libperl) =
1758     @attribs{qw(MAKE DIRS STAT EXTRA INCL TARGET TMP LIBPERL)};
1759     my(@m);
1760     push @m, "
1761     # --- MakeMaker makeaperl section ---
1762     MAP_TARGET = $target
1763     ";
1764     return join '', @m if $self->{PARENT};
1765    
1766     my($dir) = join ":", @{$self->{DIR}};
1767    
1768     unless ($self->{MAKEAPERL}) {
1769     push @m, q{
1770     $(MAKE_APERL_FILE) : $(FIRST_MAKEFILE)
1771     $(NOECHO) $(ECHO) "Writing ""$(MMS$TARGET)"" for this $(MAP_TARGET)"
1772     $(NOECHO) $(PERLRUNINST) \
1773     Makefile.PL DIR=}, $dir, q{ \
1774     FIRST_MAKEFILE=$(MAKE_APERL_FILE) LINKTYPE=static \
1775     MAKEAPERL=1 NORECURS=1 };
1776    
1777     push @m, map(q[ \\\n\t\t"$_"], @ARGV),q{
1778    
1779     $(MAP_TARGET) :: $(MAKE_APERL_FILE)
1780     $(MMS)$(MMSQUALIFIERS)$(USEMAKEFILE)$(MAKE_APERL_FILE) static $(MMS$TARGET)
1781     };
1782     push @m, "\n";
1783    
1784     return join '', @m;
1785     }
1786    
1787    
1788     my($linkcmd,@optlibs,@staticpkgs,$extralist,$targdir,$libperldir,%libseen);
1789     local($_);
1790    
1791     # The front matter of the linkcommand...
1792     $linkcmd = join ' ', $Config{'ld'},
1793     grep($_, @Config{qw(large split ldflags ccdlflags)});
1794     $linkcmd =~ s/\s+/ /g;
1795    
1796     # Which *.olb files could we make use of...
1797     local(%olbs); # XXX can this be lexical?
1798     $olbs{$self->{INST_ARCHAUTODIR}} = "$self->{BASEEXT}\$(LIB_EXT)";
1799     require File::Find;
1800     File::Find::find(sub {
1801     return unless m/\Q$self->{LIB_EXT}\E$/;
1802     return if m/^libperl/;
1803    
1804     if( exists $self->{INCLUDE_EXT} ){
1805     my $found = 0;
1806     my $incl;
1807     my $xx;
1808    
1809     ($xx = $File::Find::name) =~ s,.*?/auto/,,;
1810     $xx =~ s,/?$_,,;
1811     $xx =~ s,/,::,g;
1812    
1813     # Throw away anything not explicitly marked for inclusion.
1814     # DynaLoader is implied.
1815     foreach $incl ((@{$self->{INCLUDE_EXT}},'DynaLoader')){
1816     if( $xx eq $incl ){
1817     $found++;
1818     last;
1819     }
1820     }
1821     return unless $found;
1822     }
1823     elsif( exists $self->{EXCLUDE_EXT} ){
1824     my $excl;
1825     my $xx;
1826    
1827     ($xx = $File::Find::name) =~ s,.*?/auto/,,;
1828     $xx =~ s,/?$_,,;
1829     $xx =~ s,/,::,g;
1830    
1831     # Throw away anything explicitly marked for exclusion
1832     foreach $excl (@{$self->{EXCLUDE_EXT}}){
1833     return if( $xx eq $excl );
1834     }
1835     }
1836    
1837     $olbs{$ENV{DEFAULT}} = $_;
1838     }, grep( -d $_, @{$searchdirs || []}));
1839    
1840     # We trust that what has been handed in as argument will be buildable
1841     $static = [] unless $static;
1842     @olbs{@{$static}} = (1) x @{$static};
1843    
1844     $extra = [] unless $extra && ref $extra eq 'ARRAY';
1845     # Sort the object libraries in inverse order of
1846     # filespec length to try to insure that dependent extensions
1847     # will appear before their parents, so the linker will
1848     # search the parent library to resolve references.
1849     # (e.g. Intuit::DWIM will precede Intuit, so unresolved
1850     # references from [.intuit.dwim]dwim.obj can be found
1851     # in [.intuit]intuit.olb).
1852     for (sort { length($a) <=> length($b) } keys %olbs) {
1853     next unless $olbs{$_} =~ /\Q$self->{LIB_EXT}\E$/;
1854     my($dir) = $self->fixpath($_,1);
1855     my($extralibs) = $dir . "extralibs.ld";
1856     my($extopt) = $dir . $olbs{$_};
1857     $extopt =~ s/$self->{LIB_EXT}$/.opt/;
1858     push @optlibs, "$dir$olbs{$_}";
1859     # Get external libraries this extension will need
1860     if (-f $extralibs ) {
1861     my %seenthis;
1862     open LIST,$extralibs or warn $!,next;
1863     while (<LIST>) {
1864     chomp;
1865     # Include a library in the link only once, unless it's mentioned
1866     # multiple times within a single extension's options file, in which
1867     # case we assume the builder needed to search it again later in the
1868     # link.
1869     my $skip = exists($libseen{$_}) && !exists($seenthis{$_});
1870     $libseen{$_}++; $seenthis{$_}++;
1871     next if $skip;
1872     push @$extra,$_;
1873     }
1874     close LIST;
1875     }
1876     # Get full name of extension for ExtUtils::Miniperl
1877     if (-f $extopt) {
1878     open OPT,$extopt or die $!;
1879     while (<OPT>) {
1880     next unless /(?:UNIVERSAL|VECTOR)=boot_([\w_]+)/;
1881     my $pkg = $1;
1882     $pkg =~ s#__*#::#g;
1883     push @staticpkgs,$pkg;
1884     }
1885     }
1886     }
1887     # Place all of the external libraries after all of the Perl extension
1888     # libraries in the final link, in order to maximize the opportunity
1889     # for XS code from multiple extensions to resolve symbols against the
1890     # same external library while only including that library once.
1891     push @optlibs, @$extra;
1892    
1893     $target = "Perl$Config{'exe_ext'}" unless $target;
1894     my $shrtarget;
1895     ($shrtarget,$targdir) = fileparse($target);
1896     $shrtarget =~ s/^([^.]*)/$1Shr/;
1897     $shrtarget = $targdir . $shrtarget;
1898     $target = "Perlshr.$Config{'dlext'}" unless $target;
1899     $tmpdir = "[]" unless $tmpdir;
1900     $tmpdir = $self->fixpath($tmpdir,1);
1901     if (@optlibs) { $extralist = join(' ',@optlibs); }
1902     else { $extralist = ''; }
1903     # Let ExtUtils::Liblist find the necessary libs for us (but skip PerlShr)
1904     # that's what we're building here).
1905     push @optlibs, grep { !/PerlShr/i } split ' ', +($self->ext())[2];
1906     if ($libperl) {
1907     unless (-f $libperl || -f ($libperl = $self->catfile($Config{'installarchlib'},'CORE',$libperl))) {
1908     print STDOUT "Warning: $libperl not found\n";
1909     undef $libperl;
1910     }
1911     }
1912     unless ($libperl) {
1913     if (defined $self->{PERL_SRC}) {
1914     $libperl = $self->catfile($self->{PERL_SRC},"libperl$self->{LIB_EXT}");
1915     } elsif (-f ($libperl = $self->catfile($Config{'installarchlib'},'CORE',"libperl$self->{LIB_EXT}")) ) {
1916     } else {
1917     print STDOUT "Warning: $libperl not found
1918     If you're going to build a static perl binary, make sure perl is installed
1919     otherwise ignore this warning\n";
1920     }
1921     }
1922     $libperldir = $self->fixpath((fileparse($libperl))[1],1);
1923    
1924     push @m, '
1925     # Fill in the target you want to produce if it\'s not perl
1926     MAP_TARGET = ',$self->fixpath($target,0),'
1927     MAP_SHRTARGET = ',$self->fixpath($shrtarget,0),"
1928     MAP_LINKCMD = $linkcmd
1929     MAP_PERLINC = ", $perlinc ? map('"$_" ',@{$perlinc}) : '',"
1930     MAP_EXTRA = $extralist
1931     MAP_LIBPERL = ",$self->fixpath($libperl,0),'
1932     ';
1933    
1934    
1935     push @m,"\n${tmpdir}Makeaperl.Opt : \$(MAP_EXTRA)\n";
1936     foreach (@optlibs) {
1937     push @m,' $(NOECHO) $(PERL) -e "print q{',$_,'}" >>$(MMS$TARGET)',"\n";
1938     }
1939     push @m,"\n${tmpdir}PerlShr.Opt :\n\t";
1940     push @m,'$(NOECHO) $(PERL) -e "print q{$(MAP_SHRTARGET)}" >$(MMS$TARGET)',"\n";
1941    
1942     push @m,'
1943     $(MAP_SHRTARGET) : $(MAP_LIBPERL) Makeaperl.Opt ',"${libperldir}Perlshr_Attr.Opt",'
1944     $(MAP_LINKCMD)/Shareable=$(MMS$TARGET) $(MAP_LIBPERL), Makeaperl.Opt/Option ',"${libperldir}Perlshr_Attr.Opt/Option",'
1945     $(MAP_TARGET) : $(MAP_SHRTARGET) ',"${tmpdir}perlmain\$(OBJ_EXT) ${tmpdir}PerlShr.Opt",'
1946     $(MAP_LINKCMD) ',"${tmpdir}perlmain\$(OBJ_EXT)",', PerlShr.Opt/Option
1947     $(NOECHO) $(ECHO) "To install the new ""$(MAP_TARGET)"" binary, say"
1948     $(NOECHO) $(ECHO) " $(MMS)$(MMSQUALIFIERS)$(USEMAKEFILE)$(FIRST_MAKEFILE) inst_perl $(USEMACROS)MAP_TARGET=$(MAP_TARGET)$(ENDMACRO)"
1949     $(NOECHO) $(ECHO) "To remove the intermediate files, say
1950     $(NOECHO) $(ECHO) " $(MMS)$(MMSQUALIFIERS)$(USEMAKEFILE)$(FIRST_MAKEFILE) map_clean"
1951     ';
1952     push @m,"\n${tmpdir}perlmain.c : \$(FIRST_MAKEFILE)\n\t\$(NOECHO) \$(PERL) -e 1 >${tmpdir}Writemain.tmp\n";
1953     push @m, "# More from the 255-char line length limit\n";
1954     foreach (@staticpkgs) {
1955     push @m,' $(NOECHO) $(PERL) -e "print q{',$_,qq[}" >>${tmpdir}Writemain.tmp\n];
1956     }
1957    
1958     push @m, sprintf <<'MAKE_FRAG', $tmpdir, $tmpdir;
1959     $(NOECHO) $(PERL) $(MAP_PERLINC) -ane "use ExtUtils::Miniperl; writemain(@F)" %sWritemain.tmp >$(MMS$TARGET)
1960     $(NOECHO) $(RM_F) %sWritemain.tmp
1961     MAKE_FRAG
1962    
1963     push @m, q[
1964     # Still more from the 255-char line length limit
1965     doc_inst_perl :
1966     $(NOECHO) $(MKPATH) $(DESTINSTALLARCHLIB)
1967     $(NOECHO) $(ECHO) "Perl binary $(MAP_TARGET)|" >.MM_tmp
1968     $(NOECHO) $(ECHO) "MAP_STATIC|$(MAP_STATIC)|" >>.MM_tmp
1969     $(NOECHO) $(PERL) -pl040 -e " " ].$self->catfile('$(INST_ARCHAUTODIR)','extralibs.all'),q[ >>.MM_tmp
1970     $(NOECHO) $(ECHO) -e "MAP_LIBPERL|$(MAP_LIBPERL)|" >>.MM_tmp
1971     $(NOECHO) $(DOC_INSTALL) <.MM_tmp >>].$self->catfile('$(DESTINSTALLARCHLIB)','perllocal.pod').q[
1972     $(NOECHO) $(RM_F) .MM_tmp
1973     ];
1974    
1975     push @m, "
1976     inst_perl : pure_inst_perl doc_inst_perl
1977     \$(NOECHO) \$(NOOP)
1978    
1979     pure_inst_perl : \$(MAP_TARGET)
1980     $self->{CP} \$(MAP_SHRTARGET) ",$self->fixpath($Config{'installbin'},1),"
1981     $self->{CP} \$(MAP_TARGET) ",$self->fixpath($Config{'installbin'},1),"
1982    
1983     clean :: map_clean
1984     \$(NOECHO) \$(NOOP)
1985    
1986     map_clean :
1987     \$(RM_F) ${tmpdir}perlmain\$(OBJ_EXT) ${tmpdir}perlmain.c \$(FIRST_MAKEFILE)
1988     \$(RM_F) ${tmpdir}Makeaperl.Opt ${tmpdir}PerlShr.Opt \$(MAP_TARGET)
1989     ";
1990    
1991     join '', @m;
1992     }
1993    
1994     # --- Output postprocessing section ---
1995    
1996     =item nicetext (override)
1997    
1998     Insure that colons marking targets are preceded by space, in order
1999     to distinguish the target delimiter from a colon appearing as
2000     part of a filespec.
2001    
2002     =cut
2003    
2004     sub nicetext {
2005     my($self,$text) = @_;
2006     return $text if $text =~ m/^\w+\s*=/; # leave macro defs alone
2007     $text =~ s/([^\s:])(:+\s)/$1 $2/gs;
2008     $text;
2009     }
2010    
2011     =item prefixify (override)
2012    
2013     prefixifying on VMS is simple. Each should simply be:
2014    
2015     perl_root:[some.dir]
2016    
2017     which can just be converted to:
2018    
2019     volume:[your.prefix.some.dir]
2020    
2021     otherwise you get the default layout.
2022    
2023     In effect, your search prefix is ignored and $Config{vms_prefix} is
2024     used instead.
2025    
2026     =cut
2027    
2028     sub prefixify {
2029     my($self, $var, $sprefix, $rprefix, $default) = @_;
2030    
2031     # Translate $(PERLPREFIX) to a real path.
2032     $rprefix = $self->eliminate_macros($rprefix);
2033     $rprefix = VMS::Filespec::vmspath($rprefix) if $rprefix;
2034     $sprefix = VMS::Filespec::vmspath($sprefix) if $sprefix;
2035    
2036     $default = VMS::Filespec::vmsify($default)
2037     unless $default =~ /\[.*\]/;
2038    
2039     (my $var_no_install = $var) =~ s/^install//;
2040     my $path = $self->{uc $var} ||
2041     $ExtUtils::MM_Unix::Config_Override{lc $var} ||
2042     $Config{lc $var} || $Config{lc $var_no_install};
2043    
2044     if( !$path ) {
2045     print STDERR " no Config found for $var.\n" if $Verbose >= 2;
2046     $path = $self->_prefixify_default($rprefix, $default);
2047     }
2048     elsif( $sprefix eq $rprefix ) {
2049     print STDERR " no new prefix.\n" if $Verbose >= 2;
2050     }
2051     else {
2052    
2053     print STDERR " prefixify $var => $path\n" if $Verbose >= 2;
2054     print STDERR " from $sprefix to $rprefix\n" if $Verbose >= 2;
2055    
2056     my($path_vol, $path_dirs) = $self->splitpath( $path );
2057     if( $path_vol eq $Config{vms_prefix}.':' ) {
2058     print STDERR " $Config{vms_prefix}: seen\n" if $Verbose >= 2;
2059    
2060     $path_dirs =~ s{^\[}{\[.} unless $path_dirs =~ m{^\[\.};
2061     $path = $self->_catprefix($rprefix, $path_dirs);
2062     }
2063     else {
2064     $path = $self->_prefixify_default($rprefix, $default);
2065     }
2066     }
2067    
2068     print " now $path\n" if $Verbose >= 2;
2069     return $self->{uc $var} = $path;
2070     }
2071    
2072    
2073     sub _prefixify_default {
2074     my($self, $rprefix, $default) = @_;
2075    
2076     print STDERR " cannot prefix, using default.\n" if $Verbose >= 2;
2077    
2078     if( !$default ) {
2079     print STDERR "No default!\n" if $Verbose >= 1;
2080     return;
2081     }
2082     if( !$rprefix ) {
2083     print STDERR "No replacement prefix!\n" if $Verbose >= 1;
2084     return '';
2085     }
2086    
2087     return $self->_catprefix($rprefix, $default);
2088     }
2089    
2090     sub _catprefix {
2091     my($self, $rprefix, $default) = @_;
2092    
2093     my($rvol, $rdirs) = $self->splitpath($rprefix);
2094     if( $rvol ) {
2095     return $self->catpath($rvol,
2096     $self->catdir($rdirs, $default),
2097     ''
2098     )
2099     }
2100     else {
2101     return $self->catdir($rdirs, $default);
2102     }
2103     }
2104    
2105    
2106     =item oneliner (o)
2107    
2108     =cut
2109    
2110     sub oneliner {
2111     my($self, $cmd, $switches) = @_;
2112     $switches = [] unless defined $switches;
2113    
2114     # Strip leading and trailing newlines
2115     $cmd =~ s{^\n+}{};
2116     $cmd =~ s{\n+$}{};
2117    
2118     $cmd = $self->quote_literal($cmd);
2119     $cmd = $self->escape_newlines($cmd);
2120    
2121     # Switches must be quoted else they will be lowercased.
2122     $switches = join ' ', map { qq{"$_"} } @$switches;
2123    
2124     return qq{\$(PERLRUN) $switches -e $cmd};
2125     }
2126    
2127    
2128     =item B<echo> (o)
2129    
2130     perl trips up on "<foo>" thinking it's an input redirect. So we use the
2131     native Write command instead. Besides, its faster.
2132    
2133     =cut
2134    
2135     sub echo {
2136     my($self, $text, $file, $appending) = @_;
2137     $appending ||= 0;
2138    
2139     my $opencmd = $appending ? 'Open/Append' : 'Open/Write';
2140    
2141     my @cmds = ("\$(NOECHO) $opencmd MMECHOFILE $file ");
2142     push @cmds, map { '$(NOECHO) Write MMECHOFILE '.$self->quote_literal($_) }
2143     split /\n/, $text;
2144     push @cmds, '$(NOECHO) Close MMECHOFILE';
2145     return @cmds;
2146     }
2147    
2148    
2149     =item quote_literal
2150    
2151     =cut
2152    
2153     sub quote_literal {
2154     my($self, $text) = @_;
2155    
2156     # I believe this is all we should need.
2157     $text =~ s{"}{""}g;
2158    
2159     return qq{"$text"};
2160     }
2161    
2162     =item escape_newlines
2163    
2164     =cut
2165    
2166     sub escape_newlines {
2167     my($self, $text) = @_;
2168    
2169     $text =~ s{\n}{-\n}g;
2170    
2171     return $text;
2172     }
2173    
2174     =item max_exec_len
2175    
2176     256 characters.
2177    
2178     =cut
2179    
2180     sub max_exec_len {
2181     my $self = shift;
2182    
2183     return $self->{_MAX_EXEC_LEN} ||= 256;
2184     }
2185    
2186     =item init_linker (o)
2187    
2188     =cut
2189    
2190     sub init_linker {
2191     my $self = shift;
2192     $self->{EXPORT_LIST} ||= '$(BASEEXT).opt';
2193    
2194     my $shr = $Config{dbgprefix} . 'PERLSHR';
2195     if ($self->{PERL_SRC}) {
2196     $self->{PERL_ARCHIVE} ||=
2197     $self->catfile($self->{PERL_SRC}, "$shr.$Config{'dlext'}");
2198     }
2199     else {
2200     $self->{PERL_ARCHIVE} ||=
2201     $ENV{$shr} ? $ENV{$shr} : "Sys\$Share:$shr.$Config{'dlext'}";
2202     }
2203    
2204     $self->{PERL_ARCHIVE_AFTER} ||= '';
2205     }
2206    
2207     =item eliminate_macros
2208    
2209     Expands MM[KS]/Make macros in a text string, using the contents of
2210     identically named elements of C<%$self>, and returns the result
2211     as a file specification in Unix syntax.
2212    
2213     NOTE: This is the canonical version of the method. The version in
2214     File::Spec::VMS is deprecated.
2215    
2216     =cut
2217    
2218     sub eliminate_macros {
2219     my($self,$path) = @_;
2220     return '' unless $path;
2221     $self = {} unless ref $self;
2222    
2223     if ($path =~ /\s/) {
2224     return join ' ', map { $self->eliminate_macros($_) } split /\s+/, $path;
2225     }
2226    
2227     my($npath) = unixify($path);
2228     # sometimes unixify will return a string with an off-by-one trailing null
2229     $npath =~ s{\0$}{};
2230    
2231     my($complex) = 0;
2232     my($head,$macro,$tail);
2233    
2234     # perform m##g in scalar context so it acts as an iterator
2235     while ($npath =~ m#(.*?)\$\((\S+?)\)(.*)#gs) {
2236     if (defined $self->{$2}) {
2237     ($head,$macro,$tail) = ($1,$2,$3);
2238     if (ref $self->{$macro}) {
2239     if (ref $self->{$macro} eq 'ARRAY') {
2240     $macro = join ' ', @{$self->{$macro}};
2241     }
2242     else {
2243     print "Note: can't expand macro \$($macro) containing ",ref($self->{$macro}),
2244     "\n\t(using MMK-specific deferred substitutuon; MMS will break)\n";
2245     $macro = "\cB$macro\cB";
2246     $complex = 1;
2247     }
2248     }
2249     else { ($macro = unixify($self->{$macro})) =~ s#/\Z(?!\n)##; }
2250     $npath = "$head$macro$tail";
2251     }
2252     }
2253     if ($complex) { $npath =~ s#\cB(.*?)\cB#\${$1}#gs; }
2254     $npath;
2255     }
2256    
2257     =item fixpath
2258    
2259     Catchall routine to clean up problem MM[SK]/Make macros. Expands macros
2260     in any directory specification, in order to avoid juxtaposing two
2261     VMS-syntax directories when MM[SK] is run. Also expands expressions which
2262     are all macro, so that we can tell how long the expansion is, and avoid
2263     overrunning DCL's command buffer when MM[KS] is running.
2264    
2265     If optional second argument has a TRUE value, then the return string is
2266     a VMS-syntax directory specification, if it is FALSE, the return string
2267     is a VMS-syntax file specification, and if it is not specified, fixpath()
2268     checks to see whether it matches the name of a directory in the current
2269     default directory, and returns a directory or file specification accordingly.
2270    
2271     NOTE: This is the canonical version of the method. The version in
2272     File::Spec::VMS is deprecated.
2273    
2274     =cut
2275    
2276     sub fixpath {
2277     my($self,$path,$force_path) = @_;
2278     return '' unless $path;
2279     $self = bless {} unless ref $self;
2280     my($fixedpath,$prefix,$name);
2281    
2282     if ($path =~ /\s/) {
2283     return join ' ',
2284     map { $self->fixpath($_,$force_path) }
2285     split /\s+/, $path;
2286     }
2287    
2288     if ($path =~ m#^\$\([^\)]+\)\Z(?!\n)#s || $path =~ m#[/:>\]]#) {
2289     if ($force_path or $path =~ /(?:DIR\)|\])\Z(?!\n)/) {
2290     $fixedpath = vmspath($self->eliminate_macros($path));
2291     }
2292     else {
2293     $fixedpath = vmsify($self->eliminate_macros($path));
2294     }
2295     }
2296     elsif ((($prefix,$name) = ($path =~ m#^\$\(([^\)]+)\)(.+)#s)) && $self->{$prefix}) {
2297     my($vmspre) = $self->eliminate_macros("\$($prefix)");
2298     # is it a dir or just a name?
2299     $vmspre = ($vmspre =~ m|/| or $prefix =~ /DIR\Z(?!\n)/) ? vmspath($vmspre) : '';
2300     $fixedpath = ($vmspre ? $vmspre : $self->{$prefix}) . $name;
2301     $fixedpath = vmspath($fixedpath) if $force_path;
2302     }
2303     else {
2304     $fixedpath = $path;
2305     $fixedpath = vmspath($fixedpath) if $force_path;
2306     }
2307     # No hints, so we try to guess
2308     if (!defined($force_path) and $fixedpath !~ /[:>(.\]]/) {
2309     $fixedpath = vmspath($fixedpath) if -d $fixedpath;
2310     }
2311    
2312     # Trim off root dirname if it's had other dirs inserted in front of it.
2313     $fixedpath =~ s/\.000000([\]>])/$1/;
2314     # Special case for VMS absolute directory specs: these will have had device
2315     # prepended during trip through Unix syntax in eliminate_macros(), since
2316     # Unix syntax has no way to express "absolute from the top of this device's
2317     # directory tree".
2318     if ($path =~ /^[\[>][^.\-]/) { $fixedpath =~ s/^[^\[<]+//; }
2319    
2320     return $fixedpath;
2321     }
2322    
2323    
2324     =item os_flavor
2325    
2326     VMS is VMS.
2327    
2328     =cut
2329    
2330     sub os_flavor {
2331     return('VMS');
2332     }
2333    
2334     =back
2335    
2336     =cut
2337    
2338     1;
2339