summaryrefslogtreecommitdiff
path: root/vms
diff options
context:
space:
mode:
Diffstat (limited to 'vms')
-rw-r--r--vms/Makefile23
-rw-r--r--vms/config.vms2
-rw-r--r--vms/descrip.mms23
-rw-r--r--vms/ext/filespec.t16
-rw-r--r--vms/vms.c249
-rw-r--r--vms/vmsish.h3
6 files changed, 217 insertions, 99 deletions
diff --git a/vms/Makefile b/vms/Makefile
index e0b293fd5e..d5194b41eb 100644
--- a/vms/Makefile
+++ b/vms/Makefile
@@ -32,7 +32,7 @@ ARCH = VMS_VAX
OBJVAL = $@
# Updated by fndvers.com -- do not edit by hand
-PERL_VERSION = 5_00324#
+PERL_VERSION = 5_00325#
ARCHDIR = [.lib.$(ARCH).$(PERL_VERSION)]
@@ -378,7 +378,7 @@ IO : [.lib]IO.pm [.lib.IO]File.pm [.lib.IO]Handle.pm [.lib.IO]Pipe.pm [.lib.IO]S
@ If f$$Search("[.lib]VMS.Dir").eqs."" Then Create/Directory [.lib.VMS]
Copy/Log/NoConfirm [.vms.ext]Filespec.pm $@
-[.lib.pod]perldoc : [.utils]perldoc.PL $(ARCHDIR)Config.pm
+[.lib.pod]perldoc.com : [.utils]perldoc.PL $(ARCHDIR)Config.pm
@ If f$$Search("[.lib]pod.dir").eqs."" Then Create/Directory [.lib.pod]
$(MINIPERL) [.utils]perldoc.PL
Copy/Log [.utils]perldoc.com $@
@@ -412,7 +412,10 @@ IO : [.lib]IO.pm [.lib.IO]File.pm [.lib.IO]Handle.pm [.lib.IO]Pipe.pm [.lib.IO]S
[.x2p]s2p.com : [.x2p]s2p.PL $(ARCHDIR)Config.pm
$(MINIPERL) [.x2p]s2p.PL
+# Rename catches problem with some DECC versions in which object file is
+# placed in current default dir, not same one as source file.
[.x2p]$(DBG)a2p$(E) : [.x2p]a2p$(O), [.x2p]hash$(O), [.x2p]str$(O), [.x2p]util$(O), [.x2p]walk$(O)
+ @ If f$$Search("a2p$(O)").nes."" Then Rename/NoLog a2p$(O),hash$(O),str$(O),util$(O),walk$(O) [.x2p]
Link $(LINKFLAGS) /Exe=$@ $(MMS$SOURCE_LIST) $(CRTLOPTS)
[.lib.pod]pod2html.com : [.pod]pod2html.PL $(ARCHDIR)Config.pm
@@ -617,7 +620,7 @@ perly$(O) : perly.c, perly.h, $(h)
[.t.lib]vmsfspec.t : [.vms.ext]filespec.t
Copy/Log/NoConfirm [.vms.ext]filespec.t $@
-test : all
+test : all [.t.lib]vmsfspec.t
- @[.VMS]Test.Com "$(E)"
# CORE subset for MakeMaker, so we can build Perl without sources
@@ -1476,8 +1479,9 @@ tidy : cleanlis
- If f$$Search("[.Lib.VMS]*.*;-1").nes."" Then Purge/NoConfirm/Log [.Lib.VMS]*.*
- If f$$Search("[.Lib.Pod]*.Pod;-1").nes."" Then Purge/NoConfirm/Log [.Lib.Pod]*.Pod
- If f$$Search("$(ARCHCORE)*.*").nes."" Then Purge/NoConfirm/Log $(ARCHCORE)*.*
- - If f$$Search("[.utils]*.;-1").nes."" Then Purge/NoConfirm/Log [.utils]*./Exclude=Makefile.
- - If f$$Search("[.lib]perlbug.;-1").nes."" Then Purge/NoConfirm/Log [.lib]perlbug.
+ - If f$$Search("[.lib]*.com;-1").nes."" Then Purge/NoConfirm/Log [.lib]*.com
+ - If f$$Search("[.utils]*.com;-1").nes."" Then Purge/NoConfirm/Log [.utils]*.com
+ - If f$$Search("[.x2p]*.com;-1").nes."" Then Purge/NoConfirm/Log [.x2p]*.com
- If f$$Search("[.lib.pod]*.;-1").nes."" Then Purge/NoConfirm/Log [.lib.pod]*.
clean : tidy
@@ -1532,14 +1536,15 @@ realclean : clean
- If f$$Search("[.Lib]DynaLoader.pm").nes."" Then Delete/NoConfirm/Log [.Lib]DynaLoader.pm;*
- If f$$Search("[.Lib]Socket.pm").nes."" Then Delete/NoConfirm/Log [.Lib]Socket.pm;*
- If f$$Search("[.Lib]Config.pm").nes."" Then Delete/NoConfirm/Log [.Lib]Config.pm;*
- - If f$$Search("[.Lib]perlbug.").nes."" Then Delete/NoConfirm/Log [.Lib]perlbug.;*
+ - If f$$Search("[.Lib]*.com").nes."" Then Delete/NoConfirm/Log [.Lib]*.com;*
+ - If f$$Search("[.utils]*.com").nes."" Then Delete/NoConfirm/Log [.utils]*.com;*
+ - If f$$Search("[.x2p]*.com").nes."" Then Delete/NoConfirm/Log [.x2p]*.com;*
- If f$$Search("$(ARCHDIR)Config.pm").nes."" Then Delete/NoConfirm/Log $(ARCHDIR)Config.pm;*
- If f$$Search("[.lib.ExtUtils]Miniperl.pm").nes."" Then Delete/NoConfirm/Log [.lib.ExtUtils]Miniperl.pm;*
- - If f$$Search("[.utils]*.").nes."" Then Delete/NoConfirm/Log [.utils]*.;*/Exclude=Makefile.
- - If f$$Search("[.x2p]*.").nes."" Then Delete/NoConfirm/Log [.x2p]*.;*/Exclude=Makefile.
- If f$$Search("[.lib.pod]*.pod").nes."" Then Delete/NoConfirm/Log [.lib.pod]*.pod;*
- - If f$$Search("[.lib.pod]perldoc.").nes."" Then Delete/NoConfirm/Log [.lib.pod]perldoc.;*
+ - If f$$Search("[.lib.pod]perldoc.com").nes."" Then Delete/NoConfirm/Log [.lib.pod]perldoc.com;*
- If f$$Search("[.lib.pod]pod2*.com").nes."" Then Delete/NoConfirm/Log [.lib.pod]pod2*.com;*
+ - If f$$Search("[.t.lib]vmsfspec.t").nes."" Then Delete/NoConfirm/Log [.t.lib]vmsfspec.t;*
- If f$$Search("[...]*$(E)").nes."" Then Delete/NoConfirm/Log [...]*$(E);*
cleansrc : clean
diff --git a/vms/config.vms b/vms/config.vms
index 95aefec05a..97d5c960b8 100644
--- a/vms/config.vms
+++ b/vms/config.vms
@@ -76,7 +76,7 @@
* when Perl is built. Please do not change it by hand; make
* any changes to FndVers.Com instead.
*/
-#define ARCHLIB_EXP "/perl_root/lib/VMS_VAX/5_00324" /**/
+#define ARCHLIB_EXP "/perl_root/lib/VMS_VAX/5_00325" /**/
#define ARCHLIB ARCHLIB_EXP /*config-skip*/
/* ARCHNAME:
diff --git a/vms/descrip.mms b/vms/descrip.mms
index cfa4b660f4..36386ef846 100644
--- a/vms/descrip.mms
+++ b/vms/descrip.mms
@@ -65,7 +65,7 @@ OBJVAL = $(MMS$TARGET_NAME)$(O)
.endif
# Updated by fndvers.com -- do not edit by hand
-PERL_VERSION = 5_00324#
+PERL_VERSION = 5_00325#
ARCHDIR = [.lib.$(ARCH).$(PERL_VERSION)]
@@ -499,7 +499,7 @@ IO : [.lib]IO.pm [.lib.IO]File.pm [.lib.IO]Handle.pm [.lib.IO]Pipe.pm [.lib.IO]S
@ If F$Search("[.lib]VMS.Dir").eqs."" Then Create/Directory [.lib.VMS]
Copy/Log/NoConfirm $(MMS$SOURCE) $(MMS$TARGET)
-[.lib.pod]perldoc : [.utils]perldoc.PL $(ARCHDIR)Config.pm
+[.lib.pod]perldoc.com : [.utils]perldoc.PL $(ARCHDIR)Config.pm
@ If F$Search("[.lib]pod.dir").eqs."" Then Create/Directory [.lib.pod]
$(MINIPERL) $(MMS$SOURCE)
Copy/Log [.utils]perldoc.com $(MMS$TARGET)
@@ -533,7 +533,10 @@ IO : [.lib]IO.pm [.lib.IO]File.pm [.lib.IO]Handle.pm [.lib.IO]Pipe.pm [.lib.IO]S
[.x2p]s2p.com : [.x2p]s2p.PL $(ARCHDIR)Config.pm
$(MINIPERL) $(MMS$SOURCE)
+# Rename catches problem with some DECC versions in which object file is
+# placed in current default dir, not same one as source file.
[.x2p]$(DBG)a2p$(E) : [.x2p]a2p$(O), [.x2p]hash$(O), [.x2p]str$(O), [.x2p]util$(O), [.x2p]walk$(O)
+ @ If F$Search("a2p$(O)").nes."" Then Rename/NoLog a2p$(O),hash$(O),str$(O),util$(O),walk$(O) [.x2p]
Link $(LINKFLAGS) /Exe=$(MMS$TARGET) $(MMS$SOURCE_LIST) $(CRTLOPTS)
[.lib.pod]pod2html.com : [.pod]pod2html.PL $(ARCHDIR)Config.pm
@@ -765,7 +768,7 @@ perly$(O) : perly.c, perly.h, $(h)
[.t.lib]vmsfspec.t : [.vms.ext]filespec.t
Copy/Log/NoConfirm $(MMS$SOURCE) $(MMS$TARGET)
-test : all
+test : all [.t.lib]vmsfspec.t
- @[.VMS]Test.Com "$(E)"
# CORE subset for MakeMaker, so we can build Perl without sources
@@ -1632,8 +1635,9 @@ tidy : cleanlis
- If F$Search("[.Lib.VMS]*.*;-1").nes."" Then Purge/NoConfirm/Log [.Lib.VMS]*.*
- If F$Search("[.Lib.Pod]*.Pod;-1").nes."" Then Purge/NoConfirm/Log [.Lib.Pod]*.Pod
- If F$Search("$(ARCHCORE)*.*").nes."" Then Purge/NoConfirm/Log $(ARCHCORE)*.*
- - If F$Search("[.utils]*.;-1").nes."" Then Purge/NoConfirm/Log [.utils]*./Exclude=Makefile.
- - If F$Search("[.lib]perlbug.;-1").nes."" Then Purge/NoConfirm/Log [.lib]perlbug.
+ - If F$Search("[.lib]*.com;-1").nes."" Then Purge/NoConfirm/Log [.lib]*.com
+ - If F$Search("[.utils]*.com;-1").nes."" Then Purge/NoConfirm/Log [.utils]*.com
+ - If F$Search("[.x2p]*.com;-1").nes."" Then Purge/NoConfirm/Log [.x2p]*.com
- If F$Search("[.lib.pod]*.;-1").nes."" Then Purge/NoConfirm/Log [.lib.pod]*.
clean : tidy
@@ -1698,14 +1702,15 @@ realclean : clean
- If F$Search("[.Lib]DynaLoader.pm").nes."" Then Delete/NoConfirm/Log [.Lib]DynaLoader.pm;*
- If F$Search("[.Lib]Socket.pm").nes."" Then Delete/NoConfirm/Log [.Lib]Socket.pm;*
- If F$Search("[.Lib]Config.pm").nes."" Then Delete/NoConfirm/Log [.Lib]Config.pm;*
- - If F$Search("[.Lib]perlbug.").nes."" Then Delete/NoConfirm/Log [.Lib]perlbug.;*
+ - If F$Search("[.Lib]*.com").nes."" Then Delete/NoConfirm/Log [.Lib]*.com;*
+ - If F$Search("[.utils]*.com").nes."" Then Delete/NoConfirm/Log [.utils]*.com;*
+ - If F$Search("[.x2p]*.com").nes."" Then Delete/NoConfirm/Log [.x2p]*.com;*
- If F$Search("$(ARCHDIR)Config.pm").nes."" Then Delete/NoConfirm/Log $(ARCHDIR)Config.pm;*
- If F$Search("[.lib.ExtUtils]Miniperl.pm").nes."" Then Delete/NoConfirm/Log [.lib.ExtUtils]Miniperl.pm;*
- - If F$Search("[.utils]*.").nes."" Then Delete/NoConfirm/Log [.utils]*.;*/Exclude=Makefile.
- - If F$Search("[.x2p]*.").nes."" Then Delete/NoConfirm/Log [.x2p]*.;*/Exclude=Makefile.
- If F$Search("[.lib.pod]*.pod").nes."" Then Delete/NoConfirm/Log [.lib.pod]*.pod;*
- - If F$Search("[.lib.pod]perldoc.").nes."" Then Delete/NoConfirm/Log [.lib.pod]perldoc.;*
+ - If F$Search("[.lib.pod]perldoc.com").nes."" Then Delete/NoConfirm/Log [.lib.pod]perldoc.com;*
- If F$Search("[.lib.pod]pod2*.com").nes."" Then Delete/NoConfirm/Log [.lib.pod]pod2*.com;*
+ - If F$Search("[.t.lib]vmsfspec.t").nes."" Then Delete/NoConfirm/Log [.t.lib]vmsfspec.t;*
- If F$Search("[...]*$(E)").nes."" Then Delete/NoConfirm/Log [...]*$(E);*
cleansrc : clean
diff --git a/vms/ext/filespec.t b/vms/ext/filespec.t
index 38cd5368c9..a0a274bfee 100644
--- a/vms/ext/filespec.t
+++ b/vms/ext/filespec.t
@@ -36,18 +36,30 @@ some:[where.over]the.rainbow unixify /some/where/over/the.rainbow
[.some.where.over]the.rainbow unixify some/where/over/the.rainbow
[-.some.where.over]the.rainbow unixify ../some/where/over/the.rainbow
[.some.--.where.over]the.rainbow unixify some/../../where/over/the.rainbow
+[.some...where.over]the.rainbow unixify some/.../where/over/the.rainbow
+[...some.where.over]the.rainbow unixify .../some/where/over/the.rainbow
+[.some.where.over...]the.rainbow unixify some/where/over/.../the.rainbow
+[.some.where.over...] unixify some/where/over/.../
+[.some.where.over.-] unixify some/where/over/../
[] unixify ./
[-] unixify ../
[--] unixify ../../
+[...] unixify .../
# and back again
/some/where/over/the.rainbow vmsify some:[where.over]the.rainbow
some/where/over/the.rainbow vmsify [.some.where.over]the.rainbow
../some/where/over/the.rainbow vmsify [-.some.where.over]the.rainbow
some/../../where/over/the.rainbow vmsify [-.where.over]the.rainbow
+.../some/where/over/the.rainbow vmsify [...some.where.over]the.rainbow
+some/.../where/over/the.rainbow vmsify [.some...where.over]the.rainbow
+/some/.../where/over/the.rainbow vmsify some:[...where.over]the.rainbow
+some/where/... vmsify [.some.where...]
+/where/... vmsify where:[...]
. vmsify []
.. vmsify [-]
../.. vmsify [--]
+.../ vmsify [...]
# Fileifying directory specs
down:[the.garden.path] fileify down:[the.garden]path.dir;1
@@ -73,12 +85,16 @@ down:[the]garden.path pathify
/down/the/garden.path pathify
down:[the.garden]path.dir;2 pathify #N.B. ;2
path pathify path/
+/down/the/garden/. pathify /down/the/garden/./
+/down/the/garden/.. pathify /down/the/garden/../
+/down/the/garden/... pathify /down/the/garden/.../
path.notdir pathify
# Both VMS/Unix and file/path conversions
down:[the.garden]path.dir;1 unixpath /down/the/garden/path/
/down/the/garden/path vmspath down:[the.garden.path]
down:[the.garden.path] unixpath /down/the/garden/path/
+down:[the.garden.path...] unixpath /down/the/garden/path/.../
/down/the/garden/path.dir vmspath down:[the.garden.path]
[.down.the.garden]path.dir unixpath down/the/garden/path/
down/the/garden/path vmspath [.down.the.garden.path]
diff --git a/vms/vms.c b/vms/vms.c
index 992e75f0a7..a9060b49de 100644
--- a/vms/vms.c
+++ b/vms/vms.c
@@ -2,8 +2,8 @@
*
* VMS-specific routines for perl5
*
- * Last revised: 14-Oct-1996 by Charles Bailey bailey@genetics.upenn.edu
- * Version: 5.3.7
+ * Last revised: 29-Jan-1997 by Charles Bailey bailey@genetics.upenn.edu
+ * Version: 5.3.24
*/
#include <acedef.h>
@@ -28,7 +28,8 @@
#include <shrdef.h>
#include <ssdef.h>
#include <starlet.h>
-#include <stsdef.h>
+#include <strdef.h>
+#include <str$routines.h>
#include <syidef.h>
#include <uaidef.h>
#include <uicdef.h>
@@ -1339,7 +1340,11 @@ static char *do_pathify_dirspec(char *dir,char *buf, int ts)
if ( !(cp1 = strrchr(dir,'/')) &&
!(cp1 = strrchr(dir,']')) &&
!(cp1 = strrchr(dir,'>')) ) cp1 = dir;
- if ((cp2 = strchr(cp1,'.')) != NULL) {
+ if ((cp2 = strchr(cp1,'.')) != NULL &&
+ (*(cp2-1) != '/' || /* Trailing '.', '..', */
+ !(*(cp2+1) == '\0' || /* or '...' are dirs. */
+ (*(cp2+1) == '.' && *(cp2+2) == '\0') ||
+ (*(cp2+1) == '.' && *(cp2+2) == '.' && *(cp2+3) == '\0')))) {
int ver; char *cp3;
if (!*(cp2+1) || toupper(*(cp2+1)) != 'D' || /* Wrong type. */
!*(cp2+2) || toupper(*(cp2+2)) != 'I' || /* Bzzt. */
@@ -1482,7 +1487,7 @@ static char *do_tounixspec(char *spec, char *buf, int ts)
{
static char __tounixspec_retbuf[NAM$C_MAXRSS+1];
char *dirend, *rslt, *cp1, *cp2, *cp3, tmp[NAM$C_MAXRSS+1];
- int devlen, dirlen, retlen = NAM$C_MAXRSS+1, dashes = 0;
+ int devlen, dirlen, retlen = NAM$C_MAXRSS+1, expand = 0;
if (spec == NULL) return NULL;
if (strlen(spec) > NAM$C_MAXRSS) return NULL;
@@ -1492,9 +1497,13 @@ static char *do_tounixspec(char *spec, char *buf, int ts)
cp1 = strchr(spec,'[');
if (!cp1) cp1 = strchr(spec,'<');
if (cp1) {
- for (cp1++; *cp1 == '-'; cp1++) dashes++; /* VMS '-' ==> Unix '../' */
+ for (cp1++; *cp1; cp1++) {
+ if (*cp1 == '-') expand++; /* VMS '-' ==> Unix '../' */
+ if (*cp1 == '.' && *(cp1+1) == '.' && *(cp1+2) == '.')
+ { expand++; cp1 +=2; } /* VMS '...' ==> Unix '/.../' */
+ }
}
- New(7015,rslt,retlen+2+2*dashes,char);
+ New(7015,rslt,retlen+2+2*expand,char);
}
else rslt = __tounixspec_retbuf;
if (strchr(spec,'/') != NULL) {
@@ -1517,11 +1526,10 @@ static char *do_tounixspec(char *spec, char *buf, int ts)
else { /* the VMS spec begins with directories */
cp2++;
if (*cp2 == ']' || *cp2 == '>') {
- strcpy(rslt,"./");
+ *(cp1++) = '.'; *(cp1++) = '/'; *(cp1++) = '\0';
return rslt;
}
- else if ( *cp2 != '.' && *cp2 != '-') {
- *(cp1++) = '/'; /* add the implied device into the Unix spec */
+ else if ( *cp2 != '.' && *cp2 != '-') { /* add the implied device */
if (getcwd(tmp,sizeof tmp,1) == NULL) {
if (ts) Safefree(rslt);
return NULL;
@@ -1532,26 +1540,36 @@ static char *do_tounixspec(char *spec, char *buf, int ts)
*(cp3++) = '\0';
if (strchr(cp3,']') != NULL) break;
} while (((cp3 = my_getenv(tmp)) != NULL) && strcpy(tmp,cp3));
- cp3 = tmp;
- while (*cp3) *(cp1++) = *(cp3++);
- *(cp1++) = '/';
- if (ts &&
+ if (ts && !buf &&
((devlen = strlen(tmp)) + (dirlen = strlen(cp2)) + 1 > retlen)) {
- int offset = cp1 - rslt;
-
retlen = devlen + dirlen;
- Renew(rslt,retlen+1+2*dashes,char);
- cp1 = rslt + offset;
+ Renew(rslt,retlen+1+2*expand,char);
+ cp1 = rslt;
+ }
+ cp3 = tmp;
+ *(cp1++) = '/';
+ while (*cp3) {
+ *(cp1++) = *(cp3++);
+ if (cp1 - rslt > NAM$C_MAXRSS && !ts && !buf) return NULL; /* No room */
}
+ *(cp1++) = '/';
+ }
+ else if ( *cp2 == '.') {
+ if (*(cp2+1) == '.' && *(cp2+2) == '.') {
+ *(cp1++) = '.'; *(cp1++) = '.'; *(cp1++) = '.'; *(cp1++) = '/';
+ cp2 += 3;
+ }
+ else cp2++;
}
- else if (*cp2 == '.') cp2++;
}
for (; cp2 <= dirend; cp2++) {
if (*cp2 == ':') {
*(cp1++) = '/';
if (*(cp2+1) == '[') cp2++;
}
- else if (*cp2 == ']' || *cp2 == '>') *(cp1++) = '/';
+ else if (*cp2 == ']' || *cp2 == '>') {
+ if (*(cp1-1) != '/') *(cp1++) = '/'; /* Don't double after ellipsis */
+ }
else if (*cp2 == '.') {
*(cp1++) = '/';
if (*(cp2+1) == ']' || *(cp2+1) == '>') {
@@ -1560,6 +1578,10 @@ static char *do_tounixspec(char *spec, char *buf, int ts)
if (!strncmp(cp2,"[000000",7) && (*(cp2+7) == ']' ||
*(cp2+7) == '>' || *(cp2+7) == '.')) cp2 += 7;
}
+ else if ( *(cp2+1) == '.' && *(cp2+2) == '.') {
+ *(cp1++) = '.'; *(cp1++) = '.'; *(cp1++) = '.'; *(cp1++) ='/';
+ cp2 += 2;
+ }
}
else if (*cp2 == '-') {
if (*(cp2-1) == '[' || *(cp2-1) == '<' || *(cp2-1) == '.') {
@@ -1609,9 +1631,10 @@ static char *do_tovmsspec(char *path, char *buf, int ts) {
else strcpy(rslt,path);
return rslt;
}
- if (*(dirend+1) == '.') { /* do we have trailing "/." or "/.."? */
+ if (*(dirend+1) == '.') { /* do we have trailing "/." or "/.." or "/..."? */
if (!*(dirend+2)) dirend +=2;
if (*(dirend+2) == '.' && !*(dirend+3)) dirend += 3;
+ if (*(dirend+2) == '.' && *(dirend+3) == '.' && !*(dirend+4)) dirend += 4;
}
cp1 = rslt;
cp2 = path;
@@ -1660,6 +1683,12 @@ static char *do_tovmsspec(char *path, char *buf, int ts) {
*(cp1++) = '-'; /* "../" --> "-" */
cp2 += 3;
}
+ else if (*(cp2+1) == '.' && *(cp2+2) == '.' &&
+ (*(cp2+3) == '/' || *(cp2+3) == '\0')) {
+ *(cp1++) = '.'; *(cp1++) = '.'; *(cp1++) = '.'; /* ".../" --> "..." */
+ if (!*(cp2+4)) *(cp1++) = '.'; /* Simulate trailing '/' for later */
+ cp2 += 4;
+ }
if (cp2 > dirend) cp2 = dirend;
}
else *(cp1++) = '.';
@@ -1687,6 +1716,16 @@ static char *do_tovmsspec(char *path, char *buf, int ts) {
cp2 += 2;
if (cp2 == dirend) break;
}
+ else if ( *(cp2+1) == '.' && *(cp2+2) == '.' &&
+ (*(cp2+3) == '/' || *(cp2+3) == '\0') ) {
+ if (*(cp1-1) != '.') *(cp1++) = '.'; /* May already have 1 from '/' */
+ *(cp1++) = '.'; *(cp1++) = '.'; /* ".../" --> "..." */
+ if (!*(cp2+3)) {
+ *(cp1++) = '.'; /* Simulate trailing '/' */
+ cp2 += 2; /* for loop will incr this to == dirend */
+ }
+ else cp2 += 3; /* Trailing '/' was there, so skip it, too */
+ }
else *(cp1++) = '_'; /* fix up syntax - '.' in name not allowed */
}
else {
@@ -2132,7 +2171,7 @@ unsigned long int zero = 0, sts;
for (c = string; *c; ++c)
if (isupper(*c))
*c = tolower(*c);
- if (isunix) trim_unixpath(string,item);
+ if (isunix) trim_unixpath(string,item,1);
add_item(head, tail, string, count);
++expcount;
}
@@ -2289,23 +2328,26 @@ unsigned long int flags = 17, one = 1, retsts;
* of whether input filespec was VMS-style or Unix-style.
*
* fspec is filespec to be trimmed, and wildspec is wildcard spec used to
- * determine prefix (both may be in VMS or Unix syntax).
+ * determine prefix (both may be in VMS or Unix syntax). opts is a bit
+ * vector of options; at present, only bit 0 is used, and if set tells
+ * trim unixpath to try the current default directory as a prefix when
+ * presented with a possibly ambiguous ... wildcard.
*
* Returns !=0 on success, with trimmed filespec replacing contents of
* fspec, and 0 on failure, with contents of fpsec unchanged.
*/
-/*{{{int trim_unixpath(char *fspec, char *wildspec)*/
+/*{{{int trim_unixpath(char *fspec, char *wildspec, int opts)*/
int
-trim_unixpath(char *fspec, char *wildspec)
+trim_unixpath(char *fspec, char *wildspec, int opts)
{
char unixified[NAM$C_MAXRSS+1], unixwild[NAM$C_MAXRSS+1],
- *template, *base, *cp1, *cp2;
- register int tmplen, reslen = 0;
+ *template, *base, *end, *cp1, *cp2;
+ register int tmplen, reslen = 0, dirs = 0;
if (!wildspec || !fspec) return 0;
if (strpbrk(wildspec,"]>:") != NULL) {
if (do_tounixspec(wildspec,unixwild,0) == NULL) return 0;
- else template = unixified;
+ else template = unixwild;
}
else template = wildspec;
if (strpbrk(fspec,"]>:") != NULL) {
@@ -2327,63 +2369,112 @@ trim_unixpath(char *fspec, char *wildspec)
return 1;
}
- /* Find prefix to template consisting of path elements without wildcards */
- if ((cp1 = strpbrk(template,"*%?")) == NULL)
- for (cp1 = template; *cp1; cp1++) ;
- else while (cp1 > template && *cp1 != '/') cp1--;
- for (cp2 = base; *cp2; cp2++) ; /* Find end of resultant filespec */
-
- /* Wildcard was in first element, so we don't have a reliable string to
- * match against. Guess where to trim resultant filespec by counting
- * directory levels in the Unix template. (We could do this instead of
- * string matching in all cases, since Unix doesn't have a ... wildcard
- * that can expand into multiple levels of subdirectory, but we try for
- * the string match so our caller can interpret foo/.../bar.* as
- * [.foo...]bar.* if it wants, and only get burned if there was a
- * wildcard in the first word (in which case, caveat caller). */
- if (cp1 == template) {
- int subdirs = 0;
- for ( ; *cp1; cp1++) if (*cp1 == '/') subdirs++;
- /* need to back one more '/' than in template, to pick up leading dirname */
- subdirs++;
- while (cp2 > base) {
- if (*cp2 == '/') subdirs--;
- if (!subdirs) break; /* quit without decrement when we hit last '/' */
- cp2--;
- }
- /* ran out of directories on resultant; allow for already trimmed
- * resultant, which hits start of string looking for leading '/' */
- if (subdirs && (cp2 != base || subdirs != 1)) return 0;
- /* Move past leading '/', if there is one */
- base = cp2 + (*cp2 == '/' ? 1 : 0);
- tmplen = strlen(base);
- if (reslen && tmplen > reslen) return 0; /* not enough space */
- memmove(fspec,base,tmplen+1); /* copy result to fspec, with trailing NUL */
+ for (end = base; *end; end++) ; /* Find end of resultant filespec */
+ if ((cp1 = strstr(template,".../")) == NULL) { /* No ...; just count elts */
+ for (cp1 = template; *cp1; cp1++) if (*cp1 == '/') dirs++;
+ for (cp1 = end ;cp1 >= base; cp1--)
+ if ((*cp1 == '/') && !dirs--) /* postdec so we get front of rel path */
+ { cp1++; break; }
+ if (cp1 != fspec) memmove(fspec,cp1, end - cp1 + 1);
return 1;
}
- /* We have a prefix string of complete directory names, so we
- * try to find it on the resultant filespec */
- else {
- tmplen = cp1 - template;
- if (!memcmp(base,template,tmplen)) { /* Nothing before prefix; we're done */
- if (reslen) { /* we converted to Unix syntax; copy result over */
- tmplen = cp2 - base;
- if (tmplen > reslen) return 0; /* not enough space */
- memmove(fspec,base,tmplen+1); /* Copy trimmed spec + trailing NUL */
+ else {
+ char tpl[NAM$C_MAXRSS+1], lcres[NAM$C_MAXRSS+1];
+ char *front, *nextell, *lcend, *lcfront, *ellipsis = cp1;
+ int ells = 1, totells, segdirs, match;
+ struct dsc$descriptor_s wilddsc = {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, tpl},
+ resdsc = {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0};
+
+ while ((cp1 = strstr(ellipsis+4,".../")) != NULL) {ellipsis = cp1; ells++;}
+ totells = ells;
+ for (cp1 = ellipsis+4; *cp1; cp1++) if (*cp1 == '/') dirs++;
+ if (ellipsis == template && opts & 1) {
+ /* Template begins with an ellipsis. Since we can't tell how many
+ * directory names at the front of the resultant to keep for an
+ * arbitrary starting point, we arbitrarily choose the current
+ * default directory as a starting point. If it's there as a prefix,
+ * clip it off. If not, fall through and act as if the leading
+ * ellipsis weren't there (i.e. return shortest possible path that
+ * could match template).
+ */
+ if (getcwd(tpl, sizeof tpl,0) == NULL) return 0;
+ for (cp1 = tpl, cp2 = base; *cp1 && *cp2; cp1++,cp2++)
+ if (_tolower(*cp1) != _tolower(*cp2)) break;
+ segdirs = dirs - totells; /* Min # of dirs we must have left */
+ for (front = cp2+1; *front; front++) if (*front == '/') segdirs--;
+ if (*cp1 == '\0' && *cp2 == '/' && segdirs < 1) {
+ memcpy(fspec,cp2+1,end - cp2);
+ return 1;
}
- return 1;
}
- for ( ; cp2 - base > tmplen; base++) {
- if (*base != '/') continue;
- if (!memcmp(base + 1,template,tmplen)) break;
+ /* First off, back up over constant elements at end of path */
+ if (dirs) {
+ for (front = end ; front >= base; front--)
+ if (*front == '/' && !dirs--) { front++; break; }
+ }
+ for (cp1=template,cp2=lcres; *cp1 && cp2 <= lcend + sizeof lcend;
+ cp1++,cp2++) *cp2 = _tolower(*cp1); /* Make lc copy for match */
+ if (cp1 != '\0') return 0; /* Path too long. */
+ lcend = cp2;
+ *cp2 = '\0'; /* Pick up with memcpy later */
+ lcfront = lcres + (front - base);
+ /* Now skip over each ellipsis and try to match the path in front of it. */
+ while (ells--) {
+ for (cp1 = ellipsis - 2; cp1 >= template; cp1--)
+ if (*(cp1) == '.' && *(cp1+1) == '.' &&
+ *(cp1+2) == '.' && *(cp1+3) == '/' ) break;
+ if (cp1 < template) break; /* template started with an ellipsis */
+ if (cp1 + 4 == ellipsis) { /* Consecutive ellipses */
+ ellipsis = cp1; continue;
+ }
+ wilddsc.dsc$w_length = resdsc.dsc$w_length = ellipsis - 1 - cp1;
+ nextell = cp1;
+ for (segdirs = 0, cp2 = tpl;
+ cp1 <= ellipsis - 1 && cp2 <= tpl + sizeof tpl;
+ cp1++, cp2++) {
+ if (*cp1 == '?') *cp2 = '%'; /* Substitute VMS' wildcard for Unix' */
+ else *cp2 = _tolower(*cp1); /* else lowercase for match */
+ if (*cp2 == '/') segdirs++;
+ }
+ if (cp1 != ellipsis - 1) return 0; /* Path too long */
+ /* Back up at least as many dirs as in template before matching */
+ for (cp1 = lcfront - 1; segdirs && cp1 >= lcres; cp1--)
+ if (*cp1 == '/' && !segdirs--) { cp1++; break; }
+ for (match = 0; cp1 > lcres;) {
+ resdsc.dsc$a_pointer = cp1;
+ if (str$match_wild(&wilddsc,&resdsc) == STR$_MATCH) {
+ match++;
+ if (match == 1) lcfront = cp1;
+ }
+ for ( ; cp1 >= lcres; cp1--) if (*cp1 == '/') { cp1++; break; }
+ }
+ if (!match) return 0; /* Can't find prefix ??? */
+ if (match > 1 && opts & 1) {
+ /* This ... wildcard could cover more than one set of dirs (i.e.
+ * a set of similar dir names is repeated). If the template
+ * contains more than 1 ..., upstream elements could resolve the
+ * ambiguity, but it's not worth a full backtracking setup here.
+ * As a quick heuristic, clip off the current default directory
+ * if it's present to find the trimmed spec, else use the
+ * shortest string that this ... could cover.
+ */
+ char def[NAM$C_MAXRSS+1], *st;
+
+ if (getcwd(def, sizeof def,0) == NULL) return 0;
+ for (cp1 = def, cp2 = base; *cp1 && *cp2; cp1++,cp2++)
+ if (_tolower(*cp1) != _tolower(*cp2)) break;
+ segdirs = dirs - totells; /* Min # of dirs we must have left */
+ for (st = cp2+1; *st; st++) if (*st == '/') segdirs--;
+ if (*cp1 == '\0' && *cp2 == '/') {
+ memcpy(fspec,cp2+1,end - cp2);
+ return 1;
+ }
+ /* Nope -- stick with lcfront from above and keep going. */
+ }
}
-
- if (cp2 - base == tmplen) return 0; /* Not there - not good */
- base++; /* Move past leading '/' */
- if (reslen && cp2 - base > reslen) return 0; /* not enough space */
- /* Copy down remaining portion of filespec, including trailing NUL */
- memmove(fspec,base,cp2 - base + 1);
+ memcpy(fspec,base + (lcfront - lcres), lcend - lcfront + 1);
return 1;
+ ellipsis = nextell;
}
} /* end of trim_unixpath() */
diff --git a/vms/vmsish.h b/vms/vmsish.h
index fa23571d47..10cdc08eda 100644
--- a/vms/vmsish.h
+++ b/vms/vmsish.h
@@ -13,6 +13,7 @@
#include <libdef.h> /* status codes for various places */
#include <rmsdef.h> /* at which errno and vaxc$errno are */
#include <ssdef.h> /* explicitly set in the perl source code */
+#include <stsdef.h>
/* Suppress compiler warnings from DECC for VMS-specific extensions:
* GLOBALEXT, NOSHAREEXT, READONLYEXT: global[dr]ef declarations
@@ -483,7 +484,7 @@ struct tm *my_gmtime _((const time_t *));
I32 cando_by_name _((I32, I32, char *));
int flex_fstat _((int, struct stat *));
int flex_stat _((char *, struct stat *));
-int trim_unixpath _((char *, char*));
+int trim_unixpath _((char *, char*, int));
int my_vfork _(());
bool vms_do_aexec _((SV *, SV **, SV **));
bool vms_do_exec _((char *));