patch 9.1.1591: VMS support can be improved
Problem: VMS support can be improved
Solution: Merge chagnes from Steven M. Schweda
(Zoltan)
closes: #17810
Co-authored-by: Steven M. Schweda <sms@antinode.info>
Signed-off-by: Zoltan Arpadffy <zoltan.arpadffy@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
committed by
Christian Brabandt
parent
af9a7a04f1
commit
e9d1259111
259
src/os_vms.c
259
src/os_vms.c
@ -9,7 +9,7 @@
|
||||
* See README.txt for an overview of the Vim source code.
|
||||
*/
|
||||
|
||||
#include "vim.h"
|
||||
#include "vim.h"
|
||||
|
||||
// define _generic_64 for use in time functions
|
||||
#if !defined(VAX) && !defined(PROTO)
|
||||
@ -18,11 +18,11 @@
|
||||
// based on Alpha's gen64def.h; the file is absent on VAX
|
||||
typedef struct _generic_64 {
|
||||
# pragma __nomember_alignment
|
||||
__union { // You can treat me as...
|
||||
__union { // You can treat me as...
|
||||
// long long is not available on VAXen
|
||||
// unsigned __int64 gen64$q_quadword; ...a single 64-bit value, or
|
||||
|
||||
unsigned int gen64$l_longword [2]; // ...two 32-bit values, or
|
||||
unsigned int gen64$l_longword [2]; // ...two 32-bit values, or
|
||||
unsigned short int gen64$w_word [4]; // ...four 16-bit values
|
||||
} gen64$r_quad_overlay;
|
||||
} GENERIC_64;
|
||||
@ -583,7 +583,7 @@ vms_unix_mixed_filespec(char *in, char *out)
|
||||
ch = '[';
|
||||
SKIP_FOLLOWING_SLASHES(in);
|
||||
}
|
||||
else if (EQN(in, "../", 3)) // Unix parent directory?
|
||||
else if (EQN(in, "../", 3)) // Unix parent directory?
|
||||
{
|
||||
*out++ = '[';
|
||||
*out++ = '-';
|
||||
@ -593,20 +593,20 @@ vms_unix_mixed_filespec(char *in, char *out)
|
||||
SKIP_FOLLOWING_SLASHES(in);
|
||||
}
|
||||
else
|
||||
{ // not a special character
|
||||
while (EQN(in, "./", 2)) // Ignore Unix "current dir"
|
||||
{ // not a special character
|
||||
while (EQN(in, "./", 2)) // Ignore Unix "current dir"
|
||||
{
|
||||
in += 2;
|
||||
SKIP_FOLLOWING_SLASHES(in);
|
||||
}
|
||||
if (strchr(in, '/') == NULL) // any more Unix directories ?
|
||||
if (strchr(in, '/') == NULL) // any more Unix directories ?
|
||||
{
|
||||
strcpy(out, in); // No - get rest of the spec
|
||||
strcpy(out, in); // No - get rest of the spec
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
*out++ = '['; // Yes, denote a Vms subdirectory
|
||||
*out++ = '['; // Yes, denote a Vms subdirectory
|
||||
ch = '.';
|
||||
--in;
|
||||
}
|
||||
@ -627,7 +627,7 @@ vms_unix_mixed_filespec(char *in, char *out)
|
||||
ch = '.';
|
||||
SKIP_FOLLOWING_SLASHES(in);
|
||||
}
|
||||
else if (EQN(in, "../", 3)) // Unix parent directory?
|
||||
else if (EQN(in, "../", 3)) // Unix parent directory?
|
||||
{
|
||||
*out++ = '-';
|
||||
end_of_dir = out;
|
||||
@ -637,7 +637,7 @@ vms_unix_mixed_filespec(char *in, char *out)
|
||||
}
|
||||
else
|
||||
{
|
||||
while (EQN(in, "./", 2)) // Ignore Unix "current dir"
|
||||
while (EQN(in, "./", 2)) // Ignore Unix "current dir"
|
||||
{
|
||||
end_of_dir = out;
|
||||
in += 2;
|
||||
@ -651,7 +651,7 @@ vms_unix_mixed_filespec(char *in, char *out)
|
||||
++in;
|
||||
}
|
||||
|
||||
*out = '\0'; // Terminate output file spec
|
||||
*out = '\0'; // Terminate output file spec
|
||||
|
||||
if (end_of_dir != NULL) // Terminate directory portion
|
||||
*end_of_dir = ']';
|
||||
@ -725,28 +725,82 @@ vms_fixfilename(void *instring)
|
||||
* Remove version number from file name
|
||||
* we need it in some special cases as:
|
||||
* creating swap file name and writing new file
|
||||
*/
|
||||
|
||||
/*
|
||||
* 2025-05-13 SMS.
|
||||
* Using $PARSE would be simpler and more accurate, if all-VMS (not
|
||||
* mixed UNIX+VMS) path were ensured. Meanwhile, to improve (imperfect)
|
||||
* handling of extended name syntax:
|
||||
* o All characters (up to five (32767)) after semi-colon (or last
|
||||
* of multiple dots) must be numeric.
|
||||
* o Caret-escaped semi-colon (^;) or dot (^.) does not delimit
|
||||
* version.
|
||||
* Whether it makes sense to detect syntax errors here is not entirely
|
||||
* clear. Currently, many invalid version strings are not treated as
|
||||
* version strings. (More could be.)
|
||||
*/
|
||||
void
|
||||
vms_remove_version(void * fname)
|
||||
{
|
||||
char_u *cp;
|
||||
char_u *fp;
|
||||
char_u *dp; // Dot pointer
|
||||
char_u *rp; // Right pointer
|
||||
int done = 0;
|
||||
int vdigits = 0;
|
||||
|
||||
if ((cp = vim_strchr( fname, ';')) != NULL) // remove version
|
||||
*cp = '\0';
|
||||
else if ((cp = vim_strrchr( fname, '.')) != NULL )
|
||||
rp = (char_u *)fname+ strlen( (char *)fname)- 1; // Rightmost char
|
||||
while ((done == 0) && (rp > (char_u *)fname)) // Count digits
|
||||
{
|
||||
if ((fp = vim_strrchr( fname, ']')) != NULL )
|
||||
{;}
|
||||
else if ((fp = vim_strrchr( fname, '>')) != NULL )
|
||||
{;}
|
||||
if (isdigit( *rp))
|
||||
{
|
||||
vdigits++;
|
||||
*rp--;
|
||||
}
|
||||
else
|
||||
fp = fname;
|
||||
{
|
||||
done = 1; // Quit at non-digit
|
||||
}
|
||||
} // while (Count digits)
|
||||
|
||||
if (vdigits <= 5) // If likely version digits, check delimiter
|
||||
{ // (Could check for <= 32767, not just five digits or fewer.)
|
||||
if (*rp == (char_u)';')
|
||||
{
|
||||
if ((rp >= (char_u *)fname) && (*(rp- 1) != (char_u)'^'))
|
||||
{ // Unescaped ";"
|
||||
*rp = '\0'; // Trim off ";nnn"
|
||||
}
|
||||
}
|
||||
else if (*rp == (char_u)'.') // Last of multiple dots?
|
||||
{
|
||||
if ((rp >= (char_u *)fname) && (*(rp- 1) != '^'))
|
||||
{ // Unescaped dot. Version requires previous one
|
||||
dp = rp- 1; // Scan chars before "."
|
||||
done = 0;
|
||||
while ((done == 0) && (dp >= (char_u *)fname))
|
||||
{
|
||||
if ((*dp == ']') || (*dp == '>') || (*dp == ':') || (*dp == '/'))
|
||||
{ // Possible VMS dev:[dir] delimiter (or UNIX "/")
|
||||
if ((dp >= (char_u *)fname) && (*(dp- 1) != '^'))
|
||||
{ // Unescaped dev:[dir] (or /) delimiter
|
||||
done = 1; // No previous dot found in name
|
||||
}
|
||||
}
|
||||
else if (*dp == '.')
|
||||
{ // Possible dot delimiter
|
||||
if ((dp >= (char_u *)fname) && (*(dp- 1) != '^'))
|
||||
{ // Unescaped dot delimiter
|
||||
done = 1; // Previous dot found in name
|
||||
*rp = '\0'; // Trim off ".nnn"
|
||||
}
|
||||
}
|
||||
dp--; // Next char to right
|
||||
} // while
|
||||
}
|
||||
}
|
||||
// Else no version found to remove
|
||||
} // if (vdigits <= 5)
|
||||
|
||||
while ( *fp != '\0' && fp < cp )
|
||||
if ( *fp++ == '.' )
|
||||
*cp = '\0';
|
||||
}
|
||||
return ;
|
||||
}
|
||||
|
||||
@ -783,23 +837,29 @@ RealWaitForChar(
|
||||
if (sec > 0)
|
||||
{
|
||||
// time-out specified; convert it to absolute time
|
||||
// sec>0 requirement of lib$cvtf_to_internal_time()
|
||||
// sec>0 requirement of lib$cvt[fs]_to_internal_time()
|
||||
|
||||
// get current time (number of 100ns ticks since the VMS Epoch)
|
||||
status = sys$gettim(&time_curr);
|
||||
if (status != SS$_NORMAL)
|
||||
return 0; // error
|
||||
// construct the delta time
|
||||
#if __G_FLOAT==0
|
||||
# ifndef VAX
|
||||
// IEEE is default on IA64, but can be used on Alpha too - but not on VAX
|
||||
status = lib$cvts_to_internal_time(
|
||||
|
||||
/* On all non-VAX hardware architectures, the "CC /FLOAT=option"
|
||||
* determines the floating-point format. The default format on Alpha
|
||||
* is VAX; on IA64 and x86_64 it's IEEE. But, except on VAX, the user
|
||||
* can specify either. What matters here is the actual floating-point
|
||||
* format being used, not the hardware architecture. Choose the
|
||||
* appropriate time conversion function accordingly.
|
||||
*/
|
||||
#if __IEEE_FLOAT
|
||||
# define LIB_CVTX_TO_INTERNAL_TIME lib$cvts_to_internal_time // IEEE
|
||||
#else
|
||||
# define LIB_CVTX_TO_INTERNAL_TIME lib$cvtf_to_internal_time // VAX
|
||||
#endif // __IEEE_FLOAT CVTS
|
||||
|
||||
status = LIB_CVTX_TO_INTERNAL_TIME(
|
||||
&convert_operation, &sec, &time_diff);
|
||||
# endif
|
||||
#else // default on Alpha and VAX
|
||||
status = lib$cvtf_to_internal_time(
|
||||
&convert_operation, &sec, &time_diff);
|
||||
#endif
|
||||
if (status != LIB$_NORMAL)
|
||||
return 0; // error
|
||||
// add them up
|
||||
@ -851,3 +911,130 @@ RealWaitForChar(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined( __VAX) && (__CRTL_VER >= 70301000)
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unixlib.h>
|
||||
|
||||
// Structure to hold a DECC$* feature name and its desired value
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char *name;
|
||||
int value;
|
||||
} decc_feat_t;
|
||||
|
||||
int vms_init_done = -1;
|
||||
|
||||
decc_feat_t decc_feat_array[] = {
|
||||
|
||||
// Preserve command-line case with SET PROCESS/PARSE_STYLE=EXTENDED
|
||||
{ "DECC$ARGV_PARSE_STYLE", 1 },
|
||||
|
||||
// Preserve case for file names on ODS5 disks
|
||||
{ "DECC$EFS_CASE_PRESERVE", 1 },
|
||||
|
||||
// Enable multiple dots (and most characters) in ODS5 file names,
|
||||
// while preserving VMS-ness of ";version"
|
||||
{ "DECC$EFS_CHARSET", 1 },
|
||||
|
||||
// List terminator
|
||||
{ (char *)NULL, 0 } };
|
||||
|
||||
|
||||
/* LIB$INITIALIZE initialization.
|
||||
*
|
||||
* On sufficiently recent non-VAX systems, set a collection of C RTL
|
||||
* features without using the DECC$* logical name method.
|
||||
*
|
||||
* Note: Old VAX VMS versions may suffer from a linker complaint like
|
||||
* this:
|
||||
*
|
||||
* %LINK-W-MULPSC, conflicting attributes for psect LIB$INITIALIZE
|
||||
* in module LIB$INITIALIZE file SYS$COMMON:[SYSLIB]STARLET.OLB;1
|
||||
*
|
||||
* Using a LINK options file which includes a line like this one should
|
||||
* stop this complaint:
|
||||
*
|
||||
* PSECT_ATTR=LIB$INITIALIZE,NOPIC
|
||||
*/
|
||||
|
||||
/* vms_init()
|
||||
*
|
||||
* Uses LIB$INITIALIZE to set a collection of C RTL features without
|
||||
* requiring the user to define the corresponding logical names.
|
||||
*
|
||||
* LIB$INITIALIZE initialization function
|
||||
*/
|
||||
|
||||
static void
|
||||
vms_init(void)
|
||||
{
|
||||
// Set the global flag to indicate that LIB$INITIALIZE worked
|
||||
|
||||
vms_init_done = 1;
|
||||
|
||||
int feat_index;
|
||||
int feat_value;
|
||||
int feat_value_max;
|
||||
int feat_value_min;
|
||||
int i;
|
||||
int sts;
|
||||
|
||||
// Loop through all items in the decc_feat_array[]
|
||||
for (i = 0; decc_feat_array[i].name != NULL; i++)
|
||||
{
|
||||
// Get the feature index
|
||||
feat_index = decc$feature_get_index(decc_feat_array[i].name);
|
||||
if (feat_index >= 0)
|
||||
{
|
||||
// Valid item. Collect its properties
|
||||
feat_value = decc$feature_get_value(feat_index, 1);
|
||||
feat_value_min = decc$feature_get_value(feat_index, 2);
|
||||
feat_value_max = decc$feature_get_value(feat_index, 3);
|
||||
|
||||
if ((decc_feat_array[i].value >= feat_value_min) && (decc_feat_array[i].value <= feat_value_max))
|
||||
// Valid value. Set it if necessary
|
||||
if (feat_value != decc_feat_array[i].value)
|
||||
sts = decc$feature_set_value(feat_index, 1, decc_feat_array[i].value);
|
||||
else
|
||||
// Invalid DECC feature value
|
||||
printf("INVALID DECC FEATURE VALUE, %d: %d <= %s <= %d.\n",
|
||||
feat_value, feat_value_min, decc_feat_array[i].name, feat_value_max);
|
||||
}
|
||||
else
|
||||
// Invalid DECC feature name
|
||||
printf("UNKNOWN DECC FEATURE: %s.\n", decc_feat_array[i].name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Get "vms_init()" into a valid, loaded LIB$INITIALIZE PSECT. */
|
||||
|
||||
#pragma nostandard
|
||||
|
||||
/* Establish the LIB$INITIALIZE PSECTs, with proper alignment and
|
||||
* other attributes. Note that "nopic" is significant only on VAX.
|
||||
*/
|
||||
#pragma extern_model save
|
||||
|
||||
#pragma extern_model strict_refdef "LIB$INITIALIZE" 2, nopic, nowrt
|
||||
void (*const x_vms_init)() = vms_init;
|
||||
|
||||
#pragma extern_model strict_refdef "LIB$INITIALIZ" 2, nopic, nowrt
|
||||
const int spare[ 8] = { 0 };
|
||||
|
||||
#pragma extern_model restore
|
||||
|
||||
// Fake reference to ensure loading the LIB$INITIALIZE PSECT
|
||||
|
||||
#pragma extern_model save
|
||||
int LIB$INITIALIZE(void);
|
||||
#pragma extern_model strict_refdef
|
||||
int dmy_lib$initialize = (int) LIB$INITIALIZE;
|
||||
#pragma extern_model restore
|
||||
|
||||
#pragma standard
|
||||
|
||||
#endif // !defined( __VAX) && (__CRTL_VER >= 70301000)
|
||||
|
||||
Reference in New Issue
Block a user