summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog10
-rw-r--r--NEWS7
-rw-r--r--arscan.c2
-rw-r--r--config.h-vms.template56
-rw-r--r--default.c83
-rw-r--r--dir.c75
-rw-r--r--file.c16
-rw-r--r--glob/glob.c27
-rw-r--r--glob/glob.h12
-rw-r--r--implicit.c6
-rw-r--r--job.c583
-rw-r--r--make.h8
-rw-r--r--makefile.com16
-rw-r--r--makefile.vms41
-rw-r--r--readme.vms136
-rw-r--r--rule.c8
-rw-r--r--variable.c67
-rw-r--r--vmsdir.h29
-rw-r--r--vmsfunctions.c138
-rw-r--r--vmsify.c221
20 files changed, 1230 insertions, 311 deletions
diff --git a/ChangeLog b/ChangeLog
index 175081c..3e37cd0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2000-01-21 Paul D. Smith <psmith@gnu.org>
+
+ Installed patches for the VMS port.
+ Patches provided by: Hartmut Becker <Hartmut.Becker@compaq.com>
+
+ * readme.vms, arscan.c, config.h-vms, default.c, dir.c, file.c:
+ * implicit.c, job.c, make.h, makefile.com, makefile.vms, rule.c:
+ * variable.c, vmsdir.h, vmsfunctions.c, vmsify.c, glob/glob.c:
+ * glob/glob.h: Installed patches. See readme.vms for details.
+
2000-01-11 Paul D. Smith <psmith@gnu.org>
Resolve PR/xxxx: don't automatically evaluate the $(call ...)
diff --git a/NEWS b/NEWS
index 0b96212..1cd9ef6 100644
--- a/NEWS
+++ b/NEWS
@@ -1,8 +1,8 @@
GNU make NEWS -*-indented-text-*-
History of user-visible changes.
- 21 Nov 1999
+ 21 Jan 2000
-Copyright (C) 1992,93,94,95,96,97,98,1999 Free Software Foundation, Inc.
+Copyright (C) 1992,93,94,95,96,97,98,99,2000 Free Software Foundation, Inc.
See the end for copying conditions.
All changes mentioned here are more fully described in the GNU make
@@ -43,6 +43,9 @@ Version 3.79
a minimal amount information is generated, displaying the names of
"normal" targets (not makefiles) were deemed out of date and in need
of being rebuilt.
+
+* Hartmut Becker provided many updates for the VMS port of GNU make.
+ See the readme.vms file for more details.
Version 3.78
diff --git a/arscan.c b/arscan.c
index 6ff2715..2b90705 100644
--- a/arscan.c
+++ b/arscan.c
@@ -78,7 +78,9 @@ VMS_get_member_info (module, rfa)
mhd = (struct mhddef *) filename;
+#ifdef __DECC
val = decc$fix_time (&mhd->mhd$l_datim);
+#endif
for (i = 0; i < module->dsc$w_length; i++)
filename[i] = _tolower ((unsigned char)module->dsc$a_pointer[i]);
diff --git a/config.h-vms.template b/config.h-vms.template
index 6488255..e2dd026 100644
--- a/config.h-vms.template
+++ b/config.h-vms.template
@@ -1,4 +1,4 @@
-/* config.h-vms. Generated by hand by Klaus Kämpf <kkaempf@progis.de> */
+/* config.h-vms. Generated by hand by Klaus Kämpf <kkaempf@rmi.de> */
/* config.h. Generated automatically by configure. */
/* config.h.in. Generated automatically from configure.in by autoheader. */
@@ -11,6 +11,10 @@
/* Define if using alloca.c. */
/* #undef C_ALLOCA */
+/* maybe this should be placed into make.h */
+#if defined(__VAX) && defined(__DECC)
+#define alloca(n) __ALLOCA(n)
+#endif
/* Define if the closedir function returns void instead of int. */
/* #undef CLOSEDIR_VOID */
@@ -117,18 +121,17 @@
/* #undef NO_MINUS_C_MINUS_O */
/* Define to `int' if <sys/types.h> doesn't define. */
-/* #undef pid_t */
+/* I assume types.h is available for all 5.0 cc/cxx compilers */
+#if __DECC_VER < 50090000
+#define pid_t int
+#endif
/* Define if the system does not provide POSIX.1 features except
with this defined. */
/* #undef _POSIX_1_SOURCE */
-#include <sys/types.h>
-#include <ctype.h>
-#include <signal.h>
-
/* Define if you need to in order for stat and other things to work. */
-#define _POSIX_C_SOURCE 1
+/* #undef _POSIX_SOURCE */
/* Define as the return type of signal handlers (int or void). */
#define RETSIGTYPE void
@@ -160,7 +163,9 @@
/* #undef SYS_SIGLIST_DECLARED */
/* Define to `int' if <sys/types.h> doesn't define. */
-/* #undef uid_t */
+#if __DECC_VER < 50090000
+#define uid_t int
+#endif
/* Define for Encore UMAX. */
/* #undef UMAX */
@@ -267,7 +272,7 @@
/* #undef HAVE_WAITPID */
/* Define if you have the <dirent.h> header file. */
-/* #undef HAVE_DIRENT_H */
+#define HAVE_DIRENT_H 1
/* Define if you have the <fcntl.h> header file. */
#ifdef __DECC
@@ -302,36 +307,55 @@
/* #undef HAVE_SYS_PARAM_H */
/* Define if you have the <sys/timeb.h> header file. */
+#ifndef __GNUC__
#define HAVE_SYS_TIMEB_H 1
+#endif
/* Define if you have the <sys/wait.h> header file. */
/* #undef HAVE_SYS_WAIT_H */
-/* Define if you have the <unistd.h> header file. */
-/* #undef HAVE_UNISTD_H */
-
/* Define if you have the dgc library (-ldgc). */
/* #undef HAVE_LIBDGC */
/* Define if you have the kstat library (-lkstat). */
-/* #undef HAVE_LIBKSTAT */
+/* #undef HAVE_LIBKSTAT *
/* Define if you have the sun library (-lsun). */
/* #undef HAVE_LIBSUN */
-/* VMS specific */
+/* Define for case insensitve filenames */
+#define HAVE_CASE_INSENSITIVE_FS 1
+
+/* VMS specific, define it if you want to use case sensitve targets */
+/* #undef WANT_CASE_SENSITIVE_TARGETS */
+/* VMS specific, V7.0 has opendir() and friends, so it's undefined */
+/* Define first or both if you want to use non-VMS code for opendir() etc. */
+/* #undef HAVE_VMSDIR_H */
+/* #undef _DIRENT_HAVE_D_NAMLEN */
+
+/* On older systems with older CRTLs force non-VMS-code */
+#if __CRTL_VER < 70000000 && !defined(HAVE_VMSDIR_H)
#define HAVE_VMSDIR_H 1
+#endif
+#if defined(HAVE_VMSDIR_H) && defined(HAVE_DIRENT_H)
+#undef HAVE_DIRENT_H
+#endif
+
+#define HAVE_STDLIB_H 1
#define INCLUDEDIR "sys$sysroot:[syslib]"
#define LIBDIR "sys$sysroot:[syslib]"
-/* Avoid broken RTL functions on OpenVMS */
-#include <unixlib.h>
+/* Don't use RTL functions of OpenVMS */
+#ifdef __DECC
+#include <stdio.h>
+#include <unistd.h>
#define getopt gnu_getopt
#define optarg gnu_optarg
#define optopt gnu_optopt
#define optind gnu_optind
#define opterr gnu_opterr
+#endif
#if defined (__cplusplus) || (defined (__STDC__) && __STDC__)
#undef PARAMS
diff --git a/default.c b/default.c
index 8ad37e1..e50813d 100644
--- a/default.c
+++ b/default.c
@@ -38,8 +38,8 @@ Boston, MA 02111-1307, USA. */
static char default_suffixes[]
#ifdef VMS
- = ".exe .olb .ln .obj .c .cc .pas .p .for .f .r .y .l .mar \
-.mod .sym .def .h .info .dvi .tex .texinfo .texi .txinfo \
+ = ".exe .olb .ln .obj .c .cxx .cc .pas .p .for .f .r .y .l .mar \
+.s .ss .i .ii .mod .sym .def .h .info .dvi .tex .texinfo .texi .txinfo \
.w .ch .cweb .web .com .sh .elc .el";
#else
= ".out .a .ln .o .c .cc .C .cpp .p .f .F .r .y .l .s .S \
@@ -108,13 +108,21 @@ static char *default_suffix_rules[] =
{
#ifdef VMS
".obj.exe",
- "$(LINK.obj) $^ $(LOADLIBES) $(LDLIBS) /exe=$@",
+ "$(LINK.obj) $^ $(LOADLIBES) $(LDLIBS) $(CRT0) /exe=$@",
".mar.exe",
- "$(LINK.mar) $^ $(LOADLIBES) $(LDLIBS) /exe=$@",
+ "$(COMPILE.mar) $^ \n $(LINK.obj) $(subst .mar,.obj,$^) $(LOADLIBES) $(LDLIBS) $(CRT0) /exe=$@",
+ ".s.exe",
+ "$(COMPILE.s) $^ \n $(LINK.obj) $(subst .s,.obj,$^) $(LOADLIBES) $(LDLIBS) $(CRT0) /exe=$@",
".c.exe",
- "$(COMPILE.c) $^ \n $(LINK.obj) $(subst .c,.obj,$^) $(LOADLIBES) $(LDLIBS) /exe=$@",
+ "$(COMPILE.c) $^ \n $(LINK.obj) $(subst .c,.obj,$^) $(LOADLIBES) $(LDLIBS) $(CRT0) /exe=$@",
".cc.exe",
- "$(COMPILE.cc) $^ \n $(LINK.obj) $(subst .cc,.obj,$^) $(LOADLIBES) $(LDLIBS) /exe=$@",
+#ifdef GCC_IS_NATIVE
+ "$(COMPILE.cc) $^ \n $(LINK.obj) $(CXXSTARTUP),sys$$disk:[]$(subst .cc,.obj,$^) $(LOADLIBES) $(LXLIBS) $(LDLIBS) $(CXXRT0) /exe=$@",
+#else
+ "$(COMPILE.cc) $^ \n $(CXXLINK.obj) $(subst .cc,.obj,$^) $(LOADLIBES) $(LXLIBS) $(LDLIBS) $(CXXRT0) /exe=$@",
+ ".cxx.exe",
+ "$(COMPILE.cxx) $^ \n $(CXXLINK.obj) $(subst .cxx,.obj,$^) $(LOADLIBES) $(LXLIBS) $(LDLIBS) $(CXXRT0) /exe=$@",
+#endif
".for.exe",
"$(COMPILE.for) $^ \n $(LINK.obj) $(subst .for,.obj,$^) $(LOADLIBES) $(LDLIBS) /exe=$@",
".pas.exe",
@@ -125,8 +133,24 @@ static char *default_suffix_rules[] =
".mar.obj",
"$(COMPILE.mar) /obj=$@ $<",
+ ".s.obj",
+ "$(COMPILE.s) /obj=$@ $<",
+ ".ss.obj",
+ "$(COMPILE.s) /obj=$@ $<",
+ ".c.i",
+ "$(COMPILE.c)/prep /list=$@ $<",
+ ".c.s",
+ "$(COMPILE.c)/noobj/machine /list=$@ $<",
+ ".i.s",
+ "$(COMPILE.c)/noprep/noobj/machine /list=$@ $<",
".c.obj",
"$(COMPILE.c) /obj=$@ $<",
+ ".cc.ii",
+ "$(COMPILE.cc)/prep /list=$@ $<",
+ ".cc.ss",
+ "$(COMPILE.cc)/noobj/machine /list=$@ $<",
+ ".ii.ss",
+ "$(COMPILE.cc)/noprep/noobj/machine /list=$@ $<",
".cc.obj",
"$(COMPILE.cc) /obj=$@ $<",
".for.obj",
@@ -276,12 +300,31 @@ static char *default_suffix_rules[] =
static char *default_variables[] =
{
#ifdef VMS
+#ifdef __ALPHA
+ "ARCH", "ALPHA",
+#else
+ "ARCH", "VAX",
+#endif
"AR", "library/obj",
"ARFLAGS", "/replace",
"AS", "macro",
+ "MACRO", "macro",
+#ifdef GCC_IS_NATIVE
+ "CC", "gcc",
+#else
"CC", "cc",
+#endif
+ "CD", "builtin_cd",
+ "MAKE", "make",
+ "ECHO", "write sys$$output \"",
+#ifdef GCC_IS_NATIVE
"C++", "gcc/plus",
"CXX", "gcc/plus",
+#else
+ "C++", "cxx",
+ "CXX", "cxx",
+ "CXXLD", "cxxlink",
+#endif
"CO", "co",
"CPP", "$(CC) /preprocess_only",
"FC", "fortran",
@@ -292,21 +335,43 @@ static char *default_variables[] =
"LD", "link",
"LEX", "lex",
"PC", "pascal",
- "YACC", "yacc", /* Or "bison -y" */
+ "YACC", "bison/yacc",
+ "YFLAGS", "/Define/Verbose",
+ "BISON", "bison",
"MAKEINFO", "makeinfo",
"TEX", "tex",
"TEXINDEX", "texindex",
"RM", "delete/nolog",
+ "CSTARTUP", "",
+#ifdef GCC_IS_NATIVE
+ "CRT0", ",sys$$library:vaxcrtl.olb/lib,gnu_cc_library:crt0.obj",
+ "CXXSTARTUP", "gnu_cc_library:crtbegin.obj",
+ "CXXRT0", ",sys$$library:vaxcrtl.olb/lib,gnu_cc_library:crtend.obj,gnu_cc_library:gxx_main.obj",
+ "LXLIBS", ",gnu_cc_library:libstdcxx.olb/lib,gnu_cc_library:libgccplus.olb/lib",
+ "LDLIBS", ",gnu_cc_library:libgcc.olb/lib",
+#else
+ "CRT0", "",
+ "CXXSTARTUP", "",
+ "CXXRT0", "",
+ "LXLIBS", "",
+ "LDLIBS", "",
+#endif
+
"LINK.obj", "$(LD) $(LDFLAGS)",
+#ifndef GCC_IS_NATIVE
+ "CXXLINK.obj", "$(CXXLD) $(LDFLAGS)",
+ "COMPILE.cxx", "$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH)",
+#endif
"COMPILE.c", "$(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH)",
- "COMPILE.cc", "$(C++) $(C++FLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c",
+ "COMPILE.cc", "$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH)",
"YACC.y", "$(YACC) $(YFLAGS)",
"LEX.l", "$(LEX) $(LFLAGS)",
"COMPILE.for", "$(FC) $(FFLAGS) $(TARGET_ARCH)",
"COMPILE.pas", "$(PC) $(PFLAGS) $(CPPFLAGS) $(TARGET_ARCH)",
- "COMPILE.mar", "$(AS) $(ASFLAGS) $(TARGET_MACH)",
+ "COMPILE.mar", "$(MACRO) $(MACROFLAGS)",
+ "COMPILE.s", "$(AS) $(ASFLAGS) $(TARGET_MACH)",
"LINT.c", "$(LINT) $(LINTFLAGS) $(CPPFLAGS) $(TARGET_ARCH)",
"MV", "rename/new_version",
diff --git a/dir.c b/dir.c
index 5fa1d34..ccc5163 100644
--- a/dir.c
+++ b/dir.c
@@ -22,6 +22,9 @@ Boston, MA 02111-1307, USA. */
#ifdef HAVE_DIRENT_H
# include <dirent.h>
# define NAMLEN(dirent) strlen((dirent)->d_name)
+# ifdef VMS
+extern char *vmsify PARAMS ((char *name, int type));
+# endif
#else
# define dirent direct
# define NAMLEN(dirent) (dirent)->d_namlen
@@ -41,18 +44,18 @@ Boston, MA 02111-1307, USA. */
/* In GNU systems, <dirent.h> defines this macro for us. */
#ifdef _D_NAMLEN
-#undef NAMLEN
-#define NAMLEN(d) _D_NAMLEN(d)
+# undef NAMLEN
+# define NAMLEN(d) _D_NAMLEN(d)
#endif
-#if (defined (POSIX) || defined (WINDOWS32)) && !defined (__GNU_LIBRARY__)
+#if (defined (POSIX) || defined (VMS) || defined (WINDOWS32)) && !defined (__GNU_LIBRARY__)
/* Posix does not require that the d_ino field be present, and some
systems do not provide it. */
-#define REAL_DIR_ENTRY(dp) 1
-#define FAKE_DIR_ENTRY(dp)
+# define REAL_DIR_ENTRY(dp) 1
+# define FAKE_DIR_ENTRY(dp)
#else
-#define REAL_DIR_ENTRY(dp) (dp->d_ino != 0)
-#define FAKE_DIR_ENTRY(dp) (dp->d_ino = 1)
+# define REAL_DIR_ENTRY(dp) (dp->d_ino != 0)
+# define FAKE_DIR_ENTRY(dp) (dp->d_ino = 1)
#endif /* POSIX */
#ifdef __MSDOS__
@@ -156,7 +159,8 @@ vms_hash (name)
while (*name)
{
- h = (h << 4) + *name++;
+ h = (h << 4) + (isupper (*name) ? tolower (*name) : *name);
+ name++;
g = h & 0xf0000000;
if (g)
{
@@ -333,12 +337,12 @@ find_directory (name)
if (vmsstat_dir (name, &st) < 0)
#else
-#ifdef WINDOWS32
+# ifdef WINDOWS32
/* Remove any trailing '\'. Windows32 stat fails even on valid
directories if they end in '\'. */
if (p[-1] == '\\')
p[-1] = '\0';
-#endif
+# endif
if (stat (name, &st) < 0)
#endif
{
@@ -356,14 +360,14 @@ find_directory (name)
w32_path = w32ify(name, 1);
hash = ((unsigned int) st.st_dev << 16) | (unsigned int) st.st_ctime;
#else
-#ifdef VMS
- hash = ((unsigned int) st.st_dev << 16)
- | ((unsigned int) st.st_ino[0]
- + (unsigned int) st.st_ino[1]
- + (unsigned int) st.st_ino[2]);
-#else
+# ifdef VMS
+ hash = (((unsigned int) st.st_dev << 16)
+ | ((unsigned int) st.st_ino[0]
+ + (unsigned int) st.st_ino[1]
+ + (unsigned int) st.st_ino[2]));
+# else
hash = ((unsigned int) st.st_dev << 16) | (unsigned int) st.st_ino;
-#endif
+# endif
#endif
hash %= DIRECTORY_BUCKETS;
@@ -372,13 +376,14 @@ find_directory (name)
if (strieq(dc->path_key, w32_path))
#else
if (dc->dev == st.st_dev
-#ifdef VMS
+# ifdef VMS
&& dc->ino[0] == st.st_ino[0]
&& dc->ino[1] == st.st_ino[1]
- && dc->ino[2] == st.st_ino[2])
-#else
- && dc->ino == st.st_ino)
-#endif
+ && dc->ino[2] == st.st_ino[2]
+# else
+ && dc->ino == st.st_ino
+# endif
+ )
#endif /* WINDOWS32 */
break;
@@ -413,24 +418,22 @@ find_directory (name)
else
dc->fs_flags = FS_UNKNOWN;
#else
-#ifdef VMS
+# ifdef VMS
dc->ino[0] = st.st_ino[0];
dc->ino[1] = st.st_ino[1];
dc->ino[2] = st.st_ino[2];
-#else
+# else
dc->ino = st.st_ino;
-#endif
+# endif
#endif /* WINDOWS32 */
dc->next = directories_contents[hash];
directories_contents[hash] = dc;
dc->dirstream = opendir (name);
if (dc->dirstream == 0)
- {
- /* Couldn't open the directory. Mark this by
- setting the `files' member to a nil pointer. */
- dc->files = 0;
- }
+ /* Couldn't open the directory. Mark this by
+ setting the `files' member to a nil pointer. */
+ dc->files = 0;
else
{
/* Allocate an array of buckets for files and zero it. */
@@ -553,6 +556,14 @@ dir_contents_file_exists_p (dir, filename)
unsigned int len;
register unsigned int i;
+#if defined(VMS) && defined(HAVE_DIRENT_H)
+ /* In VMS we get file versions too, which have to be stripped off */
+ {
+ char *p = strrchr (d->d_name, ';');
+ if (p)
+ *p = '\0';
+ }
+#endif
if (!REAL_DIR_ENTRY (d))
continue;
@@ -636,6 +647,8 @@ file_exists_p (name)
#ifdef VMS
dirend = strrchr (name, ']');
+ if (dirend == 0)
+ dirend = strrchr (name, ':');
dirend++;
if (dirend == (char *)1)
return dir_file_exists_p ("[]", name);
@@ -694,6 +707,8 @@ file_impossible (filename)
#ifdef VMS
dirend = strrchr (p, ']');
+ if (dirend == 0)
+ dirend = strrchr (name, ':');
dirend++;
if (dirend == (char *)1)
dir = find_directory ("[]");
diff --git a/file.c b/file.c
index 1ce4b89..f790eb1 100644
--- a/file.c
+++ b/file.c
@@ -54,7 +54,7 @@ lookup_file (name)
register struct file *f;
register char *n;
register unsigned int hashval;
-#ifdef VMS
+#if defined(VMS) && !defined(WANT_CASE_SENSITIVE_TARGETS)
register char *lname, *ln;
#endif
@@ -65,11 +65,13 @@ lookup_file (name)
for names read from makefiles. It is here for names passed
on the command line. */
#ifdef VMS
+# ifndef WANT_CASE_SENSITIVE_TARGETS
lname = (char *)malloc(strlen(name) + 1);
for (n=name, ln=lname; *n != '\0'; ++n, ++ln)
*ln = isupper((unsigned char)*n) ? tolower((unsigned char)*n) : *n;
*ln = '\0';
name = lname;
+# endif
while (name[0] == '[' && name[1] == ']' && name[2] != '\0')
name += 2;
@@ -103,13 +105,13 @@ lookup_file (name)
{
if (strieq (f->hname, name))
{
-#ifdef VMS
+#if defined(VMS) && !defined(WANT_CASE_SENSITIVE_TARGETS)
free (lname);
#endif
return f;
}
}
-#ifdef VMS
+#if defined(VMS) && !defined(WANT_CASE_SENSITIVE_TARGETS)
free (lname);
#endif
return 0;
@@ -122,14 +124,14 @@ enter_file (name)
register struct file *f, *new;
register char *n;
register unsigned int hashval;
-#ifdef VMS
+#if defined(VMS) && !defined(WANT_CASE_SENSITIVE_TARGETS)
char *lname, *ln;
#endif
if (*name == '\0')
abort ();
-#ifdef VMS
+#if defined(VMS) && !defined(WANT_CASE_SENSITIVE_TARGETS)
lname = (char *)malloc (strlen (name) + 1);
for (n = name, ln = lname; *n != '\0'; ++n, ++ln)
{
@@ -139,6 +141,8 @@ enter_file (name)
*ln = *n;
}
*ln = 0;
+ /* Creates a possible leak, old value of name is unreachable, but I
+ currently don't know how to fix it. */
name = lname;
#endif
@@ -153,7 +157,7 @@ enter_file (name)
if (f != 0 && !f->double_colon)
{
-#ifdef VMS
+#if defined(VMS) && !defined(WANT_CASE_SENSITIVE_TARGETS)
free(lname);
#endif
return f;
diff --git a/glob/glob.c b/glob/glob.c
index 65055fb..4bbf7bb 100644
--- a/glob/glob.c
+++ b/glob/glob.c
@@ -299,6 +299,12 @@ static int glob_in_dir __P ((const char *pattern, const char *directory,
static int prefix_array __P ((const char *prefix, char **array, size_t n));
static int collated_compare __P ((const __ptr_t, const __ptr_t));
+#ifdef VMS
+/* these compilers like prototypes */
+#if !defined _LIBC || !defined NO_GLOB_PATTERN_P
+int __glob_pattern_p (const char *pattern, int quote);
+#endif
+#endif
/* Find the end of the sub-pattern in a brace expression. We define
this as an inline function if the compiler permits. */
@@ -609,7 +615,12 @@ glob (pattern, flags, errfunc, pglob)
if (dirname[1] == '\0' || dirname[1] == '/')
{
/* Look up home directory. */
- const char *home_dir = getenv ("HOME");
+#ifdef VMS
+/* This isn't obvious, RTLs of DECC and VAXC know about "HOME" */
+ const char *home_dir = getenv ("SYS$LOGIN");
+#else
+ const char *home_dir = getenv ("HOME");
+#endif
# ifdef _AMIGA
if (home_dir == NULL || home_dir[0] == '\0')
home_dir = "SYS:";
@@ -618,6 +629,11 @@ glob (pattern, flags, errfunc, pglob)
if (home_dir == NULL || home_dir[0] == '\0')
home_dir = "c:/users/default"; /* poor default */
# else
+# ifdef VMS
+/* Again, this isn't obvious, if "HOME" isn't known "SYS$LOGIN" should be set */
+ if (home_dir == NULL || home_dir[0] == '\0')
+ home_dir = "SYS$DISK:[]";
+# else
if (home_dir == NULL || home_dir[0] == '\0')
{
int success;
@@ -676,6 +692,7 @@ glob (pattern, flags, errfunc, pglob)
else
home_dir = "~"; /* No luck. */
}
+# endif /* VMS */
# endif /* WINDOWS32 */
# endif
/* Now construct the full directory. */
@@ -696,7 +713,7 @@ glob (pattern, flags, errfunc, pglob)
dirname = newp;
}
}
-# if !defined _AMIGA && !defined WINDOWS32
+# if !defined _AMIGA && !defined WINDOWS32 && !defined VMS
else
{
char *end_name = strchr (dirname, '/');
@@ -776,7 +793,7 @@ glob (pattern, flags, errfunc, pglob)
home directory. */
return GLOB_NOMATCH;
}
-# endif /* Not Amiga && not WINDOWS32. */
+# endif /* Not Amiga && not WINDOWS32 && not VMS. */
}
#endif /* Not VMS. */
@@ -1213,6 +1230,10 @@ glob_in_dir (pattern, directory, flags, errfunc, pglob)
int meta;
int save;
+#ifdef VMS
+ if (*directory == 0)
+ directory = "[]";
+#endif
meta = __glob_pattern_p (pattern, !(flags & GLOB_NOESCAPE));
if (meta == 0)
{
diff --git a/glob/glob.h b/glob/glob.h
index 7c2a67a..9f735fe 100644
--- a/glob/glob.h
+++ b/glob/glob.h
@@ -51,7 +51,15 @@ extern "C" {
typedef __SIZE_TYPE__ __size_t;
# else
/* This is a guess. */
+/*hb
+ * Conflicts with DECCs aready defined type __size_t.
+ * Defining an own type with a name beginning with '__' is no good.
+ * Anyway if DECC is used and __SIZE_T is defined then __size_t is
+ * already defined (and I hope it's exactly the one we need here).
+ */
+#if !(defined __DECC && defined __SIZE_T)
typedef unsigned long int __size_t;
+#endif
# endif
#else
/* The GNU CC stddef.h version defines __size_t as empty. We need a real
@@ -118,7 +126,11 @@ typedef struct
struct dirent *(*gl_readdir) __PMT ((void *));
__ptr_t (*gl_opendir) __PMT ((__const char *));
int (*gl_lstat) __PMT ((__const char *, struct stat *));
+#if defined(VMS) && defined(__DECC) && !defined(_POSIX_C_SOURCE)
+ int (*gl_stat) __PMT ((__const char *, struct stat *, ...));
+#else
int (*gl_stat) __PMT ((__const char *, struct stat *));
+#endif
} glob_t;
#ifdef _LARGEFILE64_SOURCE
diff --git a/implicit.c b/implicit.c
index 4156402..c0ca4ed 100644
--- a/implicit.c
+++ b/implicit.c
@@ -163,6 +163,8 @@ pattern_search (file, archive, depth, recursions)
bar/ in directory foo/, not empty in directory foo/bar/.) */
#ifdef VMS
lastslash = strrchr (filename, ']');
+ if (lastslash == 0)
+ lastslash = strrchr (filename, ':');
#else
lastslash = strrchr (filename, '/');
#if defined(__MSDOS__) || defined(WINDOWS32)
@@ -225,7 +227,9 @@ pattern_search (file, archive, depth, recursions)
prefix and the target pattern does not contain a slash. */
#ifdef VMS
- check_lastslash = lastslash != 0 && strchr (target, ']') == 0;
+ check_lastslash = lastslash != 0
+ && ((strchr (target, ']') == 0)
+ && (strchr (target, ':') == 0));
#else
check_lastslash = lastslash != 0 && strchr (target, '/') == 0;
#endif
diff --git a/job.c b/job.c
index c920b9f..c4e30c9 100644
--- a/job.c
+++ b/job.c
@@ -46,7 +46,12 @@ extern int MyExecute (char **);
directories we could trust). */
char *default_shell = "command.com";
# else /* __MSDOS__ */
+# ifdef VMS
+# include <descrip.h>
+char default_shell[] = "";
+# else
char default_shell[] = "/bin/sh";
+# endif /* VMS */
# endif /* __MSDOS__ */
int batch_mode_shell = 0;
# endif /* _AMIGA */
@@ -70,7 +75,9 @@ static int amiga_batch_file;
#ifdef VMS
# include <time.h>
-# include <processes.h>
+# ifndef __GNUC__
+# include <processes.h>
+# endif
# include <starlet.h>
# include <lib$routines.h>
#endif
@@ -186,6 +193,7 @@ extern int start_remote_job_p PARAMS ((int));
extern int remote_status PARAMS ((int *exit_code_ptr, int *signal_ptr,
int *coredump_ptr, int block));
+RETSIGTYPE child_handler PARAMS ((int));
static void free_child PARAMS ((struct child *));
static void start_job_command PARAMS ((struct child *child));
static int load_too_high PARAMS ((void));
@@ -226,7 +234,6 @@ int w32_kill(int pid, int sig)
}
#endif /* WINDOWS32 */
-
/* Write an error message describing the exit status given in
EXIT_CODE, EXIT_SIG, and COREDUMP, for the target TARGET_NAME.
Append "(ignored)" if IGNORED is nonzero. */
@@ -272,6 +279,98 @@ vmsWaitForChildren(int *status)
}
return;
}
+
+/* Set up IO redirection. */
+
+char *
+vms_redirect (desc, fname, ibuf)
+ struct dsc$descriptor_s *desc;
+ char *fname;
+ char *ibuf;
+{
+ char *fptr;
+ extern char *vmsify ();
+
+ ibuf++;
+ while (isspace (*ibuf))
+ ibuf++;
+ fptr = ibuf;
+ while (*ibuf && !isspace (*ibuf))
+ ibuf++;
+ *ibuf = 0;
+ if (strcmp (fptr, "/dev/null") != 0)
+ {
+ strcpy (fname, vmsify (fptr, 0));
+ if (strchr (fname, '.') == 0)
+ strcat (fname, ".");
+ }
+ desc->dsc$w_length = strlen(fname);
+ desc->dsc$a_pointer = fname;
+ desc->dsc$b_dtype = DSC$K_DTYPE_T;
+ desc->dsc$b_class = DSC$K_CLASS_S;
+
+ if (*fname == 0)
+ printf ("Warning: Empty redirection\n");
+ return ibuf;
+}
+
+
+/*
+ found apostrophe at (p-1)
+
+ inc p until after closing apostrophe. */
+
+static char *
+handle_apos (char *p)
+{
+ int alast;
+ int inside;
+
+#define SEPCHARS ",/()= "
+
+ inside = 0;
+
+ while (*p != 0)
+ {
+ if (*p == '"')
+ {
+ if (inside)
+ {
+ while ((alast > 0)
+ && (*p == '"'))
+ {
+ p++;
+ alast--;
+ }
+ if (alast == 0)
+ inside = 0;
+ else
+ {
+ fprintf (stderr, "Syntax error, still inside '\"'\n");
+ exit (3);
+ }
+ }
+ else
+ {
+ p++;
+ if (strchr (SEPCHARS, *p))
+ break;
+ inside = 1;
+ alast = 1;
+ while (*p == '"')
+ {
+ alast++;
+ p++;
+ }
+ }
+ }
+ else
+ p++;
+ }
+
+ return p;
+}
+
#endif
@@ -1603,6 +1702,76 @@ int vmsHandleChildTerm(struct child *child)
#define MAXCMDLEN 200
+/* local helpers to make ctrl+c and ctrl+y working, see below */
+#include <iodef.h>
+#include <libclidef.h>
+#include <ssdef.h>
+
+static int ctrlMask= LIB$M_CLI_CTRLY;
+static int oldCtrlMask;
+static int setupYAstTried= 0;
+static int pidToAbort= 0;
+static int chan= 0;
+
+static void reEnableAst(void) {
+ lib$enable_ctrl (&oldCtrlMask,0);
+}
+
+static astHandler (void) {
+ if (pidToAbort) {
+ sys$forcex (&pidToAbort, 0, SS$_ABORT);
+ pidToAbort= 0;
+ }
+ kill (getpid(),SIGQUIT);
+}
+
+static void tryToSetupYAst(void) {
+ $DESCRIPTOR(inputDsc,"SYS$COMMAND");
+ int status;
+ struct {
+ short int status, count;
+ int dvi;
+ } iosb;
+
+ setupYAstTried++;
+
+ if (!chan) {
+ status= sys$assign(&inputDsc,&chan,0,0);
+ if (!(status&SS$_NORMAL)) {
+ lib$signal(status);
+ return;
+ }
+ }
+ status= sys$qiow (0, chan, IO$_SETMODE|IO$M_CTRLYAST,&iosb,0,0,
+ astHandler,0,0,0,0,0);
+ if (status==SS$_ILLIOFUNC) {
+ sys$dassgn(chan);
+#ifdef CTRLY_ENABLED_ANYWAY
+ fprintf (stderr, "-warning, CTRL-Y will leave "
+ "sub-process(es) around.\n");
+#else
+ return;
+#endif
+ }
+ if (status==SS$_NORMAL)
+ status= iosb.status;
+ if (!(status&SS$_NORMAL)) {
+ lib$signal(status);
+ return;
+ }
+
+ /* called from AST handler ? */
+ if (setupYAstTried>1)
+ return;
+ if (atexit(reEnableAst))
+ fprintf (stderr, "-warning, you may have to re-enable CTRL-Y"
+ "handling from DCL.\n");
+ status= lib$disable_ctrl (&ctrlMask, &oldCtrlMask);
+ if (!(status&SS$_NORMAL)) {
+ lib$signal(status);
+ return;
+ }
+}
int
child_execute_job (argv, child)
char *argv;
@@ -1610,32 +1779,187 @@ child_execute_job (argv, child)
{
int i;
static struct dsc$descriptor_s cmddsc;
-#ifndef DONTWAITFORCHILD
- int spflags = 0;
-#else
+ static struct dsc$descriptor_s pnamedsc;
+ static struct dsc$descriptor_s ifiledsc;
+ static struct dsc$descriptor_s ofiledsc;
+ static struct dsc$descriptor_s efiledsc;
+ int have_redirection = 0;
+ int have_newline = 0;
+
int spflags = CLI$M_NOWAIT;
-#endif
int status;
- char cmd[4096],*p,*c;
+ char *cmd = alloca (strlen (argv) + 512), *p, *q;
+ char ifile[256], ofile[256], efile[256];
char comname[50];
+ char procname[100];
+
+ /* Parse IO redirection. */
+
+ ifile[0] = 0;
+ ofile[0] = 0;
+ efile[0] = 0;
+
+ if (debug_flag)
+ printf ("child_execute_job (%s)\n", argv);
+
+ while (isspace (*argv))
+ argv++;
+
+ if (*argv == 0)
+ return 0;
+
+ sprintf (procname, "GMAKE_%05x", getpid () & 0xfffff);
+ pnamedsc.dsc$w_length = strlen(procname);
+ pnamedsc.dsc$a_pointer = procname;
+ pnamedsc.dsc$b_dtype = DSC$K_DTYPE_T;
+ pnamedsc.dsc$b_class = DSC$K_CLASS_S;
+
+ /* Handle comments and redirection. */
+ for (p = argv, q = cmd; *p; p++, q++)
+ {
+ switch (*p)
+ {
+ case '#':
+ *p-- = 0;
+ *q-- = 0;
+ break;
+ case '\\':
+ p++;
+ if (*p == '\n')
+ p++;
+ if (isspace (*p))
+ {
+ do { p++; } while (isspace (*p));
+ p--;
+ }
+ *q = *p;
+ break;
+ case '<':
+ p = vms_redirect (&ifiledsc, ifile, p);
+ *q = ' ';
+ have_redirection = 1;
+ break;
+ case '>':
+ have_redirection = 1;
+ if (*(p-1) == '2')
+ {
+ q--;
+ if (strncmp (p, ">&1", 3) == 0)
+ {
+ p += 3;
+ strcpy (efile, "sys$output");
+ efiledsc.dsc$w_length = strlen(efile);
+ efiledsc.dsc$a_pointer = efile;
+ efiledsc.dsc$b_dtype = DSC$K_DTYPE_T;
+ efiledsc.dsc$b_class = DSC$K_CLASS_S;
+ }
+ else
+ {
+ p = vms_redirect (&efiledsc, efile, p);
+ }
+ }
+ else
+ {
+ p = vms_redirect (&ofiledsc, ofile, p);
+ }
+ *q = ' ';
+ break;
+ case '\n':
+ have_newline = 1;
+ default:
+ *q = *p;
+ break;
+ }
+ }
+ *q = *p;
-/* Remove backslashes */
- for (p = argv, c = cmd; *p; p++,c++)
+ if (strncmp (cmd, "builtin_", 8) == 0)
{
- if (*p == '\\') p++;
- *c = *p;
+ child->pid = 270163;
+ child->efn = 0;
+ child->cstatus = 1;
+
+ if (debug_flag)
+ printf ("BUILTIN [%s][%s]\n", cmd, cmd+8);
+
+ p = cmd + 8;
+
+ if ((*(p) == 'c')
+ && (*(p+1) == 'd')
+ && ((*(p+2) == ' ') || (*(p+2) == '\t')))
+ {
+ p += 3;
+ while ((*p == ' ') || (*p == '\t'))
+ p++;
+ if (debug_flag)
+ printf ("BUILTIN CD %s\n", p);
+ if (chdir (p))
+ return 0;
+ else
+ return 1;
+ }
+ else if ((*(p) == 'r')
+ && (*(p+1) == 'm')
+ && ((*(p+2) == ' ') || (*(p+2) == '\t')))
+ {
+ int in_arg;
+
+ /* rm */
+ p += 3;
+ while ((*p == ' ') || (*p == '\t'))
+ p++;
+ in_arg = 1;
+
+ if (debug_flag)
+ printf ("BUILTIN RM %s\n", p);
+ while (*p)
+ {
+ switch (*p)
+ {
+ case ' ':
+ case '\t':
+ if (in_arg)
+ {
+ *p++ = ';';
+ in_arg = 0;
+ }
+ break;
+ default:
+ break;
+ }
+ p++;
+ }
+ }
+ else
+ {
+ printf("Unknown builtin command '%s'\n", cmd);
+ fflush(stdout);
+ return 0;
+ }
}
- *c = *p;
- /* Check for maximum DCL length and create *.com file if neccesary.
- Also create a .com file if the command is more than one line long. */
+ /* Create a *.com file if either the command is too long for
+ lib$spawn, or the command contains a newline, or if redirection
+ is desired. Forcing commands with newlines into DCLs allows to
+ store search lists on user mode logicals. */
comname[0] = '\0';
- if (strlen (cmd) > MAXCMDLEN || strchr (cmd, '\n'))
+ if (strlen (cmd) > MAXCMDLEN
+ || (have_redirection != 0)
+ || (have_newline != 0))
{
FILE *outfile;
- char tmp;
+ char c;
+ char *sep;
+ int alevel = 0; /* apostrophe level */
+
+ if (strlen (cmd) == 0)
+ {
+ printf ("Error, empty command\n");
+ fflush (stdout);
+ return 0;
+ }
strcpy (comname, "sys$scratch:CMDXXXXXX.COM");
(void) mktemp (comname);
@@ -1644,27 +1968,81 @@ child_execute_job (argv, child)
if (outfile == 0)
pfatal_with_name (comname);
- fprintf (outfile, "$ ");
- c = cmd;
+ if (ifile[0])
+ {
+ fprintf (outfile, "$ assign/user %s sys$input\n", ifile);
+ DB (DB_JOBS, (_("Redirected input from %s\n"), ifile));
+ ifiledsc.dsc$w_length = 0;
+ }
+
+ if (efile[0])
+ {
+ fprintf (outfile, "$ define sys$error %s\n", efile);
+ DB (DB_JOBS, (_("Redirected error to %s\n"), efile));
+ efiledsc.dsc$w_length = 0;
+ }
+
+ if (ofile[0])
+ {
+ fprintf (outfile, "$ define sys$output %s\n", ofile);
+ DB (DB_JOBS, (_("Redirected output to %s\n"), ofile));
+ ofiledsc.dsc$w_length = 0;
+ }
- while (c)
+ p = sep = q = cmd;
+ for (c = '\n'; c; c = *q++)
{
- p = strchr (c, ',');
- if ((p == NULL) || (p-c > MAXCMDLEN))
- p = strchr (c, ' ');
- if (p != NULL)
+ switch (c)
{
- p++;
- tmp = *p;
- *p = '\0';
+ case '\n':
+ /* At a newline, skip any whitespace around a leading $
+ from the command and issue exactly one $ into the DCL. */
+ while (isspace (*p))
+ p++;
+ if (*p == '$')
+ p++;
+ while (isspace (*p))
+ p++;
+ fwrite (p, 1, q - p, outfile);
+ fputc ('$', outfile);
+ fputc (' ', outfile);
+ /* Reset variables. */
+ p = sep = q;
+ break;
+
+ /* Nice places for line breaks are after strings, after
+ comma or space and before slash. */
+ case '"':
+ q = handle_apos (q + 1);
+ sep = q;
+ break;
+ case ',':
+ case ' ':
+ sep = q;
+ break;
+ case '/':
+ case '\0':
+ sep = q - 1;
+ break;
+ default:
+ break;
}
- else
- tmp = '\0';
- fprintf (outfile, "%s%s\n", c, (tmp == '\0')?"":" -");
- if (p != NULL)
- *p = tmp;
- c = p;
- }
+ if (sep - p > 78)
+ {
+ /* Enough stuff for a line. */
+ fwrite (p, 1, sep - p, outfile);
+ p = sep;
+ if (*sep)
+ {
+ /* The command continues. */
+ fputc ('-', outfile);
+ }
+ fputc ('\n', outfile);
+ }
+ }
+
+ fwrite (p, 1, q - p, outfile);
+ fputc ('\n', outfile);
fclose (outfile);
@@ -1681,31 +2059,98 @@ child_execute_job (argv, child)
child->efn = 0;
while (child->efn < 32 || child->efn > 63)
{
- status = lib$get_ef(&child->efn);
+ status = lib$get_ef ((unsigned long *)&child->efn);
if (!(status & 1))
return 0;
}
- sys$clref(child->efn);
+ sys$clref (child->efn);
vms_jobsefnmask |= (1 << (child->efn - 32));
+/*
+ LIB$SPAWN [command-string]
+ [,input-file]
+ [,output-file]
+ [,flags]
+ [,process-name]
+ [,process-id] [,completion-status-address] [,byte-integer-event-flag-num]
+ [,AST-address] [,varying-AST-argument]
+ [,prompt-string] [,cli] [,table]
+*/
+
#ifndef DONTWAITFORCHILD
- status = lib$spawn(&cmddsc,0,0,&spflags,0,&child->pid,&child->cstatus,
- &child->efn,0,0);
+/*
+ * Code to make ctrl+c and ctrl+y working.
+ * The problem starts with the synchronous case where after lib$spawn is
+ * called any input will go to the child. But with input re-directed,
+ * both control characters won't make it to any of the programs, neither
+ * the spawning nor to the spawned one. Hence the caller needs to spawn
+ * with CLI$M_NOWAIT to NOT give up the input focus. A sys$waitfr
+ * has to follow to simulate the wanted synchronous behaviour.
+ * The next problem is ctrl+y which isn't caught by the crtl and
+ * therefore isn't converted to SIGQUIT (for a signal handler which is
+ * already established). The only way to catch ctrl+y, is an AST
+ * assigned to the input channel. But ctrl+y handling of DCL needs to be
+ * disabled, otherwise it will handle it. Not to mention the previous
+ * ctrl+y handling of DCL needs to be re-established before make exits.
+ * One more: At the time of LIB$SPAWN signals are blocked. SIGQUIT will
+ * make it to the signal handler after the child "normally" terminates.
+ * This isn't enough. It seems reasonable for simple command lines like
+ * a 'cc foobar.c' spawned in a subprocess but it is unacceptable for
+ * spawning make. Therefore we need to abort the process in the AST.
+ *
+ * Prior to the spawn it is checked if an AST is already set up for
+ * ctrl+y, if not one is set up for a channel to SYS$COMMAND. In general
+ * this will work except if make is run in a batch environment, but there
+ * nobody can press ctrl+y. During the setup the DCL handling of ctrl+y
+ * is disabled and an exit handler is established to re-enable it.
+ * If the user interrupts with ctrl+y, the assigned AST will fire, force
+ * an abort to the subprocess and signal SIGQUIT, which will be caught by
+ * the already established handler and will bring us back to common code.
+ * After the spawn (now /nowait) a sys$waitfr simulates the /wait and
+ * enables the ctrl+y be delivered to this code. And the ctrl+c too,
+ * which the crtl converts to SIGINT and which is caught by the common
+ * signal handler. Because signals were blocked before entering this code
+ * sys$waitfr will always complete and the SIGQUIT will be processed after
+ * it (after termination of the current block, somewhere in common code).
+ * And SIGINT too will be delayed. That is ctrl+c can only abort when the
+ * current command completes. Anyway it's better than nothing :-)
+ */
+
+ if (!setupYAstTried)
+ tryToSetupYAst();
+ status = lib$spawn (&cmddsc, /* cmd-string */
+ (ifiledsc.dsc$w_length == 0)?0:&ifiledsc, /* input-file */
+ (ofiledsc.dsc$w_length == 0)?0:&ofiledsc, /* output-file */
+ &spflags, /* flags */
+ &pnamedsc, /* proc name */
+ &child->pid, &child->cstatus, &child->efn,
+ 0, 0,
+ 0, 0, 0);
+ pidToAbort= child->pid;
+ status= sys$waitfr (child->efn);
+ pidToAbort= 0;
vmsHandleChildTerm(child);
#else
- status = lib$spawn(&cmddsc,0,0,&spflags,0,&child->pid,&child->cstatus,
- &child->efn,vmsHandleChildTerm,child);
+ status = lib$spawn (&cmddsc,
+ (ifiledsc.dsc$w_length == 0)?0:&ifiledsc,
+ (ofiledsc.dsc$w_length == 0)?0:&ofiledsc,
+ &spflags,
+ &pnamedsc,
+ &child->pid, &child->cstatus, &child->efn,
+ vmsHandleChildTerm, child,
+ 0, 0, 0);
#endif
if (!(status & 1))
{
- printf(_("Error spawning, %d\n"),status);
- fflush(stdout);
+ printf ("Error spawning, %d\n",status);
+ fflush (stdout);
}
- unlink (comname);
+ if (comname[0] && !ISDB (DB_JOBS)))
+ unlink (comname);
return (status & 1);
}
@@ -1748,6 +2193,10 @@ exec_command (argv, envp)
char **argv, **envp;
{
#ifdef VMS
+ /* to work around a problem with signals and execve: ignore them */
+#ifdef SIGCHLD
+ signal (SIGCHLD,SIG_IGN);
+#endif
/* Run the program. */
execve (argv[0], argv, envp);
perror_with_name ("execve: ", argv[0]);
@@ -2337,7 +2786,11 @@ construct_command_argv_internal (line, restp, shell, ifs, batch_filename_ptr)
argument list. */
unsigned int shell_len = strlen (shell);
+#ifndef VMS
static char minus_c[] = " -c ";
+#else
+ static char minus_c[] = "";
+#endif
unsigned int line_len = strlen (line);
char *new_line = (char *) alloca (shell_len + (sizeof (minus_c) - 1)
@@ -2480,6 +2933,7 @@ construct_command_argv_internal (line, restp, shell, ifs, batch_filename_ptr)
return new_argv;
}
+#endif /* !VMS */
/* Figure out the argument list necessary to run LINE as a command. Try to
avoid using a shell. This routine handles only ' quoting, and " quoting
@@ -2503,6 +2957,48 @@ construct_command_argv (line, restp, file, batch_filename_ptr)
char *shell, *ifs;
char **argv;
+#ifdef VMS
+ char *cptr;
+ int argc;
+
+ argc = 0;
+ cptr = line;
+ for (;;)
+ {
+ while ((*cptr != 0)
+ && (isspace (*cptr)))
+ cptr++;
+ if (*cptr == 0)
+ break;
+ while ((*cptr != 0)
+ && (!isspace(*cptr)))
+ cptr++;
+ argc++;
+ }
+
+ argv = (char **)malloc (argc * sizeof (char *));
+ if (argv == 0)
+ abort ();
+
+ cptr = line;
+ argc = 0;
+ for (;;)
+ {
+ while ((*cptr != 0)
+ && (isspace (*cptr)))
+ cptr++;
+ if (*cptr == 0)
+ break;
+ if (debug_flag)
+ printf ("argv[%d] = [%s]\n", argc, cptr);
+ argv[argc++] = cptr;
+ while ((*cptr != 0)
+ && (!isspace(*cptr)))
+ cptr++;
+ if (*cptr != 0)
+ *cptr++ = 0;
+ }
+#else
{
/* Turn off --warn-undefined-variables while we expand SHELL and IFS. */
int save = warn_undefined_variables_flag;
@@ -2528,10 +3024,9 @@ construct_command_argv (line, restp, file, batch_filename_ptr)
free (shell);
free (ifs);
-
+#endif /* !VMS */
return argv;
}
-#endif /* !VMS */
#if !defined(HAVE_DUP2) && !defined(_AMIGA)
int
diff --git a/make.h b/make.h
index 8f1b057..18eb1c9 100644
--- a/make.h
+++ b/make.h
@@ -312,6 +312,9 @@ extern char *alloca ();
# define strieq(a, b) (strcmp ((a), (b)) == 0)
#endif
#define strneq(a, b, l) (strncmp ((a), (b), (l)) == 0)
+#ifdef VMS
+extern int strcmpi (const char *,const char *);
+#endif
/* Add to VAR the hashing value of C, one character in a name. */
#define HASH(var, c) \
@@ -449,10 +452,9 @@ extern long int lseek ();
#endif /* Not GNU C library or POSIX. */
#ifdef HAVE_GETCWD
+# if !defined(VMS) && !defined(__DECC)
extern char *getcwd ();
-# ifdef VMS
-extern char *getwd PARAMS ((char *));
-# endif
+#endif
#else
extern char *getwd ();
# define getcwd(buf, len) getwd (buf)
diff --git a/makefile.com b/makefile.com
index f180df2..5a0f884 100644
--- a/makefile.com
+++ b/makefile.com
@@ -7,6 +7,13 @@ $! P2 = DEBUG will build an image with debug information
$!
$! In case of problems with the install you might contact me at
$! zinser@decus.decus.de (preferred) or martin_zinser@exchange.de
+$
+$! hb
+$! But don't ask Martin Zinser about the lines, I added/changed.
+$! In case of an error do some cleanup
+$ on error then $ goto cleanup
+$! in case somebody set up her/his own symbol for cc
+$ set symbol/scope=(nolocal,noglobal)
$!
$! Look for the compiler used
$!
@@ -57,9 +64,16 @@ $ linkit:
$ close optf
$ if p1 .nes. "" then goto link_using_library
$ link/exe=make make.opt/opt'lopt
-$ exit
+$ goto cleanup
+$
$ link_using_library:
$ link/exe=make make.opt/opt,sys$library:vaxcrtl/lib'lopt
+$
+$ cleanup:
+$ if f$trnlnm("SYS").nes."" then $ deassign sys
+$ if f$trnlnm("OPTF").nes."" then $ close optf
+$ if f$search("make.opt").nes."" then $ del make.opt;*
+$ exit
$!
$ compileit : subroutine
$ ploc = f$locate("]",p1)
diff --git a/makefile.vms b/makefile.vms
index 9b8208a..9a780d8 100644
--- a/makefile.vms
+++ b/makefile.vms
@@ -2,7 +2,8 @@
# This file is part of GNU Make.
#
# VMS extensions from GNU Make 3.60 imported by
-# Klaus Kämpf (kkaempf@progis.de) of proGIS Software, Aachen, Germany
+# Klaus Kämpf (kkaempf@rmi.de)
+# Modified for version 3.78.1 by Hartmut.Becker@compaq.com.
#
# GNU Make is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -19,7 +20,7 @@
# the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.
-CC = cc/warn
+CC = cc
CP = copy
%.obj: %.c
@@ -28,11 +29,23 @@ CP = copy
# Makefile for GNU Make
#
-CFLAGS = $(defines) /debug/noopt/include=([],[.glob])
+ifeq ($(CC),cc)
+CFLAGS = $(defines) /include=([],[.glob])/prefix=all/standard=relaxed
+else
+CFLAGS = $(defines) /include=([],[.glob])
+endif
#LDFLAGS = /deb
LDFLAGS =
+ifeq ($(CC),cc)
defines = /define=("unlink=remove","HAVE_CONFIG_H","VMS","allocated_variable_expand_for_file=alloc_var_expand_for_file")
+else
+ifeq ($(ARCH),VAX)
+defines = /define=("HAVE_CONFIG_H","GCC_IS_NATIVE","VAX")
+else
+defines = /define=("HAVE_CONFIG_H","GCC_IS_NATIVE")
+endif
+endif
LOAD_AVG = /define="NO_LDAV"
@@ -44,12 +57,17 @@ ARCHIVES_SRC = ar.c arscan.c
# System V probably need -lPW for alloca.
# if on vax, uncomment the following line
#LOADLIBES = ,c.opt/opt
-LOADLIBES =,sys$$library:vaxcrtl.olb/lib
+ifeq ($(CC),cc)
+#LOADLIBES =,sys$$library:vaxcrtl.olb/lib
+CRT0 =
+else
+LOADLIBES =,gnu_cc_library:libgcc.olb/lib
+endif
# If your system doesn't have alloca, or the one provided is bad,
# get it from the Emacs distribution and define these.
-ALLOCA = ,alloca.obj
-ALLOCASRC = alloca.c
+#ALLOCA = ,alloca.obj
+#ALLOCASRC = alloca.c
# If there are remote execution facilities defined,
# enable them with switches here (see remote-*.c).
@@ -86,11 +104,14 @@ doc: make.info make.dvi
make.exe: $(objs)
- $(LD)$(LDFLAGS)/exe=$@ $^$(LOADLIBES)
+ $(LD)$(LDFLAGS)/exe=$@ $^$(LOADLIBES)$(CRT0)
.PHONY: clean realclean
clean:
- -$(RM) make.exe;,*.obj;*
+ $$ purge [...]
+ -$(RM) make.exe;,*.obj;
+ -$(RM) *.opt;
+ -$(RM) [.glob]*.obj;
# Automatically generated dependencies.
commands.obj: commands.c make.h dep.h commands.h filedef.h variable.h job.h
@@ -108,7 +129,7 @@ variable.obj: variable.c make.h commands.h variable.h dep.h filedef.h
expand.obj: expand.c make.h commands.h filedef.h variable.h
function.obj: function.c make.h variable.h dep.h commands.h job.h
vpath.obj: vpath.c make.h filedef.h variable.h
-version.obj: version.c
+version.obj: version.c config.h
arscan.obj: arscan.c
ar.obj: ar.c make.h filedef.h
signame.obj: signame.c
@@ -117,6 +138,8 @@ remote-stub.obj: remote-stub.c
[.glob]fnmatch.obj: [.glob]fnmatch.c
getopt.obj: getopt.c
getopt1.obj: getopt1.c
+vmsfunctions.obj: vmsfunctions.c make.h vmsdir.h
+vmsify.obj: vmsify.c make.h
config.h: config.h-vms
$(CP) $< $@
diff --git a/readme.vms b/readme.vms
index 43b4dd0..dacc394 100644
--- a/readme.vms
+++ b/readme.vms
@@ -1,9 +1,111 @@
+This is the VMS port of GNU Make done by Hartmut.Becker@compaq.com.
+
+It is based on the specific version 3.77k and on 3.78.1. 3.77k was done
+by Klaus Kämpf <kkaempf@rmi.de>, the code was based on the VMS port of
+GNU Make 3.60 by Mike Moretti.
+
+It was ported on OpenVMS/Alpha V7.1, DECC V5.7-006. It was re-build and
+tested on OpenVMS/Alpha V7.2, OpenVMS/VAX 7.1 and 5.5-2. Different
+versions of DECC were used. VAXC was tried: it fails; but it doesn't
+seem worth to get it working. There are still some PTRMISMATCH warnings
+during the compile. Although perl is working on VMS the test scripts
+don't work. The function $shell is still missing.
+
+New in 3.78.1:
+
+Fix a problem with automatically remaking makefiles. GNU make uses an
+execve to restart itself after a successful remake of the makefile. On
+UNIX systems execve replaces the running program with a new one and
+resets all signal handling to the default. On VMS execve creates a child
+process, signal and exit handlers of the parent are still active, and,
+unfortunately, corrupt the exit code from the child. Fix in job.c:
+ignore SIGCHLD.
+
+Added some switches to reflect latest features of DECC. Modifications in
+makefile.vms.
+
+Set some definitions to reflect latest features of DECC. Modifications in
+config.h-vms (which is copied to config.h).
+
+Added extern strcmpi declaration to avoid 'implicitly declared' messages.
+Modification in make.h.
+
+Default rule for C++, conditionals for gcc (GCC_IS_NATIVE) or DEC/Digital/
+Compaq c/c++ compilers. Modifications in default.c.
+
+Usage of opendir() and friends, suppress file version. Modifications in dir.c.
+
+Added VMS specific code to handle ctrl+c and ctrl+y to abort make.
+Modifications in job.c.
+
+Added support to have case sensitive targets and dependencies but to
+still use case blind file names. This is especially useful for Java
+makefiles on VMS:
+
+ .SUFFIXES :
+ .SUFFIXES : .class .java
+ .java.class :
+ javac "$<
+ HelloWorld.class : HelloWorld.java
+
+A new macro WANT_CASE_SENSITIVE_TARGETS in config.h-vms was introduced.
+It needs to be enabled to get this feature; default is disabled. The
+macro HAVE_CASE_INSENSITIVE_FS must not be touched: it is still enabled.
+Modifications in file.c and config.h-vms.
+
+Bootstrap make to start building make is still makefile.com, but make
+needs to be re-made with a make to make a correct version: ignore all
+possible warnings, delete all objects, rename make.exe to a different
+name and run it.
+
+Made some minor modifications to the bootstrap build makefile.com.
+
This is the VMS port of GNU Make.
It is based on the VMS port of GNU Make 3.60 by Mike Moretti.
-This port was done by Klaus Kämpf <kkaempf@progis.de> of
-proGIS Software, Aachen, Germany.
+This port was done by Klaus Kämpf <kkaempf@rmi.de>
+
+There is first-level support available from proGIS Software, Germany.
+Visit their web-site at http://www.progis.de to get information
+about other vms software and forthcoming updates to gnu make.
+
+New for 3.77:
+
+/bin/sh style I/O redirection is supported. You can now write lines like
+ mcr sys$disk:[]program.exe < input.txt > output.txt &> error.txt
+
+Makefile variables are looked up in the current environment. You can set
+symbols or logicals in DCL and evaluate them in the Makefile via
+$(<name-of-symbol-or-logical>). Variables defined in the Makefile
+override VMS symbols/logicals !
+
+Functions for file names are working now. See the GNU Make manual for
+$(dir ...) and $(wildcard ...). Unix-style and VMS-style names are
+supported as arguments.
+
+The default rules are set up for GNU C. Building an executable from a
+single source file is as easy as 'make file.exe'.
+
+The variable $(ARCH) is predefined as ALPHA or VAX resp. Makefiles for
+different VMS systems can now be written by checking $(ARCH) as in
+ ifeq ($(ARCH),ALPHA)
+ $(ECHO) "On the Alpha"
+ else
+ $(ECHO) "On the VAX"
+ endif
+
+Command lines of excessive length are correctly broken and written to a
+batch file in sys$scratch for later execution. There's no limit to the
+lengths of commands (and no need for .opt files :-) any more.
+
+Empty commands are handled correctly and don't end in a new DCL process.
+
+
+New for 3.76:
+
+John W. Eaton has updated the VMS port to support libraries and VPATH.
+
To build Make, simply type @makefile. This should compile all the
necessary files and link Make. There is also a file called
@@ -12,6 +114,16 @@ Make with this makefile to rebuild.
Here are some notes about GNU Make for VMS:
+The cd command is supported if it's called as $(CD). This invokes
+the 'builtin_cd' command which changes the directory.
+Calling 'set def' doesn't do the trick, since a sub-shell is
+spawned for this command, the directory is changed *in this sub-shell*
+and the sub-shell ends.
+
+Libraries are not supported. They were in GNU Make 3.60 but somehow I
+didn't care porting the code. If there is enough interest, I'll do it at
+some later time.
+
The variable $^ separates files with commas instead of spaces (It's the
natural thing to do for VMS).
@@ -26,8 +138,8 @@ The default include directory for including other makefiles is
SYS$SYSROOT:[SYSLIB] (I don't remember why I didn't just use
SYS$LIBRARY: instead; maybe it wouldn't work that way).
-The default makefiles make looks for are: makefile.vms, gnumakefile, makefile.,
-and gnumakefile. .
+The default makefiles make looks for are: makefile.vms, gnumakefile,
+makefile., and gnumakefile. .
The stat() function and handling of time stamps in VMS is broken, so I
replaced it with a hack in vmsfunctions.c. I will provide a full rewrite
@@ -37,9 +149,9 @@ less than what vms provides. This might be a problem on the faster Alphas.
You can use a : in a filename only if you preceed it with a backslash ('\').
E.g.- hobbes\:[bogas.files]
-Make ignores success, informational, or warning errors (-S-, -I-, or -W-).
-But it will stop on -E- and -F- errors. (unless you do something to override
-this in your makefile, or whatever).
+Make ignores success, informational, or warning errors (-S-, -I-, or
+-W-). But it will stop on -E- and -F- errors. (unless you do something
+to override this in your makefile, or whatever).
Remote stuff isn't implemented yet.
@@ -47,18 +159,10 @@ Multiple line DCL commands, such as "if" statements, must be put inside
command files. You can run a command file by using \@.
-Change history:
+VMS changes made for 3.74.3
-3.76.x
-======
-Added VMS help version (make.hlp) of the Unix man page. To integrate
-that with an existing Help library use a command like the following
- $lib/ins/help sys$help:helplib.hlb make.hlp
-3.74.3
-======
Lots of default settings are adapted for VMS. See default.c.
Long command lines are now converted to command files.
Comma (',') as a separator is now allowed. See makefile.vms for an example.
-
diff --git a/rule.c b/rule.c
index 90e04e3..5933777 100644
--- a/rule.c
+++ b/rule.c
@@ -109,10 +109,14 @@ count_implicit_rule_limits ()
#ifdef VMS
char *p = strrchr (dep->name, ']');
+ char *p2;
+ if (p == 0)
+ p = strrchr (dep->name, ':');
+ p2 = p != 0 ? strchr (dep->name, '%') : 0;
#else
char *p = strrchr (dep->name, '/');
-#endif
char *p2 = p != 0 ? strchr (dep->name, '%') : 0;
+#endif
ndeps++;
if (len > max_pattern_dep_length)
@@ -140,7 +144,7 @@ count_implicit_rule_limits ()
dep->changed = !dir_file_exists_p (name, "");
#ifdef VMS
- if (dep->changed && *name == ']')
+ if (dep->changed && strchr (name, ':') != 0)
#else
if (dep->changed && *name == '/')
#endif
diff --git a/variable.c b/variable.c
index 8058a74..6d105b2 100644
--- a/variable.c
+++ b/variable.c
@@ -182,6 +182,63 @@ lookup_variable (name, length)
return v;
}
+#ifdef VMS
+ /* since we don't read envp[] on startup, try to get the
+ variable via getenv() here. */
+
+ {
+ char *vname = alloca (length + 1);
+ char *value;
+ strncpy (vname, name, length);
+ vname[length] = 0;
+ value = getenv (vname);
+ if (value != 0)
+ {
+ char *sptr;
+ int scnt;
+
+ sptr = value;
+ scnt = 0;
+
+ while ((sptr = strchr (sptr, '$')))
+ {
+ scnt++;
+ sptr++;
+ }
+
+ if (scnt > 0)
+ {
+ char *nvalue;
+ char *nptr;
+
+ nvalue = alloca (length + scnt + 1);
+ sptr = value;
+ nptr = nvalue;
+
+ while (*sptr)
+ {
+ if (*sptr == '$')
+ {
+ *nptr++ = '$';
+ *nptr++ = '$';
+ }
+ else
+ {
+ *nptr++ = *sptr;
+ }
+ sptr++;
+ }
+
+ return define_variable (vname, length, nvalue, o_env, 1);
+
+ }
+
+ return define_variable (vname, length, value, o_env, 1);
+ }
+ }
+
+#endif /* VMS */
+
return 0;
}
@@ -457,6 +514,15 @@ define_automatic_variables ()
/* Define the magic D and F variables in terms of
the automatic variables they are variations of. */
+#ifdef VMS
+ define_variable ("@D", 2, "$(dir $@)", o_automatic, 1);
+ define_variable ("%D", 2, "$(dir $%)", o_automatic, 1);
+ define_variable ("*D", 2, "$(dir $*)", o_automatic, 1);
+ define_variable ("<D", 2, "$(dir $<)", o_automatic, 1);
+ define_variable ("?D", 2, "$(dir $?)", o_automatic, 1);
+ define_variable ("^D", 2, "$(dir $^)", o_automatic, 1);
+ define_variable ("+D", 2, "$(dir $+)", o_automatic, 1);
+#else
define_variable ("@D", 2, "$(patsubst %/,%,$(dir $@))", o_automatic, 1);
define_variable ("%D", 2, "$(patsubst %/,%,$(dir $%))", o_automatic, 1);
define_variable ("*D", 2, "$(patsubst %/,%,$(dir $*))", o_automatic, 1);
@@ -464,6 +530,7 @@ define_automatic_variables ()
define_variable ("?D", 2, "$(patsubst %/,%,$(dir $?))", o_automatic, 1);
define_variable ("^D", 2, "$(patsubst %/,%,$(dir $^))", o_automatic, 1);
define_variable ("+D", 2, "$(patsubst %/,%,$(dir $+))", o_automatic, 1);
+#endif
define_variable ("@F", 2, "$(notdir $@)", o_automatic, 1);
define_variable ("%F", 2, "$(notdir $%)", o_automatic, 1);
define_variable ("*F", 2, "$(notdir $*)", o_automatic, 1);
diff --git a/vmsdir.h b/vmsdir.h
index 4cf1583..5903475 100644
--- a/vmsdir.h
+++ b/vmsdir.h
@@ -1,15 +1,21 @@
/* dirent.h for vms */
+#ifndef VMSDIR_H
+#define VMSDIR_H
+
#include <rms.h>
#define MAXNAMLEN 255
#ifndef __DECC
+#if !defined (__GNUC__) && !defined (__ALPHA)
typedef unsigned long u_long;
typedef unsigned short u_short;
#endif
+#endif
-struct direct {
+struct direct
+{
off_t d_off;
u_long d_fileno;
u_short d_reclen;
@@ -18,8 +24,11 @@ struct direct {
};
#undef DIRSIZ
-#define DIRSIZ(dp) \
- (((sizeof (struct direct) - (MAXNAMLEN+1) + ((dp)->d_namlen+1)) + 3) & ~3)
+#define DIRSIZ(dp) \
+ (((sizeof (struct direct) \
+ - (MAXNAMLEN+1) \
+ + ((dp)->d_namlen+1)) \
+ + 3) & ~3)
#define d_ino d_fileno /* compatability */
@@ -28,15 +37,25 @@ struct direct {
* Definitions for library routines operating on directories.
*/
-typedef struct FAB DIR;
+typedef struct DIR
+{
+ struct direct dir;
+ char d_result[MAXNAMLEN + 1];
+#if defined (__ALPHA) || defined (__DECC)
+ struct FAB fab;
+#else
+ struct fabdef fab;
+#endif
+} DIR;
#ifndef NULL
#define NULL 0
#endif
+
extern DIR *opendir PARAMS (());
extern struct direct *readdir PARAMS ((DIR *dfd));
#define rewinddir(dirp) seekdir((dirp), (long)0)
extern int closedir PARAMS ((DIR *dfd));
extern char *vmsify PARAMS ((char *name, int type));
-/* EOF */
+#endif /* VMSDIR_H */
diff --git a/vmsfunctions.c b/vmsfunctions.c
index 4e0cb34..a36630e 100644
--- a/vmsfunctions.c
+++ b/vmsfunctions.c
@@ -1,7 +1,5 @@
/* vmsfunctions.c */
-#define KDEBUG 0
-
#include "make.h"
#include "debug.h"
@@ -21,37 +19,17 @@ DIR *
opendir (dspec)
char *dspec;
{
- static struct FAB *dfab;
- struct NAM *dnam;
- char *searchspec;
-
- dfab = (struct FAB *) xmalloc (sizeof (struct FAB));
- if (! dfab)
- {
- printf ("Error mallocing for FAB\n");
- return (NULL);
- }
+ struct DIR *dir = (struct DIR *)xmalloc (sizeof (struct DIR));
+ struct NAM *dnam = (struct NAM *)xmalloc (sizeof (struct NAM));
+ struct FAB *dfab = &dir->fab;
+ char *searchspec = (char *)xmalloc (MAXNAMLEN + 1);
- dnam = (struct NAM *) xmalloc (sizeof (struct NAM));
- if (! dnam)
- {
- printf ("Error mallocing for NAM\n");
- free (dfab);
- return (NULL);
- }
-
- searchspec = (char *) xmalloc (MAXNAMLEN + 1);
- if (! searchspec)
- {
- printf ("Error mallocing for searchspec\n");
- free (dfab);
- free (dnam);
- return (NULL);
- }
+ memset (dir, 0, sizeof *dir);
+ *dfab = cc$rms_fab;
+ *dnam = cc$rms_nam;
sprintf (searchspec, "%s*.*;", dspec);
- *dfab = cc$rms_fab;
dfab->fab$l_fna = searchspec;
dfab->fab$b_fns = strlen (searchspec);
dfab->fab$l_nam = dnam;
@@ -62,13 +40,13 @@ opendir (dspec)
if (! (sys$parse (dfab) & 1))
{
- free (dfab);
+ free (dir);
free (dnam);
free (searchspec);
return (NULL);
}
- return (dfab);
+ return dir;
}
#define uppercasify(str) \
@@ -82,65 +60,59 @@ opendir (dspec)
while (0)
struct direct *
-readdir (dfd)
- DIR * dfd;
+readdir (dir)
+ DIR * dir;
{
- static struct direct *dentry;
- static char resultspec[MAXNAMLEN + 1];
+ struct FAB *dfab = &dir->fab;
+ struct NAM *dnam = (struct NAM *)(dfab->fab$l_nam);
+ struct direct *dentry = &dir->dir;
int i;
- dentry = (struct direct *) xmalloc (sizeof (struct direct));
- if (! dentry)
- {
- printf ("Error mallocing for direct\n");
- return (NULL);
- }
+ memset (dentry, 0, sizeof *dentry);
- dfd->fab$l_nam->nam$l_rsa = resultspec;
- dfd->fab$l_nam->nam$b_rss = MAXNAMLEN;
+ dnam->nam$l_rsa = dir->d_result;
+ dnam->nam$b_rss = MAXNAMLEN;
- DB (DB_EXTRA, ("."));
+ if (debug_flag)
+ printf (".");
- if (!((i = sys$search (dfd)) & 1))
+ if (!((i = sys$search (dfab)) & 1))
{
- DB (DB_EXTRA, ("sys$search failed with %d\n", i));
- free (dentry);
+ if (debug_flag)
+ printf ("sys$search failed with %d\n", i);
return (NULL);
}
dentry->d_off = 0;
- if (dfd->fab$l_nam->nam$w_fid == 0)
+ if (dnam->nam$w_fid == 0)
dentry->d_fileno = 1;
else
- dentry->d_fileno = dfd->fab$l_nam->nam$w_fid[0]
- + dfd->fab$l_nam->nam$w_fid[1] << 16;
+ dentry->d_fileno = dnam->nam$w_fid[0] + (dnam->nam$w_fid[1] << 16);
+
dentry->d_reclen = sizeof (struct direct);
-#if 0
- if (!strcmp(dfd->fab$l_nam->nam$l_type, ".DIR"))
- dentry->d_namlen = dfd->fab$l_nam->nam$b_name;
- else
-#endif
- dentry->d_namlen = dfd->fab$l_nam->nam$b_name + dfd->fab$l_nam->nam$b_type;
- strncpy (dentry->d_name, dfd->fab$l_nam->nam$l_name, dentry->d_namlen);
+ dentry->d_namlen = dnam->nam$b_name + dnam->nam$b_type;
+ strncpy (dentry->d_name, dnam->nam$l_name, dentry->d_namlen);
dentry->d_name[dentry->d_namlen] = '\0';
uppercasify (dentry->d_name);
-#if 0
- uvUnFixRCSSeparator(dentry->d_name);
-#endif
return (dentry);
}
-closedir (dfd)
- DIR *dfd;
+int
+closedir (dir)
+ DIR *dir;
{
- if (dfd)
+ if (dir != NULL)
{
- if (dfd->fab$l_nam)
- free (dfd->fab$l_nam->nam$l_esa);
- free (dfd->fab$l_nam);
- free (dfd);
+ struct FAB *dfab = &dir->fab;
+ struct NAM *dnam = (struct NAM *)(dfab->fab$l_nam);
+ if (dnam != NULL)
+ free (dnam->nam$l_esa);
+ free (dnam);
+ free (dir);
}
+
+ return 0;
}
#endif /* compiled for OpenVMS prior to V7.x */
@@ -227,7 +199,7 @@ vms_stat (name, buf)
/* Initialize the FIB */
for (i = 0; i < 3; i++)
{
-#if __DECC
+#ifndef __VAXC
Fib.fib$w_fid[i] = Nam.nam$w_fid[i];
Fib.fib$w_did[i] = Nam.nam$w_did[i];
#else
@@ -275,3 +247,33 @@ cvt_time (tval)
return (str);
}
+
+
+int
+strcmpi (s1, s2)
+ const char *s1;
+ const char *s2;
+{
+ while (*s1 != '\0' && toupper(*s1) == toupper(*s2))
+ {
+ s1++;
+ s2++;
+ }
+
+ return toupper(*(unsigned char *) s1) - toupper(*(unsigned char *) s2);
+}
+
+
+int
+strcmpi (s1, s2)
+ const char *s1;
+ const char *s2;
+{
+ while (*s1 != '\0' && toupper(*s1) == toupper(*s2))
+ {
+ s1++;
+ s2++;
+ }
+
+ return toupper(*(unsigned char *) s1) - toupper(*(unsigned char *) s2);
+}
diff --git a/vmsify.c b/vmsify.c
index 350ce15..f7871bb 100644
--- a/vmsify.c
+++ b/vmsify.c
@@ -8,6 +8,7 @@
*/
+#include <stdio.h>
#include <string.h>
#include <ctype.h>
@@ -78,8 +79,8 @@ copyto (char **to, char **from, char upto, int as_dir)
}
else
{
- if (islower ((unsigned char)**from))
- **to = toupper ((unsigned char)**from);
+ if (isupper ((unsigned char)**from))
+ **to = tolower ((unsigned char)**from);
else
**to = **from;
}
@@ -127,6 +128,27 @@ trnlog (char *name)
return s;
}
+static char *
+showall (char *s)
+{
+ static char t[512];
+ char *pt;
+
+ pt = t;
+ if (strchr (s, '\\') == 0)
+ return s;
+ while (*s)
+ {
+ if (*s == '\\')
+ {
+ *pt++ = *s;
+ }
+ *pt++ = *s++;
+ }
+ return pt;
+}
+
+
enum namestate { N_START, N_DEVICE, N_OPEN, N_DOT, N_CLOSED, N_DONE };
/*
@@ -205,16 +227,39 @@ vmsify (name, type)
s = strpbrk (name, "$:");
if (s != 0)
{
+ char *s1;
+ char *s2;
+
+ if (type == 1)
+ {
+ s1 = strchr (s+1, '[');
+ s2 = strchr (s+1, ']');
+ }
+
if (*s == '$')
{
if (strchr (name, '/') == 0)
{
- return name;
+ if ((type == 1) && (s1 != 0) && (s2 == 0))
+ {
+ strcpy (vmsname, name);
+ strcat (vmsname, "]");
+ return vmsname;
+ }
+ else
+ return name;
}
}
else
{
- return name;
+ if ((type == 1) && (s1 != 0) && (s2 == 0))
+ {
+ strcpy (vmsname, name);
+ strcat (vmsname, "]");
+ return vmsname;
+ }
+ else
+ return name;
}
}
@@ -227,7 +272,15 @@ vmsify (name, type)
s1 = strchr (s+1, '[');
if (s1 == 0)
{
- return name; /* single [, keep unchanged */
+ if ((type == 1)
+ && (strchr (s+1, ']') == 0))
+ {
+ strcpy (vmsname, name);
+ strcat (vmsname, "]");
+ return vmsname;
+ }
+ else
+ return name; /* single [, keep unchanged */
}
s1--;
if (*s1 != ']')
@@ -403,7 +456,7 @@ vmsify (name, type)
{
if (*(s2-1) == '.') /* ends in '.]' */
{
- if (!strneq (fptr, "000000", 6))
+ if (strncmp (fptr, "000000", 6) != 0)
rooted = 0;
}
else
@@ -727,21 +780,48 @@ vmsify (name, type)
while (*fptr == '/');
}
{ /* got '..' or '../' */
- nstate = N_OPEN;
- *vptr++ = '[';
- while (count--)
- *vptr++ = '-';
+ char cwdbuf[MAXPATHLEN+1];
- if (*fptr == 0) /* had '..' or '../' */
+ s1 = getcwd(cwdbuf, MAXPATHLEN);
+ if (s1 == 0)
{
- *vptr++ = ']';
- state = -1;
+ return ""; /* FIXME, err getcwd */
}
- else /* had '../xxx' */
+ strcpy (vptr, s1);
+ s = strchr (vptr, ']');
+ if (s != 0)
{
- state = 9;
+ nstate = N_OPEN;
+ while (s > vptr)
+ {
+ s--;
+ if (*s == '[')
+ {
+ s++;
+ strcpy (s, "000000]");
+ state = -1;
+ break;
+ }
+ else if (*s == '.')
+ {
+ if (--count == 0)
+ {
+ if (*fptr == 0) /* had '..' or '../' */
+ {
+ *s++ = ']';
+ state = -1;
+ }
+ else /* had '../xxx' */
+ {
+ state = 9;
+ }
+ *s = 0;
+ break;
+ }
+ }
+ }
}
- *vptr = 0;
+ vptr += strlen (vptr);
}
break;
@@ -752,89 +832,38 @@ vmsify (name, type)
{
return name;
}
- fptr++;
+ while (*fptr == '/')
+ fptr++;
}
- if (*fptr)
- {
- state = 9;
-
- switch (type)
- {
- case 0:
- nstate = N_CLOSED;
- *vptr++ = '[';
- *vptr++ = ']';
- break;
-
- case 1:
- nstate = N_OPEN;
- *vptr++ = '[';
- break;
-
- case 2:
- nstate = N_CLOSED;
- break;
- }
- }
- else
- {
- if (type == 1)
- {
- *vptr++ = '[';
- *vptr++ = ']';
- state = -1;
- }
- else
- {
- char cwdbuf[MAXPATHLEN+1];
-
- s1 = getcwd(cwdbuf, MAXPATHLEN);
- if (s1 == 0)
- {
- return "foo"; /*FIXME, err getcwd */
- }
- strcpy (vptr, s1);
- vptr += strlen (vptr);
-
- if (type == 2)
- {
- s = vptr;
- while (s > vmsname)
- {
- if (*s == '.')
- {
- *s = ']';
- vptr--;
- break;
- }
-
- if (*s == '[')
- {
- int i;
- char *t = vptr - 2;
- while (t > s)
- {
- *(t+7) = *t;
- t--;
- }
- s++;
- for (i = 0; i < 6; i++)
- *s++ = '0';
- *s = ']';
- vptr += 6;
- break;
- }
- s--;
- }
-
- strcpy (vptr, ".dir");
- vptr += 4;
- }
+ {
+ char cwdbuf[MAXPATHLEN+1];
- state = -1;
- }
- }
+ s1 = getcwd(cwdbuf, MAXPATHLEN);
+ if (s1 == 0)
+ {
+ return ""; /*FIXME, err getcwd */
+ }
+ strcpy (vptr, s1);
+ if (*fptr == 0)
+ {
+ state = -1;
+ break;
+ }
+ else
+ {
+ s = strchr (vptr, ']');
+ if (s == 0)
+ {
+ state = -1;
+ break;
+ }
+ *s = 0;
+ nstate = N_OPEN;
+ vptr += strlen (vptr);
+ state = 9;
+ }
+ }
break;
}