summaryrefslogtreecommitdiff
path: root/vms/vms.c
diff options
context:
space:
mode:
authorCraig A. Berry <craigberry@mac.com>2012-12-14 08:29:55 -0600
committerCraig A. Berry <craigberry@mac.com>2012-12-14 08:50:11 -0600
commitb7bc7afbe074add30fdf01d619e7cfef04b07403 (patch)
treefe3fdb1a20c9f0bceee06416419cee40215ddd94 /vms/vms.c
parent35c9969e6e0005027f32d516744606751dcaab67 (diff)
downloadperl-b7bc7afbe074add30fdf01d619e7cfef04b07403.tar.gz
More fun escaping dots in tovmsspec.
c1abd561a0a322 avoided the double escaping of dots in filenames, but failed to copy the dot itself in cases where it was already escaped. Plus, when not using extended file specifications and thus converting the dot to an underscore, we need to make sure the underscore is not escaped. And add a test that covers most of these scenarios. Probably more tests are needed.
Diffstat (limited to 'vms/vms.c')
-rw-r--r--vms/vms.c31
1 files changed, 19 insertions, 12 deletions
diff --git a/vms/vms.c b/vms/vms.c
index b3201a44fc..06a606a3bf 100644
--- a/vms/vms.c
+++ b/vms/vms.c
@@ -8248,19 +8248,20 @@ int utf8_flag;
return result;
}
-/* A convenience macro for escaping dots that haven't already been
- * escaped, with guards to avoid checking before the start of the
- * buffer or advancing beyond the end of it (allowing room for the
- * NUL terminator).
+/* A convenience macro for copying dots in filenames and escaping
+ * them when they haven't already been escaped, with guards to
+ * avoid checking before the start of the buffer or advancing
+ * beyond the end of it (allowing room for the NUL terminator).
*/
-#define VMSEFS_ESCAPE_DOT(vmsefsdot,vmsefsbuf,vmsefsbufsiz) STMT_START { \
+#define VMSEFS_DOT_WITH_ESCAPE(vmsefsdot,vmsefsbuf,vmsefsbufsiz) STMT_START { \
if ( ((vmsefsdot) > (vmsefsbuf) && *((vmsefsdot) - 1) != '^' \
|| ((vmsefsdot) == (vmsefsbuf))) \
- && (vmsefsdot) < (vmsefsbuf) + (vmsefsbufsiz) - 2 \
+ && (vmsefsdot) < (vmsefsbuf) + (vmsefsbufsiz) - 3 \
) { \
*((vmsefsdot)++) = '^'; \
- *((vmsefsdot)++) = '.'; \
} \
+ if ((vmsefsdot) < (vmsefsbuf) + (vmsefsbufsiz) - 2) \
+ *((vmsefsdot)++) = '.'; \
} STMT_END
/*{{{ char *tovmsspec[_ts](char *path, char *buf, int * utf8_flag)*/
@@ -8546,20 +8547,26 @@ static char *int_tovmsspec
else cp2 += 3; /* Trailing '/' was there, so skip it, too */
}
else {
- if (decc_efs_charset == 0)
+ if (decc_efs_charset == 0) {
+ if (*(cp1-1) == '^')
+ cp1--; /* remove the escape, if any */
*(cp1++) = '_'; /* fix up syntax - '.' in name not allowed */
+ }
else {
- VMSEFS_ESCAPE_DOT(cp1, rslt, VMS_MAXRSS);
+ VMSEFS_DOT_WITH_ESCAPE(cp1, rslt, VMS_MAXRSS);
}
}
}
else {
if (!infront && *(cp1-1) == '-') *(cp1++) = '.';
if (*cp2 == '.') {
- if (decc_efs_charset == 0)
+ if (decc_efs_charset == 0) {
+ if (*(cp1-1) == '^')
+ cp1--; /* remove the escape, if any */
*(cp1++) = '_';
+ }
else {
- VMSEFS_ESCAPE_DOT(cp1, rslt, VMS_MAXRSS);
+ VMSEFS_DOT_WITH_ESCAPE(cp1, rslt, VMS_MAXRSS);
}
}
else *(cp1++) = *cp2;
@@ -8590,7 +8597,7 @@ static char *int_tovmsspec
case '.':
if (((cp2 < lastdot) || (cp2[1] == '\0')) &&
decc_readdir_dropdotnotype) {
- VMSEFS_ESCAPE_DOT(cp1, rslt, VMS_MAXRSS);
+ VMSEFS_DOT_WITH_ESCAPE(cp1, rslt, VMS_MAXRSS);
cp2++;
/* trailing dot ==> '^..' on VMS */