In vms/perlvms.pod :
Document traditional VMS behavior of C<die>, and also document the
latent POSIX_EXIT behavior changes for C<die> and C<$?>.
In perl.c:
Fixes to generate both the traditional and latent POSIX_EXIT VMS
behaviors and provide comments about why they are so different from
non-VMS. This needed a new macro STATUS_EXIT_SET in perl.h.
In perl.h:
Fixes to generate the expected VMS exit status for the various ways that
it could be set.
New macro STATUS_EXIT_SET to differentiate the cases, for non-VMS made
it reference STATUS_UNIX_SET.
In vms/vms.c:
Fix #1, default operator precedence in C was different than what I
intended, so child exit status codes were translated incorrectly.
Fix #2, typo caused a UNIX status code translation be changed to the
wrong code.
A test was run last night and all the tests that exercised this code passed.
-John
[EMAIL PROTECTED]
Personal Opinion Only
--- /rsync_root/perl/vms/perlvms.pod Tue Oct 25 05:05:13 2005
+++ vms/perlvms.pod Tue Oct 25 10:36:35 2005
@@ -626,6 +626,24 @@
return 1;
}
+
+=item die
+
+C<die> Will force the native VMS exit status to be an SS$_ABORT code
+if neither of the $! or $? status values are ones that would cause
+the native status to be interpreted as being what VMS classifies as
+SEVERE_ERROR severity for DCL error handling.
+
+When the future POSIX_EXIT mode is active, C<die>, the native status
+code will be set to VMS condition value that will allow C programs
+including the GNV package to automatically decode the original C<$!>
+or <$?> or <$^E> settings unless those are all success values, in
+which case it will be set for those programs to recover the value
+255. If at the time C<die> is called, the native VMS status value
+is either of SEVERE_ERROR or ERROR severity, the native VMS
+value will be used. See C<$?> for a description on decoding the
+native VMS value to recover the original exit status.
+
=item dump
Rather than causing Perl to abort and dump core, the C<dump>
@@ -1070,11 +1088,24 @@
SS$_NORMAL, and setting C<$?> to a non-zero value results in the
generic failure status SS$_ABORT. See also L<perlport/exit>.
+With the future POSIX_EXIT mode set, setting C<$?> will cause the
+code set to be encoded into a native VMS status code so that the
+either the parent or child exit codes of 0 to 255 can be recovered
+by C programs expecting _POSIX_EXIT behavior. If both a parent
+and a child exit code are set, then it will be assumed that this
+is a VMS status code to be passed through. The special code of
+0xFFFF is almost a NOOP as it will cause the current native
+VMS status in the C library to become the current native Perl
+VMS status.
+
The pragma C<use vmsish 'status'> makes C<$?> reflect the actual
VMS exit status instead of the default emulation of POSIX status
described above. This pragma also disables the conversion of
non-zero values to SS$_ABORT when setting C<$?> in an END
block (but zero will still be converted to SS$_NORMAL).
+
+Do not use the pragma C<use vmsish 'status'> with the future
+POSIX_EXIT mode, as they are requesting conflicting actions.
=item $|
--- /rsync_root/perl/perl.c Tue Oct 25 04:57:15 2005
+++ perl.c Tue Oct 25 09:52:09 2005
@@ -5154,7 +5154,7 @@
STATUS_ALL_FAILURE;
break;
default:
- STATUS_UNIX_EXIT_SET(status);
+ STATUS_EXIT_SET(status);
break;
}
my_exit_jump();
@@ -5166,15 +5166,57 @@
#ifdef VMS
/* We have been called to fall on our sword. The desired exit code
* should be already set in STATUS_UNIX, but could be shifted over
- * by 8 bits. STATUS_UNIX_EXIT_SET will fix all cases where
- * an error code has been set.
+ * by 8 bits. STATUS_UNIX_EXIT_SET will handle the cases where a
+ * that code is set.
*
* If an error code has not been set, then force the issue.
*/
- if (STATUS_UNIX == 0) /* No errors or status recorded? */
- STATUS_ALL_FAILURE; /* Ok, force the issue with a generic code */
- else
- STATUS_UNIX_EXIT_SET(STATUS_UNIX);
+ if (MY_POSIX_EXIT) {
+
+ /* In POSIX_EXIT mode follow Perl documentations and use 255 for
+ * the exit code when there isn't an error.
+ */
+
+ if (STATUS_UNIX == 0)
+ STATUS_UNIX_EXIT_SET(255);
+ else {
+ STATUS_UNIX_EXIT_SET(STATUS_UNIX);
+
+ /* The exit code could have been set by $? or vmsish which
+ * means that it may not be fatal. So convert
+ * success/warning codes to fatal.
+ */
+ if ((STATUS_NATIVE & (STS$K_SEVERE|STS$K_ERROR)) == 0)
+ STATUS_UNIX_EXIT_SET(255);
+ }
+ }
+ else {
+ /* Traditionally Perl on VMS always expects a Fatal Error. */
+ if (vaxc$errno & 1) {
+
+ /* So force success status to failure */
+ if (STATUS_NATIVE & 1)
+ STATUS_ALL_FAILURE;
+ }
+ else {
+ if (!vaxc$errno) {
+ STATUS_UNIX = EINTR; /* In case something cares */
+ STATUS_ALL_FAILURE;
+ }
+ else {
+ int severity;
+ STATUS_NATIVE = vaxc$errno; /* Should already be this */
+
+ /* Encode the severity code */
+ severity = STATUS_NATIVE & STS$M_SEVERITY;
+ STATUS_UNIX = (severity ? severity : 1) << 8;
+
+ /* Perl expects this to be a fatal error */
+ if (severity != STS$K_SEVERE)
+ STATUS_ALL_FAILURE;
+ }
+ }
+ }
#else
int exitstatus;
--- /rsync_root/perl/perl.h Tue Oct 25 04:57:16 2005
+++ perl.h Tue Oct 25 10:41:23 2005
@@ -2642,26 +2642,28 @@
# define STATUS_UNIX_SET(n) \
STMT_START { \
I32 evalue = (I32)n; \
- PL_statusvalue = evalue; \
+ PL_statusvalue = evalue; \
if (PL_statusvalue != -1) { \
- if (PL_statusvalue != EVMSERR) { \
- PL_statusvalue &= 0xFFFF; \
- PL_statusvalue_vms = Perl_unix_status_to_vms(evalue); \
- } \
- else { \
- PL_statusvalue_vms = vaxc$errno; \
- } \
+ if (PL_statusvalue != EVMSERR) { \
+ PL_statusvalue &= 0xFFFF; \
+ if (MY_POSIX_EXIT) \
+ PL_statusvalue_vms=PL_statusvalue ? SS$_ABORT : SS$_NORMAL;\
+ else PL_statusvalue_vms = Perl_unix_status_to_vms(evalue); \
+ } \
+ else { \
+ PL_statusvalue_vms = vaxc$errno; \
+ } \
} \
- else PL_statusvalue_vms = SS$_ABORT; \
- set_vaxc_errno(evalue); \
+ else PL_statusvalue_vms = SS$_ABORT; \
+ set_vaxc_errno(PL_statusvalue_vms); \
} STMT_END
/* STATUS_UNIX_EXIT_SET - Takes a UNIX/POSIX exit code and sets
* the NATIVE error status based on it. It does not assume that
* the UNIX/POSIX exit codes have any relationship to errno, except
* that 0 indicates a success. When in the default mode to comply
- * with the Perl VMS documentation, anything other than 0 indicates
- * a native status should be set to the failure code SS$_ABORT;
+ * with the Perl VMS documentation, any other code sets the NATIVE
+ * status to a failure code of SS$_ABORT.
*
* In the new POSIX EXIT mode, native status will be set so that the
* actual exit code will can be retrieved by the calling program or
@@ -2686,7 +2688,8 @@
PL_statusvalue_vms = \
(C_FAC_POSIX | (evalue << 3 ) | (evalue == 1)? \
(STS$K_ERROR | STS$M_INHIB_MSG) : 0); \
- else PL_statusvalue_vms = SS$_ABORT; \
+ else \
+ PL_statusvalue_vms = SS$_ABORT; \
} else { /* forgive them Perl, for they have sinned */ \
if (evalue != EVMSERR) PL_statusvalue_vms = evalue; \
else PL_statusvalue_vms = vaxc$errno; \
@@ -2698,6 +2701,33 @@
set_vaxc_errno(PL_statusvalue_vms); \
} STMT_END
+ /* STATUS_EXIT_SET - Takes a NATIVE/UNIX/POSIX exit code
+ * and sets the NATIVE error status based on it. This special case
+ * is needed to maintain compatibility with past VMS behavior.
+ *
+ * In the default mode on VMS, this number is passed through as
+ * both the NATIVE and UNIX status. Which makes it different
+ * that the STATUS_UNIX_EXIT_SET.
+ *
+ * In the new POSIX EXIT mode, native status will be set so that the
+ * actual exit code will can be retrieved by the calling program or
+ * shell.
+ *
+ */
+
+# define STATUS_EXIT_SET(n) \
+ STMT_START { \
+ I32 evalue = (I32)n; \
+ PL_statusvalue = evalue; \
+ if (MY_POSIX_EXIT) \
+ PL_statusvalue_vms = \
+ (C_FAC_POSIX | (evalue << 3 ) | (evalue == 1)? \
+ (STS$K_ERROR | STS$M_INHIB_MSG) : 0); \
+ else \
+ PL_statusvalue_vms = evalue ? evalue : SS$_NORMAL; \
+ set_vaxc_errno(PL_statusvalue_vms); \
+ } STMT_END
+
/* This macro forces a success status */
# define STATUS_ALL_SUCCESS \
@@ -2754,6 +2784,7 @@
PL_statusvalue &= 0xFFFF; \
} STMT_END
# define STATUS_UNIX_EXIT_SET(n) STATUS_UNIX_SET(n)
+# define STATUS_EXIT_SET(n) STATUS_UNIX_SET(n)
# define STATUS_CURRENT STATUS_UNIX
# define STATUS_EXIT STATUS_UNIX
# define STATUS_ALL_SUCCESS (PL_statusvalue = 0, PL_statusvalue_posix = 0)
--- /rsync_root/perl/vms/vms.c Tue Oct 25 05:05:17 2005
+++ vms/vms.c Tue Oct 25 09:52:37 2005
@@ -1821,7 +1821,7 @@
fac_sp = vms_status & STS$M_FAC_SP;
msg_no = vms_status & (STS$M_MSG_NO | STS$M_SEVERITY);
- if ((facility == 0) || (fac_sp == 0) && (child_flag == 0)) {
+ if (((facility == 0) || (fac_sp == 0)) && (child_flag == 0)) {
switch(msg_no) {
case SS$_NORMAL:
unix_status = 0;
@@ -2025,7 +2025,7 @@
case EACCES: return SS$_FILACCERR;
case EFAULT: return SS$_ACCVIO;
/* case ENOTBLK */
- case EBUSY: SS$_DEVOFFLINE;
+ case EBUSY: return SS$_DEVOFFLINE;
case EEXIST: return RMS$_FEX;
/* case EXDEV */
case ENODEV: return SS$_NOSUCHDEV;