* Merge VMS patches by Hartmut Becker.
authorPaul Smith <psmith@gnu.org>
Sat, 22 Jan 2000 05:43:03 +0000 (05:43 +0000)
committerPaul Smith <psmith@gnu.org>
Sat, 22 Jan 2000 05:43:03 +0000 (05:43 +0000)
20 files changed:
ChangeLog
NEWS
arscan.c
config.h-vms.template
default.c
dir.c
file.c
glob/glob.c
glob/glob.h
implicit.c
job.c
make.h
makefile.com
makefile.vms
readme.vms
rule.c
variable.c
vmsdir.h
vmsfunctions.c
vmsify.c

index 175081c..3e37cd0 100644 (file)
--- 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 (file)
--- 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.
 \f
 Version 3.78
 
index 6ff2715..2b90705 100644 (file)
--- 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]);
index 6488255..e2dd026 100644 (file)
@@ -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.  */
 
 
 /* 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 */
 /* #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
 /* #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 */
 /* #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
 /* #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
index 8ad37e1..e50813d 100644 (file)
--- 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 (file)
--- 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 */
 \f
 #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 (file)
--- 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;
index 65055fb..4bbf7bb 100644 (file)
@@ -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)
     {
index 7c2a67a..9f735fe 100644 (file)
@@ -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
index 4156402..c0ca4ed 100644 (file)
@@ -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 (file)
--- 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 */
 \f
-
 /* 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 */
 \f
 #if !defined(HAVE_DUP2) && !defined(_AMIGA)
 int
diff --git a/make.h b/make.h
index 8f1b057..18eb1c9 100644 (file)
--- 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)
index f180df2..5a0f884 100644 (file)
@@ -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)
index 9b8208a..9a780d8 100644 (file)
@@ -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) $< $@
index 43b4dd0..dacc394 100644 (file)
@@ -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.
+\f
 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 (file)
--- 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
index 8058a74..6d105b2 100644 (file)
@@ -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;
 }
 \f
@@ -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);
index 4cf1583..5903475 100644 (file)
--- 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 */
index 4e0cb34..a36630e 100644 (file)
@@ -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);
+}
index 350ce15..f7871bb 100644 (file)
--- 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;
        }