A potential fix for non-empty LD in Unix.
[p5sagit/p5-mst-13.2.git] / lib / ExtUtils / MM_VMS.pm
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