summaryrefslogtreecommitdiff
path: root/vms/ext
diff options
context:
space:
mode:
authorLarry Wall <lwall@netlabs.com>1995-03-12 22:32:14 -0800
committerLarry Wall <lwall@netlabs.com>1995-03-12 22:32:14 -0800
commit748a93069b3d16374a9859d1456065dd3ae11394 (patch)
tree308ca14de9933a313dceacce8be77db67d9368c7 /vms/ext
parentfec02dd38faf8f83471b031857d89cb76fea1ca0 (diff)
downloadperl-748a93069b3d16374a9859d1456065dd3ae11394.tar.gz
Perl 5.001perl-5.001
[See the Changes file for a list of changes]
Diffstat (limited to 'vms/ext')
-rw-r--r--vms/ext/Filespec.pm323
-rw-r--r--vms/ext/MM_VMS.pm812
-rw-r--r--vms/ext/VMS/stdio/Makefile.PL3
-rw-r--r--vms/ext/VMS/stdio/stdio.pm78
-rw-r--r--vms/ext/VMS/stdio/stdio.xs109
5 files changed, 1325 insertions, 0 deletions
diff --git a/vms/ext/Filespec.pm b/vms/ext/Filespec.pm
new file mode 100644
index 0000000000..35c8365c4c
--- /dev/null
+++ b/vms/ext/Filespec.pm
@@ -0,0 +1,323 @@
+# Perl hooks into the routines in vms.c for interconversion
+# of VMS and Unix file specification syntax.
+#
+# Version: 1.1
+# Author: Charles Bailey bailey@genetics.upenn.edu
+# Revised: 08-Mar-1995
+
+=head1 NAME
+
+VMS::Filespec - convert between VMS and Unix file specification syntax
+
+=head1 SYNOPSIS
+
+use VMS::Filespec;
+$vmsspec = vmsify('/my/Unix/file/specification');
+$unixspec = unixify('my:[VMS]file.specification');
+$path = pathify('my:[VMS.or.Unix.directory]specification.dir');
+$dirfile = fileify('my:[VMS.or.Unix.directory.specification]');
+$vmsdir = vmspath('my/VMS/or/Unix/directory/specification.dir');
+$unixdir = unixpath('my:[VMS.or.Unix.directory]specification.dir');
+candelete('my:[VMS.or.Unix]file.specification');
+
+=head1 DESCRIPTION
+
+This package provides routines to simplify conversion between VMS and
+Unix syntax when processing file specifications. This is useful when
+porting scripts designed to run under either OS, and also allows you
+to take advantage of conveniences provided by either syntax (e.g.
+ability to easily concatenate Unix-style specifications). In
+addition, it provides an additional file test routine, C<candelete>,
+which determines whether you have delete access to a file.
+
+If you're running under VMS, the routines in this package are special,
+in that they're automatically made available to any Perl script,
+whether you're running F<miniperl> or the full F<perl>. The C<use
+VMS::Filespec> or C<require VMS::Filespec; import VMS::Filespec ...>
+statement can be used to import the function names into the current
+package, but they're always available if you use the fully qualified
+name, whether or not you've mentioned the F<.pm> file in your script.
+If you're running under another OS and have installed this package, it
+behaves like a normal Perl extension (in fact, you're using Perl
+substitutes to emulate the necessary VMS system calls).
+
+Each of these routines accepts a file specification in either VMS or
+Unix syntax, and returns the converted file specification, ir undef if
+an error occurs. The conversions are, for the most part, simply
+string manipulations; the routines do not check the details of syntax
+(e.g. that only legal characters are used). There is one exception:
+when running under VMS, conversions from VMS syntax use the $PARSE
+service to expand specifications, so illegal syntax, or a relative
+directory specification which extends above the tope of the current
+directory path (e.g [---.foo] when in dev:[dir.sub]) will cause
+errors. In general, any legal file specification will be converted
+properly, but garbage input tends to produce garbage output.
+
+The routines provided are:
+
+=head2 vmsify
+
+Converts a file specification to VMS syntax.
+
+=head2 unixify
+
+Converts a file specification to Unix syntax.
+
+=head2 pathify
+
+Converts a directory specification to a path - that is, a string you
+can prepend to a file name to form a valid file specification. If the
+input file specification uses VMS syntax, the returned path does, too;
+likewise for Unix syntax (Unix paths are guaranteed to end with '/').
+
+=head2 fileify
+
+Converts a directory specification to the file specification of the
+directory file - that is, a string you can pass to functions like
+C<stat> or C<rmdir> to manipulate the directory file. If the
+input directory specification uses VMS syntax, the returned file
+specification does, too; likewise for Unix syntax.
+
+=head2 vmspath
+
+Acts like C<pathify>, but insures the returned path uses VMS syntax.
+
+=head2 unixpath
+
+Acts like C<pathify>, but insures the returned path uses Unix syntax.
+
+=head2 candelete
+
+Determines whether you have delete access to a file. If you do, C<candelete>
+returns true. If you don't, or its argument isn't a legal file specification,
+C<candelete> returns FALSE. Unlike other file tests, the argument to
+C<candelete> must be a file name (not a FileHandle), and, since it's an XSUB,
+it's a list operator, so you need to be careful about parentheses. Both of
+these restrictions may be removed in the future if the functionality of
+C<candelete> becomes part of the Perl core.
+
+=head1 REVISION
+
+This document was last revised 08-Mar-1995, for Perl 5.001.
+
+=cut
+
+package VMS::Filespec;
+
+# If you want to use this package on a non-VMS system, uncomment
+# the following line, and add AutoLoader to @ISA.
+# require AutoLoader;
+require Exporter;
+
+@ISA = qw( Exporter );
+@EXPORT = qw( &rmsexpand &vmsify &unixify &pathify
+ &fileify &vmspath &unixpath &candelete);
+
+1;
+
+
+__END__
+
+
+# The autosplit routines here are provided for use by non-VMS systems
+# They are not guaranteed to function identically to the XSUBs of the
+# same name, since they do not have access to the RMS system routine
+# sys$parse() (in particular, no real provision is made for handling
+# of complex DECnet node specifications). However, these routines
+# should be adequate for most purposes.
+
+# A sort-of sys$parse() replacement
+sub rmsexpand {
+ my($fspec,$defaults) = @_;
+ if (!$fspec) { return undef }
+ my($node,$dev,$dir,$name,$type,$ver,$dnode,$ddev,$ddir,$dname,$dtype,$dver);
+
+ $fspec =~ s/:$//;
+ $defaults = [] unless $defaults;
+ $defaults = [ $defaults ] unless ref($defaults) && ref($defaults) eq 'ARRAY';
+
+ while ($fspec !~ m#[:>\]]# && $ENV{$fspec}) { $fspec = $ENV{$fspec} }
+
+ if ($fspec =~ /:/) {
+ my($dev,$devtrn,$base);
+ ($dev,$base) = split(/:/,$fspec);
+ $devtrn = $dev;
+ while ($devtrn = $ENV{$devtrn}) {
+ if ($devtrn =~ /(.)([:>\]])$/) {
+ $dev .= ':', last if $1 eq '.';
+ $dev = $devtrn, last;
+ }
+ }
+ $fspec = $dev . $base;
+ }
+
+ ($node,$dev,$dir,$name,$type,$ver) = $fspec =~
+ /([^:]*::)?([^:]*:)?([^>\]]*[>\]])?([^.;]*)(\.?[^.;]*)([.;]?\d*)/;
+ foreach ((@$defaults,$ENV{'DEFAULT'})) {
+ last if $node && $ver && $type && $dev && $dir && $name;
+ ($dnode,$ddev,$ddir,$dname,$dtype,$dver) =
+ /([^:]*::)?([^:]*:)?([^>\]]*[>\]])?([^.;]*)(\.?[^.;]*)([.;]?\d*)/;
+ $node = $dnode if $dnode && !$node;
+ $dev = $ddev if $ddev && !$dev;
+ $dir = $ddir if $ddir && !$dir;
+ $name = $dname if $dname && !$name;
+ $type = $dtype if $dtype && !$type;
+ $ver = $dver if $dver && !$ver;
+ }
+ # do this the long way to keep -w happy
+ $fspec = '';
+ $fspec .= $node if $node;
+ $fspec .= $dev if $dev;
+ $fspec .= $dir if $dir;
+ $fspec .= $name if $name;
+ $fspec .= $type if $type;
+ $fspec .= $ver if $ver;
+ $fspec;
+}
+
+sub vmsify {
+ my($fspec) = @_;
+ my($hasdev,$dev,$defdirs,$dir,$base,@dirs,@realdirs);
+
+ if ($fspec =~ m#^\.(\.?)/?$#) { return $1 ? '[-]' : '[]'; }
+ return $fspec if $fspec !~ m#/#;
+ ($hasdev,$dir,$base) = $fspec =~ m#(/?)(.*)/(.*)#;
+ @dirs = split(m#/#,$dir);
+ if ($base eq '.') { $base = ''; }
+ elsif ($base eq '..') {
+ push @dirs,$base;
+ $base = '';
+ }
+ foreach (@dirs) {
+ next unless $_; # protect against // in input
+ next if $_ eq '.';
+ if ($_ eq '..') {
+ if (@realdirs && $realdirs[$#realdirs] ne '-') { pop @realdirs }
+ else { push @realdirs, '-' }
+ }
+ else { push @realdirs, $_; }
+ }
+ if ($hasdev) {
+ $dev = shift @realdirs;
+ @realdirs = ('000000') unless @realdirs;
+ $base = '' unless $base; # keep -w happy
+ $dev . ':[' . join('.',@realdirs) . "]$base";
+ }
+ else {
+ '[' . join('',map($_ eq '-' ? $_ : ".$_",@realdirs)) . "]$base";
+ }
+}
+
+sub unixify {
+ my($fspec) = @_;
+
+ return $fspec if $fspec !~ m#[:>\]]#;
+ return '.' if ($fspec eq '[]' || $fspec eq '<>');
+ if ($fspec =~ m#^[<\[](\.|-+)(.*)# ) {
+ $fspec = ($1 eq '.' ? '' : "$1.") . $2;
+ my($dir,$base) = split(/[\]>]/,$fspec);
+ my(@dirs) = grep($_,split(m#\.#,$dir));
+ if ($dirs[0] =~ /^-/) {
+ my($steps) = shift @dirs;
+ for (1..length($steps)) { unshift @dirs, '..'; }
+ }
+ join('/',@dirs) . "/$base";
+ }
+ else {
+ $fspec = rmsexpand($fspec,'_N_O_T_:[_R_E_A_L_]');
+ $fspec =~ s/.*_N_O_T_:(?:\[_R_E_A_L_\])?//;
+ my($dev,$dir,$base) = $fspec =~ m#([^:<\[]*):?[<\[](.*)[>\]](.*)#;
+ my(@dirs) = split(m#\.#,$dir);
+ if ($dirs[0] && $dirs[0] =~ /^-/) {
+ my($steps) = shift @dirs;
+ for (1..length($steps)) { unshift @dirs, '..'; }
+ }
+ "/$dev/" . join('/',@dirs) . "/$base";
+ }
+}
+
+
+sub fileify {
+ my($path) = @_;
+
+ if (!$path) { return undef }
+ if ($path =~ /(.+)\.([^:>\]]*)$/) {
+ $path = $1;
+ if ($2 !~ /^dir(?:;1)?$/i) { return undef }
+ }
+
+ if ($path !~ m#[/>\]]#) {
+ $path =~ s/:$//;
+ while ($ENV{$path}) {
+ ($path = $ENV{$path}) =~ s/:$//;
+ last if $path =~ m#[/>\]]#;
+ }
+ }
+ if ($path =~ m#[>\]]#) {
+ my($dir,$sep,$base) = $path =~ /(.*)([>\]])(.*)/;
+ $sep =~ tr/<[/>]/;
+ if ($base) {
+ "$dir$sep$base.dir;1";
+ }
+ else {
+ if ($dir !~ /\./) { $dir =~ s/([<\[])/${1}000000./; }
+ $dir =~ s#\.(\w+)$#$sep$1#;
+ $dir =~ s/^.$sep//;
+ "$dir.dir;1";
+ }
+ }
+ else {
+ $path =~ s#/$##;
+ "$path.dir;1";
+ }
+}
+
+sub pathify {
+ my($fspec) = @_;
+
+ if (!$fspec) { return undef }
+ if ($fspec =~ m#[/>\]]$#) { return $fspec; }
+ if ($fspec =~ m#(.+)\.([^/>\]]*)$# && $2 && $2 ne '.') {
+ $fspec = $1;
+ if ($2 !~ /^dir(?:;1)?$/i) { return undef }
+ }
+
+ if ($fspec !~ m#[/>\]]#) {
+ $fspec =~ s/:$//;
+ while ($ENV{$fspec}) {
+ if ($ENV{$fspec} =~ m#[>\]]$#) { return $ENV{$fspec} }
+ else { $fspec = $ENV{$fspec} =~ s/:$// }
+ }
+ }
+
+ if ($fspec !~ m#[>\]]#) { "$fspec/"; }
+ else {
+ if ($fspec =~ /([^>\]]+)([>\]])(.+)/) { "$1.$3$2"; }
+ else { $fspec; }
+ }
+}
+
+sub vmspath {
+ pathify(vmsify($_[0]));
+}
+
+sub unixpath {
+ pathify(unixify($_[0]));
+}
+
+sub candelete {
+ my($fspec) = @_;
+ my($parent);
+
+ return '' unless -w $fspec;
+ $fspec =~ s#/$##;
+ if ($fspec =~ m#/#) {
+ ($parent = $fspec) =~ s#/[^/]+$#;
+ return (-w $parent);
+ }
+ elsif ($parent = fileify($fspec)) { # fileify() here to expand lnms
+ $parent =~ s/[>\]][^>\]]+//;
+ return (-w fileify($parent));
+ }
+ else { return (-w '[-]'); }
+}
diff --git a/vms/ext/MM_VMS.pm b/vms/ext/MM_VMS.pm
index 3ef0233d9a..f861d83021 100644
--- a/vms/ext/MM_VMS.pm
+++ b/vms/ext/MM_VMS.pm
@@ -11,6 +11,818 @@ package ExtUtils::MM_VMS;
use Config;
require Exporter;
+use VMS::Filespec;
+use File::Basename;
+
+Exporter::import('ExtUtils::MakeMaker',
+ qw(%att %skip %Recognized_Att_Keys $Verbose &neatvalue));
+
+
+sub fixpath {
+ my($path) = @_;
+ my($head,$macro,$tail);
+
+ while (($head,$macro,$tail) = ($path =~ m#(.*?)\$\((\S+?)\)/(.*)#)) {
+ ($macro = unixify($att{$macro})) =~ s#/$##;
+ $path = "$head$macro/$tail";
+ }
+ vmsify($path);
+}
+
+
+sub init_others {
+ &MM_Unix::init_others;
+ $att{NOOP} = "\tContinue";
+ $att{MAKEFILE} = '$(MAKEFILE)';
+ $att{RM_F} = '$(PERL) -e "foreach (@ARGV) { -d $_ ? rmdir $_ : unlink $_}"';
+ $att{RM_RF} = '$(PERL) -e "use File::Path; use VMS::Filespec; @dirs = map(unixify($_),@ARGV); rmtree(\@dirs,0,0)"';
+ $att{TOUCH} = '$(PERL) -e "$t=time; utime $t,$t,@ARGV"';
+ $att{CP} = 'Copy/NoConfirm';
+ $att{MV} = 'Rename/NoConfirm';
+}
+
+sub constants {
+ my(@m,$def);
+ push @m, "
+NAME = $att{NAME}
+DISTNAME = $att{DISTNAME}
+VERSION = $att{VERSION}
+
+# In which library should we install this extension?
+# This is typically the same as PERL_LIB.
+# (also see INST_LIBDIR and relationship to ROOTEXT)
+INST_LIB = ",vmspath($att{INST_LIB}),"
+INST_ARCHLIB = ",vmspath($att{INST_ARCHLIB}),"
+INST_EXE = ",vmspath($att{INST_EXE}),"
+
+# Perl library to use when building the extension
+PERL_LIB = ",vmspath($att{PERL_LIB}),"
+PERL_ARCHLIB = ",vmspath($att{PERL_ARCHLIB}),"
+LIBPERL_A = ",vmsify($att{LIBPERL_A}),"
+";
+
+# Define I_PERL_LIBS to include the required -Ipaths
+# To be cute we only include PERL_ARCHLIB if different
+# To be portable we add quotes for VMS
+my(@i_perl_libs) = qw{-I$(PERL_ARCHLIB) -I$(PERL_LIB)};
+shift(@i_perl_libs) if ($att{PERL_ARCHLIB} eq $att{PERL_LIB});
+push @m, "I_PERL_LIBS = \"".join('" "',@i_perl_libs)."\"\n";
+
+if ($att{PERL_SRC}) {
+ push @m, "
+# Where is the perl source code located?
+PERL_SRC = ",vmspath($att{PERL_SRC});
+}
+ push @m,"
+# Perl header files (will eventually be under PERL_LIB)
+PERL_INC = ",vmspath($att{PERL_INC}),"
+# Perl binaries
+PERL = $att{PERL}
+FULLPERL = $att{FULLPERL}
+
+# FULLEXT = Pathname for extension directory (eg DBD/Oracle).
+# BASEEXT = Basename part of FULLEXT. May be just equal FULLEXT.
+# ROOTEXT = Directory part of FULLEXT with leading slash (e.g /DBD)
+FULLEXT = ",vmsify($att{FULLEXT}),"
+BASEEXT = $att{BASEEXT}
+ROOTEXT = ",($att{ROOTEXT} eq '') ? '[]' : vmspath($att{ROOTEXT}),"
+
+INC = ";
+
+ if ($att{'INC'}) {
+ push @m,'/Include=(';
+ my(@includes) = split(/\s+/,$att{INC});
+ foreach (@includes) {
+ s/^-I//;
+ push @m,vmspath($_);
+ }
+ push @m, ")\n";
+ }
+
+ if ($att{DEFINE} ne '') {
+ my(@defs) = split(/\s+/,$att{DEFINE});
+ foreach $def (@defs) {
+ $def =~ s/^-D//;
+ $def = "\"$def\"" if $def =~ /=/;
+ }
+ $att{DEFINE} = join ',',@defs;
+ }
+
+ push @m,"
+DEFINE = $att{DEFINE}
+OBJECT = ",vmsify($att{OBJECT}),"
+LDFROM = ",vmsify($att{LDFROM}),"
+LINKTYPE = $att{LINKTYPE}
+
+# Handy lists of source code files:
+XS_FILES = ",join(', ', sort keys %{$att{XS}}),"
+C_FILES = ",join(', ', @{$att{C}}),"
+O_FILES = ",join(', ', @{$att{O_FILES}}),"
+H_FILES = ",join(', ', @{$att{H}}),"
+
+.SUFFIXES : .xs
+
+# This extension may link to it's own library (see SDBM_File)";
+ push @m,"
+MYEXTLIB = ",vmsify($att{MYEXTLIB}),"
+
+# Here is the Config.pm that we are using/depend on
+CONFIGDEP = \$(PERL_ARCHLIB)Config.pm, \$(PERL_INC)config.h
+
+# Where to put things:
+INST_LIBDIR = ",($att{'INST_LIBDIR'} = vmspath(unixpath($att{INST_LIB}) . unixpath($att{ROOTEXT}))),"
+INST_ARCHLIBDIR = ",($att{'INST_ARCHLIBDIR'} = vmspath(unixpath($att{INST_ARCHLIB}) . unixpath($att{ROOTEXT}))),"
+
+INST_AUTODIR = ",($att{'INST_AUTODIR'} = vmspath(unixpath($att{INST_LIB}) . 'auto/' . unixpath($att{FULLEXT}))),'
+INST_ARCHAUTODIR = ',($att{'INST_ARCHAUTODIR'} = vmspath(unixpath($att{INST_ARCHLIB}) . 'auto/' . unixpath($att{FULLEXT}))),'
+
+INST_STATIC = $(INST_ARCHAUTODIR)$(BASEEXT).olb
+INST_DYNAMIC = $(INST_ARCHAUTODIR)$(BASEEXT).$(DLEXT)
+INST_BOOT = $(INST_ARCHAUTODIR)$(BASEEXT).bs
+INST_PM = ',join(', ',map(fixpath($_),sort values %{$att{PM}})),'
+';
+
+ join('',@m);
+}
+
+
+sub const_cccmd {
+ my($cmd) = $Config{'cc'};
+ my($name,$sys,@m);
+
+ ( $name = $att{NAME} . "_cflags" ) =~ s/:/_/g ;
+ print STDOUT "Unix shell script ".$Config{"$att{'BASEEXT'}_cflags"}.
+ " required to modify CC command for $att{'BASEEXT'}\n"
+ if ($Config{$name});
+
+ # Deal with $att{DEFINE} here since some C compilers pay attention
+ # to only one /Define clause on command line, so we have to
+ # conflate the ones from $Config{'cc'} and $att{DEFINE}
+ if ($att{DEFINE} ne '') {
+ if ($cmd =~ m:/define=\(?([^\(\/\)]+)\)?:i) {
+ $cmd = $` . "/Define=(" . $1 . ",$att{DEFINE})" . $';
+ }
+ else { $cmd .= "/Define=($att{DEFINE})" }
+ }
+
+ $sys = ($cmd =~ /^gcc/i) ? 'GNU_CC_Include:[VMS]' : 'Sys$Library';
+ push @m,'
+.FIRST
+ @ If F$TrnLnm("Sys").eqs."" Then Define/NoLog SYS ',$sys,'
+
+';
+ push(@m, "CCCMD = $cmd\n");
+
+ join('',@m);
+}
+
+
+
+sub const_loadlibs{
+ my (@m);
+ push @m, "
+# $att{NAME} might depend on some other libraries.
+#
+# Dependent libraries are linked in either by the Link command
+# at build time or by the DynaLoader at bootstrap time.
+#
+# These comments may need revising:
+#
+# EXTRALIBS = Full list of libraries needed for static linking.
+# Only those libraries that actually exist are included.
+#
+# BSLOADLIBS = List of those libraries that are needed but can be
+# linked in dynamically.
+#
+# LDLOADLIBS = List of those libraries which must be statically
+# linked into the shared library.
+#
+EXTRALIBS = ",map(vmsify($_) . ' ',$att{'EXTRALIBS'}),"
+BSLOADLIBS = ",map(vmsify($_) . ' ',$att{'BSLOADLIBS'}),"
+LDLOADLIBS = ",map(vmsify($_) . ' ',$att{'LDLOADLIBS'}),"\n";
+
+ join('',@m);
+}
+
+# --- Tool Sections ---
+
+sub tool_autosplit{
+ my($self, %attribs) = @_;
+ my($asl) = "";
+ $asl = "\$AutoSplit::Maxlen=$attribs{MAXLEN};" if $attribs{MAXLEN};
+ q{
+# Usage: $(AUTOSPLITFILE) FileToSplit AutoDirToSplitInto
+AUTOSPLITFILE = $(PERL) $(I_PERL_LIBS) -e "use AutoSplit;}.$asl.q{ AutoSplit::autosplit($ARGV[0], $ARGV[1], 0, 1, 1) ;"
+};
+}
+
+sub tool_xsubpp{
+ my($xsdir) = unixpath($att{PERL_LIB}).'ExtUtils';
+ # drop back to old location if xsubpp is not in new location yet
+ $xsdir = unixpath($att{PERL_SRC}).'ext' unless (-f "$xsdir/xsubpp");
+ my(@tmdeps) = '$(XSUBPPDIR)typemap';
+ push(@tmdeps, "typemap") if -f "typemap";
+ my(@tmargs) = map("-typemap $_", @tmdeps);
+ "
+XSUBPPDIR = ".vmspath($xsdir)."
+XSUBPP = \$(PERL) \$(XSUBPPDIR)xsubpp
+XSUBPPDEPS = @tmdeps
+XSUBPPARGS = @tmargs
+";
+}
+
+sub tools_other {
+ "
+# Assumes \$(MMS) invokes MMS or MMK
+USEMAKEFILE = /Descrip=
+USEMACROS = /Macro=(
+MACROEND = )
+MAKEFILE = Descrip.MMS
+SHELL = Posix
+LD = $att{LD}
+TOUCH = $att{TOUCH}
+CP = $att{CP}
+RM_F = $att{RM_F}
+RM_RF = $att{RM_RF}
+MKPATH = Create/Directory
+";
+}
+
+
+# --- Translation Sections ---
+
+sub c_o {
+ '
+.c.obj :
+ $(CCCMD) $(CCCDLFLAGS) /Include=($(PERL_INC)) $(INC) $(MMS$TARGET_NAME).c
+';
+}
+
+sub xs_c {
+ '
+.xs.c :
+ $(XSUBPP) $(XSUBPPARGS) $(MMS$TARGET_NAME).xs >$(MMS$TARGET)
+';
+}
+
+sub xs_o { # many makes are too dumb to use xs_c then c_o
+ '
+.xs.obj :
+ $(XSUBPP) $(XSUBPPARGS) $(MMS$TARGET_NAME).xs >$(MMS$TARGET_NAME).c
+ $(CCCMD) $(CCCDLFLAGS) /Include=($(PERL_INC)) $(INC) $(MMS$TARGET_NAME).c
+';
+}
+
+
+# --- Target Sections ---
+
+sub top_targets{
+ my(@m);
+ push @m, '
+all :: config linkext $(INST_PM)
+'.$att{NOOP}.'
+
+config :: '.$att{MAKEFILE}.'
+ @ $(MKPATH) $(INST_LIBDIR), $(INST_ARCHAUTODIR)
+';
+ push @m, '
+$(O_FILES) : $(H_FILES)
+' if @{$att{O_FILES} || []} && @{$att{H} || []};
+ join('',@m);
+}
+
+sub dlsyms {
+ my($self,%attribs) = @_;
+ my($funcs) = $attribs{DL_FUNCS} || $att{DL_FUNCS} || {};
+ my($vars) = $attribs{DL_VARS} || $att{DL_VARS} || [];
+ my(@m);
+
+ push(@m,'
+dynamic :: perlshr.opt $(BASEEXT).opt
+ ',$att{NOOP},'
+
+perlshr.opt : makefile.PL
+ $(PERL) -e "open O,\'>perlshr.opt\'; print O ""PerlShr/Share\n""; close O"
+') unless $skip{'dynamic'};
+
+ push(@m,'
+static :: $(BASEEXT).opt
+ ',$att{NOOP},'
+') unless $skip{'static'};
+
+ push(@m,'
+$(BASEEXT).opt : makefile.PL
+ $(PERL) $(I_PERL_LIBS) -e "use ExtUtils::MakeMaker; mksymlists(DL_FUNCS => ',neatvalue($att{DL_FUNCS}),', DL_VARS => ',neatvalue($att{DL_VARS}),',NAME => ',$att{NAME},')"
+ $(PERL) $(I_PERL_LIBS) -e "open OPT,\'>>$(MMS$TARGET)\'; print OPT ""$(INST_STATIC)/Include=$(BASEEXT)\n$(INST_STATIC)/Library\n"";close OPT"
+');
+
+ join('',@m);
+}
+
+
+# --- Dynamic Loading Sections ---
+
+sub dynamic_lib {
+ my($self, %attribs) = @_;
+ my($otherldflags) = $attribs{OTHERLDFLAGS} || "";
+ my(@m);
+ push @m,"
+
+OTHERLDFLAGS = $otherldflags
+
+";
+ push @m, '
+$(INST_DYNAMIC) : $(INST_STATIC) $(PERL_INC)perlshr_attr.opt perlshr.opt $(BASEEXT).opt
+ @ $(MKPATH) $(INST_ARCHAUTODIR)
+ Link $(LDFLAGS) /Shareable=$(MMS$TARGET)$(OTHERLDFLAGS) $(BASEEXT).opt/Option,perlshr.opt/Option,$(PERL_INC)perlshr_attr.opt/Option
+';
+
+ join('',@m);
+}
+
+sub dynamic_bs {
+ my($self, %attribs) = @_;
+ '
+BOOTSTRAP = '."$att{BASEEXT}.bs".'
+
+# As MakeMaker mkbootstrap might not write a file (if none is required)
+# we use touch to prevent make continually trying to remake it.
+# The DynaLoader only reads a non-empty file.
+$(BOOTSTRAP): '."$att{MAKEFILE} $att{BOOTDEP}".'
+ @ Write Sys$Output "Running mkbootstrap for $(NAME) ($(BSLOADLIBS))"
+ @ $(PERL) $(I_PERL_LIBS) -e "use ExtUtils::MakeMaker; &mkbootstrap(""$(BSLOADLIBS)"");" "INST_LIB=$(INST_LIB)" "INST_ARCHLIB=$(INST_ARCHLIB)" "PERL_SRC=$(PERL_SRC)" "NAME=$(NAME)"
+ @ $(TOUCH) $(BOOTSTRAP)
+
+$(INST_BOOT): $(BOOTSTRAP)
+ @ '.$att{RM_RF}.' $(INST_BOOT)
+ - '.$att{CP}.' $(BOOTSTRAP) $(INST_BOOT)
+';
+}
+# --- Static Loading Sections ---
+
+sub static_lib {
+ '
+$(INST_STATIC) : $(OBJECT), $(MYEXTLIB)
+ @ $(MKPATH) $(INST_ARCHAUTODIR)
+ If F$Search("$(MMS$TARGET)").eqs."" Then Library/Object/Create $(MMS$TARGET)
+ Library/Object/Replace $(MMS$TARGET) $(MMS$SOURCE_LIST)
+';
+}
+
+
+sub installpm_x { # called by installpm perl file
+ my($self, $dist, $inst, $splitlib) = @_;
+ $inst = fixpath($inst);
+ $dist = vmsify($dist);
+ my($instdir) = dirname($inst);
+ my(@m);
+
+ push(@m, "
+$inst : $dist $att{MAKEFILE}
+",' @ ',$att{RM_F},' $(MMS$TARGET);*
+ @ $(MKPATH) ',$instdir,'
+ @ ',$att{CP},' $(MMS$SOURCE) $(MMS$TARGET)
+');
+ if ($splitlib and $inst =~ /\.pm$/) {
+ my($attdir) = $splitlib;
+ $attdir =~ s/\$\((.*)\)/$1/;
+ $attdir = $att{$attdir} if $att{$attdir};
+
+ push(@m, ' $(AUTOSPLITFILE) $(MMS$TARGET) ',
+ vmspath(unixpath($attdir) . 'auto')."\n");
+ push(@m,"\n");
+ }
+
+ join('',@m);
+}
+
+
+# --- Sub-directory Sections ---
+
+sub exescan {
+ vmsify($_);
+}
+
+sub subdir_x {
+ my($self, $subdir) = @_;
+ my(@m);
+ # The intention is that the calling Makefile.PL should define the
+ # $(SUBDIR_MAKEFILE_PL_ARGS) make macro to contain whatever
+ # information needs to be passed down to the other Makefile.PL scripts.
+ # If this does not suit your needs you'll need to write your own
+ # MY::subdir_x() method to override this one.
+ push @m, '
+config :: ',vmspath($subdir) . '$(MAKEFILE)
+ $(MMS) $(USEMAKEFILE) $(MMS$SOURCE) config $(USEMACROS)(INST_LIB=$(INST_LIB),INST_ARCHLIB=$(INST_ARCHLIB), \\
+ LINKTYPE=$(LINKTYPE),INST_EXE=$(INST_EXE),LIBPERL_A=$(LIBPERL_A)$(MACROEND) $(SUBDIR_MAKEFILE_PL_ARGS)
+
+',vmspath($subdir),'$(MAKEFILE) : ',vmspath($subdir),'Makefile.PL, $(CONFIGDEP)
+ @Write Sys$Output "Rebuilding $(MMS$TARGET) ..."
+ $(PERL) "-I$(PERL_ARCHLIB)" "-I$(PERL_LIB)" -e "use ExtUtils::MakeMaker; MM->runsubdirpl(qw('.$subdir.'))" \\
+ $(SUBDIR_MAKEFILE_PL_ARGS) INST_LIB=$(INST_LIB) INST_ARCHLIB=$(INST_ARCHLIB) \\
+ INST_EXE=$(INST_EXE) LIBPERL_A=$(LIBPERL_A) LINKTYPE=$(LINKTYPE)
+ @Write Sys$Output "Rebuild of $(MMS$TARGET) complete."
+
+# The default clean, realclean and test targets in this Makefile
+# have automatically been given entries for $subdir.
+
+subdirs ::
+ Set Default ',vmspath($subdir),'
+ $(MMS) all $(USEMACROS)LINKTYPE=$(LINKTYPE)$(MACROEND)
+';
+ join('',@m);
+}
+
+
+# --- Cleanup and Distribution Sections ---
+
+sub clean {
+ my($self, %attribs) = @_;
+ my(@m);
+ push @m, '
+# Delete temporary files but do not touch installed files
+# We don\'t delete the Makefile here so that a
+# later make realclean still has a makefile to work from
+clean ::
+';
+ foreach (@{$att{DIR}}) { # clean subdirectories first
+ my($vmsdir) = vmspath($_);
+ push( @m, ' If F$Search("'.$vmsdir.'$(MAKEFILE)") Then $(MMS) $(USEMAKEFILE)'.$vmsdir.'$(MAKEFILE) clean'."\n");
+ }
+ push @m, "
+ $att{RM_F} *.Map;* *.lis;* *.cpp;* *.Obj;* *.Olb;* \$(BOOTSTRAP);* \$(BASEEXT).bso;*
+";
+
+ my(@otherfiles) = values %{$att{XS}}; # .c files from *.xs files
+ push(@otherfiles, $attribs{FILES}) if $attribs{FILES};
+ push(@otherfiles, "blib.dir");
+ push(@m, " $att{RM_F} ".join(";* ", map(fixpath($_),@otherfiles)),";*\n");
+ # See realclean and ext/utils/make_ext for usage of Makefile.old
+ push(@m, " $att{MV} $att{MAKEFILE} $att{MAKEFILE}_old");
+ push(@m, " $attribs{POSTOP}\n") if $attribs{POSTOP};
+ join('', @m);
+}
+
+
+sub realclean {
+ my($self, %attribs) = @_;
+ my(@m);
+ push(@m,'
+# Delete temporary files (via clean) and also delete installed files
+realclean :: clean
+');
+ foreach(@{$att{DIR}}){
+ my($vmsdir) = vmspath($_);
+ push(@m, ' If F$Search("'."$vmsdir$att{MAKEFILE}".'").nes."" Then $(MMS) $(USEMAKEFILE)'."$vmsdir$att{MAKEFILE}".' realclean'."\n");
+ push(@m, ' If F$Search("'."$vmsdir$att{MAKEFILE}".'_old").nes."" Then $(MMS) $(USEMAKEFILE)'."$vmsdir$att{MAKEFILE}".'_old realclean'."\n");
+ }
+ push @m,'
+ ',$att{RM_RF},' $(INST_AUTODIR) $(INST_ARCHAUTODIR)
+ ',$att{RM_F},' *.Opt;* $(INST_DYNAMIC);* $(INST_STATIC);* $(INST_BOOT);* $(INST_PM);*
+ ',$att{RM_F},' $(OBJECT);* $(MAKEFILE);* $(MAKEFILE)_old;*
+';
+ push(@m, " $att{RM_RF} ".join(";* ", map(fixpath($_),$attribs{'FILES'})),";*\n") if $attribs{'FILES'};
+ push(@m, " $attribs{POSTOP}\n") if $attribs{POSTOP};
+ join('', @m);
+}
+
+
+sub distclean {
+ my($self, %attribs) = @_;
+ my($preop) = $attribs{PREOP} || '@ !'; # e.g., update MANIFEST
+ my($zipname) = $attribs{TARNAME} || '$(DISTNAME)-$(VERSION)';
+ my($zipflags) = $attribs{ZIPFLAGS} || '-Vu';
+ my($postop) = $attribs{POSTOP} || "";
+ my($mkfiles) = join(' ', map("$_\$(MAKEFILE) $_\$(MAKEFILE)_old",map(vmspath($_),@{$att{'DIR'}})));
+
+ "
+distclean : clean
+ $preop
+ $att{RM_F} $mkfiles
+ Zip \"$zipflags\" $zipname \$(BASEEXT).* Makefile.PL
+ $postop
+";
+}
+
+
+# --- Test and Installation Sections ---
+
+sub test {
+ my($self, %attribs) = @_;
+ my($tests) = $attribs{TESTS} || ( -d 't' ? 't/*.t' : '');
+ my(@m);
+ push @m,'
+test : all
+';
+ push(@m,' $(PERL) "-I$(INST_ARCHLIB)" "-I$(INST_LIB)" $(I_PERL_LIBS) -e "use Test::Harness; runtests @ARGV;" '.$tests."\n")
+ if $tests;
+ push(@m,' $(PERL) "-I$(INST_ARCHLIB)" "-I$(INST_LIB)" $(I_PERL_LIBS) test.pl',"\n")
+ if -f 'test.pl';
+ foreach(@{$att{DIR}}){
+ my($vmsdir) = vmspath($_);
+ push(@m, ' If F$Search("',$vmsdir,'$(MAKEFILE)").nes."" Then $(PERL) -e "chdir \'',$vmsdir,
+ '\'; print `$(MMS) $(USEMAKEFILE)$(MAKEFILE) $(USEMACRO)LINKTYPE=$(LINKTYPE)$(MACROEND) test`'."\n");
+ }
+ push(@m, "\t\@echo 'No tests defined for \$(NAME) extension.'\n") unless @m > 1;
+
+ join('',@m);
+}
+
+sub install {
+ my($self, %attribs) = @_;
+ my(@m);
+ push @m, q{
+doc_install ::
+ @ $(PERL) "-I$(INST_ARCHLIB)" "-I$(INST_LIB)" $(I_PERL_LIBS) \\
+ -e "use ExtUtils::MakeMaker; MM->writedoc('Module', '$(NAME)', \\
+ 'LINKTYPE=$(LINKTYPE)', 'VERSION=$(VERSION)', 'EXE_FILES=$(EXE_FILES)')"
+};
+
+ push(@m, "
+install :: pure_install doc_install
+
+pure_install :: all
+");
+ # install subdirectories first
+ foreach(@{$att{DIR}}){
+ my($vmsdir) = vmspath($_);
+ push(@m, ' If F$Search("',$vmsdir,'$(MAKEFILE)").nes."" Then $(PERL) -e "chdir \'',$vmsdir,
+ '\'; print `$(MMS) $(USEMAKEFILE)$(MAKEFILE) install`'."\n");
+ }
+
+ push(@m, "\t! perl5.000 used to autosplit into INST_ARCHLIB, we delete these old files here
+ $att{RM_F} ",fixpath(unixpath($Config{'installarchlib'}).'auto/$(FULLEXT)/*.al'),';* ',
+ fixpath(unixpath($Config{'installarchlib'}).'auto/$(FULLEXT)/*.ix'),";*
+ \$(MMS) \$(USEMACROS)INST_LIB=$Config{'installprivlib'},INST_ARCHLIB=$Config{'installarchlib'},INST_EXE=$Config{'installbin'}\$(MACROEND)
+");
+
+ join("",@m);
+}
+
+sub perldepend {
+ my(@m);
+
+ push @m, '
+$(OBJECT) : $(PERL_INC)EXTERN.h, $(PERL_INC)INTERN.h, $(PERL_INC)XSUB.h, $(PERL_INC)av.h
+$(OBJECT) : $(PERL_INC)cop.h, $(PERL_INC)cv.h, $(PERL_INC)embed.h, $(PERL_INC)form.h
+$(OBJECT) : $(PERL_INC)gv.h, $(PERL_INC)handy.h, $(PERL_INC)hv.h, $(PERL_INC)keywords.h
+$(OBJECT) : $(PERL_INC)mg.h, $(PERL_INC)op.h, $(PERL_INC)opcode.h, $(PERL_INC)patchlevel.h
+$(OBJECT) : $(PERL_INC)perl.h, $(PERL_INC)perly.h, $(PERL_INC)pp.h, $(PERL_INC)proto.h
+$(OBJECT) : $(PERL_INC)regcomp.h, $(PERL_INC)regexp.h, $(PERL_INC)scope.h, $(PERL_INC)sv.h
+$(OBJECT) : $(PERL_INC)vmsish.h, $(PERL_INC)util.h, $(PERL_INC)config.h
+
+';
+ push(@m,'
+
+$(PERL_ARCHLIB)/Config.pm: $(PERL_SRC)/config.sh
+ @ Write Sys$Error "$(PERL_ARCHLIB)/Config.pm may be out of date with $(PERL_SRC)/config.sh"
+ Set Default $(PERL_SRC)
+ $(MMS) $(USEMAKEFILE)[.VMS]$(MAKEFILE) [.lib]config.pm
+');
+
+ push(@m, join(" ", map(vmsify($_),values %{$att{XS}}))." : \$(XSUBPPDEPS)\n")
+ if %{$att{XS}};
+
+ join('',@m);
+}
+
+sub makefile {
+ my(@m,@cmd);
+ push(@m,'
+
+# We take a very conservative approach here, but it\'s worth it.
+# We move $(MAKEFILE) to $(MAKEFILE)_old here to avoid gnu make looping.
+$(MAKEFILE) : Makefile.PL $(CONFIGDEP)
+ @ Write Sys$Output "',$att{MAKEFILE},' out-of-date with respect to $(MMS$SOURCE_LIST)"
+ @ Write Sys$Output "Cleaning current config before rebuilding ',$att{MAKEFILE},'...
+ - ',"$att{MV} $att{MAKEFILE} $att{MAKEFILE}_old",'
+ - $(MMS) $(USEMAKEFILE)',$att{MAKEFILE},'_old clean
+ $(PERL) $(I_PERL_LIBS) Makefile.PL
+ @ Write Sys$Output "Now you must rerun $(MMS)."
+');
+
+ join('',@m);
+}
+
+
+# --- Determine libraries to use and how to use them ---
+
+sub makeaperl {
+ my($self, %attribs) = @_;
+ my($makefilename, $searchdirs, $static, $extra, $perlinc, $target, $tmp, $libperl) =
+ @attribs{qw(MAKE DIRS STAT EXTRA INCL TARGET TMP LIBPERL)};
+ my(@m);
+ my($linkcmd,@staticopts,@staticpkgs,$extralist,$target,$targdir,$libperldir);
+
+ # The front matter of the linkcommand...
+ $linkcmd = join ' ', $Config{'ld'},
+ grep($_, @Config{qw(large split ldflags ccdlflags)});
+ $linkcmd =~ s/\s+/ /g;
+
+ # Which *.olb files could we make use of...
+ local(%olbs);
+ File::Find::find(sub {
+ return unless m/\.olb$/;
+ return if m/^libperl/;
+ $olbs{$ENV{DEFAULT}} = $_;
+ }, grep( -d $_, @{$searchdirs || []}), grep( -f $_, @{$static || []}) );
+
+ $extra = [] unless $extra && ref $extra eq 'ARRAY';
+ # Sort the object libraries in inverse order of
+ # filespec length to try to insure that dependent extensions
+ # will appear before their parents, so the linker will
+ # search the parent library to resolve references.
+ # (e.g. Intuit::DWIM will precede Intuit, so unresolved
+ # references from [.intuit.dwim]dwim.obj can be found
+ # in [.intuit]intuit.olb).
+ for (sort keys %olbs) {
+ next unless $olbs{$_} =~ /\.olb$/;
+ my($dir) = vmspath($_);
+ my($extralibs) = $dir . "extralibs.ld";
+ my($extopt) = $dir . $olbs{$_};
+ $extopt =~ s/\.olb$/.opt/;
+ if (-f $extralibs ) {
+ open LIST,$extralibs or warn $!,next;
+ push @$extra, <LIST>;
+ close LIST;
+ }
+ if (-f $extopt) {
+ open OPT,$extopt or die $!;
+ while (<OPT>) {
+ next unless /(?:UNIVERSAL|VECTOR)=boot_([\w_]+)/;
+ # ExtUtils::Miniperl expects Unix paths
+ (my($pkg) = "$2_$2.a") =~ s#_*#/#g;
+ push @staticpkgs,$pkg;
+ }
+ push @staticopts, $extopt;
+ }
+ }
+
+ $target = "Perl.Exe" unless $target;
+ ($shrtarget,$targdir) = fileparse($target);
+ $shrtarget =~ s/^([^.]*)/$1Shr/;
+ $shrtarget = $targdir . $shrtarget;
+ $target = "Perlshr$Config{'dlext'}" unless $target;
+ $tmp = "[]" unless $tmp;
+ $tmp = unixpath($tmp);
+ if (@$extra) {
+ $extralist = join(' ',@$extra);
+ $extralist =~ s/[,\s\n]+/, /g;
+ }
+ else { $extralist = ''; }
+ if ($libperl) {
+ unless (-f $libperl || -f ($libperl = unixpath($Config{'installarchlib'})."CORE/$libperl")){
+ print STDOUT "Warning: $libperl not found";
+ undef $libperl;
+ }
+ }
+ unless ($libperl) {
+ if (defined $att{PERL_SRC}) {
+ $libperl = "$att{PERL_SRC}/libperl.olb";
+ } elsif ( -f ( $libperl = unixpath($Config{'installarchlib'}).'CORE/libperl.olb' )) {
+ } else {
+ print STDOUT "Warning: $libperl not found";
+ }
+ }
+ $libperldir = vmspath((fileparse($libperl))[1]);
+
+ push @m, '
+# Fill in the target you want to produce if it\'s not perl
+MAP_TARGET = ',vmsify($target),'
+MAP_SHRTARGET = ',vmsify($shrtarget),"
+FULLPERL = $att{'FULLPERL'}
+MAP_LINKCMD = $linkcmd
+MAP_PERLINC = ", $perlinc ? map('"-I'.vmspath($_).'" ',@{$perlinc}) : '$(I_PERL_LIB)','
+# We use the linker options files created with each extension, rather than
+#specifying the object files directly on the command line.
+MAP_STATIC = ',@staticopts ? join(' ', @staticopts) : '','
+MAP_OPTS = ',@staticopts ? ','.join(',', map($_.'/Option', @staticopts)) : '',"
+MAP_EXTRA = $extralist
+MAP_LIBPERL = ",vmsify($libperl),'
+';
+
+
+ push @m,'
+$(MAP_SHRTARGET) : $(MAP_LIBPERL) $(MAP_STATIC) ',"${libperldir}Perlshr_Attr.Opt",'
+ $(MAP_LINKCMD)/Shareable=$(MMS$TARGET) $(MAP_OPTS), $(MAP_EXTRA), $(MAP_LIBPERL) ',"${libperldir}Perlshr_Attr.Opt",'
+$(MAP_TARGET) : $(MAP_SHRTARGET) ',vmsify("${tmp}perlmain.obj"),' ',vmsify("${tmp}PerlShr.Opt"),'
+ $(MAP_LINKCMD) ',vmsify("${tmp}perlmain.obj"),', PerlShr.Opt/Option
+ @ Write Sys$Output "To install the new ""$(MAP_TARGET)"" binary, say"
+ @ Write Sys$Output " $(MMS)$(USEMAKEFILE)$(MAKEFILE) inst_perl $(USEMACROS)MAP_TARGET=$(MAP_TARGET)$(ENDMACRO)"
+ @ Write Sys$Output "To remove the intermediate files, say
+ @ Write Sys$Output " $(MMS)$(USEMAKEFILE)$(MAKEFILE) map_clean"
+';
+ push @m,'
+',vmsify("${tmp}perlmain.c"),' : $(MAKEFILE)
+ @ $(PERL) $(MAP_PERLINC) -e "use ExtUtils::Miniperl; writemain(qw|',@staticpkgs,'|)" >$(MMS$TARGET)
+';
+
+ push @m, q{
+doc_inst_perl :
+ @ $(PERL) -e "use ExtUtils::MakeMaker; MM->writedoc('Perl binary','$(MAP_TARGET)','MAP_STATIC=$(MAP_STATIC)','MAP_EXTRA=$(MAP_EXTRA)','MAP_LIBPERL=$(MAP_LIBPERL)')"
+};
+
+ push @m, "
+inst_perl : pure_inst_perl doc_inst_perl
+
+pure_inst_perl : \$(MAP_TARGET)
+ $att{CP} \$(MAP_SHRTARGET) ",vmspath($Config{'installbin'}),"
+ $att{CP} \$(MAP_TARGET) ",vmspath($Config{'installbin'}),"
+
+map_clean :
+ $att{RM_F} ",vmsify("${tmp}perlmain.obj"),vmsify("${tmp}perlmain.c"),
+ vmsify("${tmp}PerlShr.Opt")," $makefilename
+";
+
+ join '', @m;
+}
+
+sub extliblist {
+ '','','';
+}
+
+sub old_extliblist {
+ '','',''
+}
+
+sub new_extliblist {
+ '','',''
+}
+
+# --- Write a DynaLoader bootstrap file if required
+
+# VMS doesn't require a bootstrap file as a rule
+sub mkbootstrap {
+ 1;
+}
+
+sub mksymlists {
+ my($self,%attribs) = @_;
+
+ MY->init_main() unless $att{BASEEXT};
+
+ my($vars) = $attribs{DL_VARS} || $att{DL_VARS} || [];
+ my($procs) = $attribs{DL_FUNCS} || $att{DL_FUNCS};
+ my($package,$packprefix,$sym);
+ if (!%$procs) {
+ $package = $attribs{NAME} || $att{NAME};
+ $package =~ s/\W/_/g;
+ $procs = { $package => ["boot_$package"] };
+ }
+ my($isvax) = $Config{'arch'} =~ /VAX/i;
+
+ # Options file declaring universal symbols
+ # Used when linking shareable image for dynamic extension,
+ # or when linking PerlShr into which we've added this package
+ # as a static extension
+ # We don't do anything to preserve order, so we won't relax
+ # the GSMATCH criteria for a dynamic extension
+ open OPT, ">$att{BASEEXT}.opt";
+ foreach $package (keys %$procs) {
+ ($packprefix = $package) =~ s/\W/_/g;
+ foreach $sym (@{$$procs{$package}}) {
+ $sym = "XS_${packprefix}_$sym" unless $sym =~ /^boot_/;
+ if ($isvax) { print OPT "UNIVERSAL=$sym\n" }
+ else { print OPT "SYMBOL_VECTOR=($sym=PROCEDURE)\n"; }
+ }
+ }
+ foreach $sym (@$vars) {
+ print OPT "PSECT_ATTR=${sym},PIC,OVR,RD,NOEXE,WRT,NOSHR\n";
+ if ($isvax) { print OPT "UNIVERSAL=$sym\n" }
+ else { print OPT "SYMBOL_VECTOR=($sym=DATA)\n"; }
+ }
+ close OPT;
+}
+
+# --- Output postprocessing section ---
+
+sub nicetext {
+ # Insure that colons marking targets are preceded by space -
+ # most Unix Makes don't need this, but it's necessary under VMS
+ # to distinguish the target delimiter from a colon appearing as
+ # part of a filespec.
+
+ my($self,$text) = @_;
+ $text =~ s/([^\s:])(:+\s)/$1 $2/gs;
+ $text;
+}
+
+1;
+
+__END__
+# MM_VMS.pm
+# MakeMaker default methods for VMS
+# This package is inserted into @ISA of MakeMaker's MM before the
+# built-in MM_Unix methods if MakeMaker.pm is run under VMS.
+#
+# Version: 4.03
+# Author: Charles Bailey bailey@genetics.upenn.edu
+# Revised: 30-Jan-1995
+
+package ExtUtils::MM_VMS;
+
+use Config;
+require Exporter;
use File::VMSspec;
use File::Basename;
diff --git a/vms/ext/VMS/stdio/Makefile.PL b/vms/ext/VMS/stdio/Makefile.PL
new file mode 100644
index 0000000000..d6683b4af6
--- /dev/null
+++ b/vms/ext/VMS/stdio/Makefile.PL
@@ -0,0 +1,3 @@
+use ExtUtils::MakeMaker;
+
+WriteMakefile( 'VERSION' => '1.0' );
diff --git a/vms/ext/VMS/stdio/stdio.pm b/vms/ext/VMS/stdio/stdio.pm
new file mode 100644
index 0000000000..d8b4ec21ec
--- /dev/null
+++ b/vms/ext/VMS/stdio/stdio.pm
@@ -0,0 +1,78 @@
+# VMS::stdio - VMS extensions to Perl's stdio calls
+#
+# Author: Charles Bailey bailey@genetics.upenn.edu
+# Version: 1.0
+# Revised: 29-Nov-1994
+#
+# Revision History:
+# 1.0 29-Nov-1994 Charles Bailey bailey@genetics.upenn.edu
+# original version
+# 1.1 09-Mar-1995 Charles Bailey bailey@genetics.upenn.edu
+# changed calling sequence to return FH/undef - like POSIX::open
+# added fgetname and tmpnam
+
+=head1 NAME
+
+VMS::stdio
+
+=head1 SYNOPSIS
+
+use VMS::stdio;
+$name = fgetname(FH);
+$uniquename = &tmpnam;
+$fh = vmsfopen("my.file","rfm=var","alq=100",...) or die $!;
+
+=head1 DESCRIPTION
+
+This package gives Perl scripts access to VMS extensions to the
+C stdio routines, such as optional arguments to C<fopen()>.
+The specific routines are described below.
+
+=head2 fgetname
+
+The C<fgetname> function returns the file specification associated
+with a Perl FileHandle. If an error occurs, it returns C<undef>.
+
+=head2 tmpnam
+
+The C<tmpnam> function returns a unique string which can be used
+as a filename when creating temporary files. If, for some
+reason, it is unable to generate a name, it returns C<undef>.
+
+=head2 vmsfopen
+
+The C<vmsfopen> function provides access to the VMS CRTL
+C<fopen()> function. It is similar to the built-in Perl C<open>
+function (see L<perlfunc> for a complete description), but will
+only open normal files; it cannot open pipes or duplicate
+existing FileHandles. Up to 8 optional arguments may follow the
+file name. These arguments should be strings which specify
+optional file characteristics as allowed by the CRTL C<fopen()>
+routine. (See the CRTL reference manual for details.)
+
+You can use the FileHandle returned by C<vmsfopen> just as you
+would any other Perl FileHandle.
+
+C<vmsfopen> is a temporary solution to problems which arise in
+handling VMS-specific file formats; in the long term, we hope to
+provide more transparent access to VMS file I/O through routines
+which replace standard Perl C<open> function, or through tied
+FileHandles. When this becomes possible, C<vmsfopen> may be
+replaced.
+
+=head1 REVISION
+
+This document was last revised on 09-Mar-1995, for Perl 5.001.
+
+=cut
+
+package VMS::stdio;
+
+require DynaLoader;
+require Exporter;
+
+@ISA = qw( Exporter DynaLoader);
+@EXPORT = qw( &fgetname &tmpfile &tmpnam &vmsfopen );
+
+bootstrap VMS::stdio;
+1;
diff --git a/vms/ext/VMS/stdio/stdio.xs b/vms/ext/VMS/stdio/stdio.xs
new file mode 100644
index 0000000000..367f489bf5
--- /dev/null
+++ b/vms/ext/VMS/stdio/stdio.xs
@@ -0,0 +1,109 @@
+/* VMS::stdio - VMS extensions to stdio routines
+ *
+ * Version: 1.1
+ * Author: Charles Bailey bailey@genetics.upenn.edu
+ * Revised: 09-Mar-1995
+ *
+ *
+ * Revision History:
+ *
+ * 1.0 29-Nov-1994 Charles Bailey bailey@genetics.upenn.edu
+ * original version - vmsfopen
+ * 1.1 09-Mar-1995 Charles Bailey bailey@genetics.upenn.edu
+ * changed calling sequence to return FH/undef - like POSIX::open
+ * added fgetname and tmpnam
+ */
+
+#include "EXTERN.h"
+#include "perl.h"
+#include "XSUB.h"
+
+/* Use type for FILE * from Perl's XSUB typemap. This is a bit
+ * of a hack, since all Perl filehandles using this type will permit
+ * both read & write operations, but it saves to write the PPCODE
+ * directly for updating the Perl filehandles.
+ */
+typedef FILE * InOutStream;
+
+MODULE = VMS::stdio PACKAGE = VMS::stdio
+
+void
+vmsfopen(name,...)
+ char * name
+ CODE:
+ char *args[8],mode[5] = {'r','\0','\0','\0','\0'}, c;
+ register int i, myargc;
+ FILE *fp;
+ if (items > 9) {
+ croak("File::VMSfopen::vmsfopen - too many args");
+ }
+ /* First, set up name and mode args from perl's string */
+ if (*name == '+') {
+ mode[1] = '+';
+ name++;
+ }
+ if (*name == '>') {
+ if (*(name+1) == '>') *mode = 'a', name += 2;
+ else *mode = 'w', name++;
+ }
+ myargc = items - 1;
+ for (i = 0; i < myargc; i++) args[i] = SvPV(ST(i+1),na);
+ /* This hack brought to you by C's opaque arglist management */
+ switch (myargc) {
+ case 0:
+ fp = fopen(name,mode);
+ break;
+ case 1:
+ fp = fopen(name,mode,args[0]);
+ break;
+ case 2:
+ fp = fopen(name,mode,args[0],args[1]);
+ break;
+ case 3:
+ fp = fopen(name,mode,args[0],args[1],args[2]);
+ break;
+ case 4:
+ fp = fopen(name,mode,args[0],args[1],args[2],args[3]);
+ break;
+ case 5:
+ fp = fopen(name,mode,args[0],args[1],args[2],args[3],args[4]);
+ break;
+ case 6:
+ fp = fopen(name,mode,args[0],args[1],args[2],args[3],args[4],args[5]);
+ break;
+ case 7:
+ fp = fopen(name,mode,args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
+ break;
+ case 8:
+ fp = fopen(name,mode,args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
+ break;
+ }
+ ST(0) = sv_newmortal();
+ if (fp != NULL) {
+ GV *gv = newGVgen("VMS::stdio");
+ c = mode[0]; name = mode;
+ if (mode[1]) *(name++) = '+';
+ if (c == 'r') *(name++) = '<';
+ else {
+ *(name++) = '>';
+ if (c == 'a') *(name++) = '>';
+ }
+ *(name++) = '&';
+ if (do_open(gv,mode,name - mode,fp))
+ sv_setsv(ST(0),newRV((SV*)gv));
+ }
+
+char *
+fgetname(fp)
+ FILE * fp
+ CODE:
+ char fname[257];
+ ST(0) = sv_newmortal();
+ if (fgetname(fp,fname) != NULL) sv_setpv(ST(0),fname);
+
+char *
+tmpnam()
+ CODE:
+ char fname[L_tmpnam];
+ ST(0) = sv_newmortal();
+ if (tmpnam(fname) != NULL) sv_setpv(ST(0),fname);