diff options
author | Larry Wall <lwall@netlabs.com> | 1995-03-12 22:32:14 -0800 |
---|---|---|
committer | Larry Wall <lwall@netlabs.com> | 1995-03-12 22:32:14 -0800 |
commit | 748a93069b3d16374a9859d1456065dd3ae11394 (patch) | |
tree | 308ca14de9933a313dceacce8be77db67d9368c7 /vms/ext | |
parent | fec02dd38faf8f83471b031857d89cb76fea1ca0 (diff) | |
download | perl-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.pm | 323 | ||||
-rw-r--r-- | vms/ext/MM_VMS.pm | 812 | ||||
-rw-r--r-- | vms/ext/VMS/stdio/Makefile.PL | 3 | ||||
-rw-r--r-- | vms/ext/VMS/stdio/stdio.pm | 78 | ||||
-rw-r--r-- | vms/ext/VMS/stdio/stdio.xs | 109 |
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); |