Tue Mar 19 20:21:34 1996 Roland McGrath <roland@charlie-brown.gnu.ai.mit.edu>
authorRoland McGrath <roland@redhat.com>
Wed, 20 Mar 1996 14:57:41 +0000 (14:57 +0000)
committerRoland McGrath <roland@redhat.com>
Wed, 20 Mar 1996 14:57:41 +0000 (14:57 +0000)
Merged VMS port from Klaus Kaempf <kkaempf@didymus.rmi.de>.
* make.h (PARAMS): New macro.
* config.h-vms: New file.
* makefile.com: New file.
* makefile.vms: New file.
* readme.vms: New file.
* vmsdir.h: New file.
* vmsfunctions.c: New file.
* vmsify.c: New file.
* file.h: Renamed to filedef.h to avoid conflict with VMS system hdr.
* ar.c: Added prototypes and changes for VMS.
* commands.c: Likewise.
* commands.h: Likewise.
* default.c: Likewise.
* dep.h: Likewise.
* dir.c: Likewise.
* expand.c: Likewise.
* file.c: Likewise.
* function.c: Likewise.
* implicit.c: Likewise.
* job.c: Likewise.
* job.h: Likewise.
* main.c: Likewise.
* make.h: Likewise.
* misc.c: Likewise.
* read.c: Likewise.
* remake.c: Likewise.
* remote-stub.c: Likewise.
* rule.c: Likewise.
* rule.h: Likewise.
* variable.c: Likewise.
* variable.h: Likewise.
* vpath.c: Likewise.
* compatMakefile (srcs): Rename file.h to filedef.h.

32 files changed:
ar.c
commands.c
commands.h
compatMakefile
config.h-vms.template [new file with mode: 0644]
default.c
dep.h
dir.c
expand.c
file.c
filedef.h [new file with mode: 0644]
function.c
implicit.c
job.c
job.h
main.c
make.h
makefile.com [new file with mode: 0644]
makefile.vms [new file with mode: 0644]
misc.c
read.c
readme.vms [new file with mode: 0644]
remake.c
remote-stub.c
rule.c
rule.h
variable.c
variable.h
vmsdir.h [new file with mode: 0644]
vmsfunctions.c [new file with mode: 0644]
vmsify.c [new file with mode: 0644]
vpath.c

diff --git a/ar.c b/ar.c
index 63fcd34..117e11b 100644 (file)
--- a/ar.c
+++ b/ar.c
@@ -20,14 +20,14 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 #ifndef        NO_ARCHIVES
 
-#include "file.h"
+#include "filedef.h"
 #include "dep.h"
 #include <fnmatch.h>
 
 /* Defined in arscan.c.  */
-extern long int ar_scan ();
-extern int ar_member_touch ();
-extern int ar_name_equal ();
+extern long int ar_scan PARAMS ((char *archive, long int (*function) (), long int arg));
+extern int ar_member_touch PARAMS ((char *arname, char *memname));
+extern int ar_name_equal PARAMS ((char *name, char *mem, int truncated));
 
 
 /* Return nonzero if NAME is an archive-member reference, zero if not.
@@ -67,8 +67,113 @@ ar_parse_name (name, arname_p, memname_p)
   if (memname_p != 0)
     *memname_p = savestring (p + 1, end - (p + 1));
 }  
+#ifdef VMS
+#include <lbrdef.h>
+#include <mhddef.h>
+#include <credef.h>
+#include <descrip.h>
+#include <ctype.h>
+#if __DECC
+#include <lbr$routines.h>
+#endif
+
+#define uppercasify(str) {char *str1; for (str1 = str; *str1; str1++) *str1 = _toupper(*str1);}
+
+#define LBR$_KEYNOTFND 2527330 /* This isn't in any .h file anywhere so I got it from a MACRO library */
+
+time_t
+ar_member_date (name)
+     char *name;
+{
+  static char *arname;
+  static char *memname;
+  char *p,*q;
+  long int val;
+  static struct {
+    struct mhddef mhd;
+    struct credef cre;
+    char garbage[256];
+  } buf;
+  int func=LBR$C_READ,
+      type=LBR$C_TYP_OBJ,
+      rfa[2],
+      lidx,
+      status;
+  $DESCRIPTOR(bufdesc,(char *)&buf);
+  $DESCRIPTOR(libdesc,arname);
+  $DESCRIPTOR(moddesc,memname);
+
+  /* This "file" is an archive member.  */
+  p = index (name, '(');
+  arname = savestring (name, p - name);
+  val = strlen (p) - 2;
+/*
+  if (val > 15)
+    val = 15;
+*/
+  memname = savestring (p + 1, val);
+#ifdef OLDWAY
+  p = rindex (memname, ')');
+  if (p != 0) {
+      q = rindex(p,'.');
+      if (q)
+       *q = '\0'; /* to get rid of extension */
+  }
+#endif
+
+  q = rindex(memname,'.');
+  if (q)
+    *q = '\0'; /* to get rid of extension */
+
+  uppercasify(memname);
+
+  /* Make sure we know the modtime of the archive itself because
+     we are likely to be called just before commands to remake a
+     member are run, and they will change the archive itself.  */
+  (void) f_mtime (enter_file (arname));
+
+  libdesc.dsc$a_pointer = arname;
+  libdesc.dsc$w_length = strlen(arname);
+  moddesc.dsc$a_pointer = memname;
+  moddesc.dsc$w_length = strlen(memname);
+
+  if (!((status = lbr$ini_control(&lidx,&func,&type,0)) & 1)) {
+    printf("Error in lbr$ini_control, %d\n",status);
+    return(-1);
+  }
+
+  if (!((status = lbr$open(&lidx,&libdesc,0,0,0,0,0)) & 1)) {
+    printf("Error opening library %s to lookup member %s, %d\n",arname, memname ,status);
+    return(-1);
+  }
+
+  if (!((status = lbr$lookup_key(&lidx,&moddesc,rfa)) & 1)) {
+      if (status != LBR$_KEYNOTFND)
+       printf("Error looking up module %s in library %s, %d\n",memname, arname ,status);
+      lbr$close(&lidx);
+      return(-1);
+  }
+
+  if (!((status = lbr$set_module(&lidx,rfa,&bufdesc,&bufdesc,0)) & 1)) {
+    printf("Error getting module info, %d\n",status);
+    lbr$close(&lidx);
+    return(-1);
+  }
+
+  lbr$close(&lidx);
+
+  val = SHELL$FIX_TIME(&buf.mhd.mhd$l_datim);
+
+  free (arname);
+  free (memname);
+  return (val <= 0 ? (time_t) -1 : (time_t) val);
+}
+
+#else
 \f
-static long int ar_member_date_1 ();
+static long int ar_member_date_1 PARAMS ((int desc, char *mem, int truncated, long int hdrpos,
+       long int datapos, long int size, long int date, int uid, int gid, int mode, char *name));
 
 /* Return the modtime of NAME.  */
 
@@ -127,9 +232,19 @@ ar_member_date_1 (desc, mem, truncated,
 {
   return ar_name_equal (name, mem, truncated) ? date : 0;
 }
+#endif /* !VMS */
 \f
 /* Set the archive-member NAME's modtime to now.  */
 
+#ifdef VMS
+int
+ar_touch (name)  
+     char *name;
+{
+  error ("touch archive member is not available on VMS");
+  return -1;
+}
+#else
 int
 ar_touch (name)
      char *name;
@@ -182,6 +297,7 @@ ar_touch (name)
 
   return val;
 }
+#endif /* !VMS */
 \f
 /* State of an `ar_glob' run, passed to `ar_glob_match'.  */
 
index 97ccbb1..1a4372f 100644 (file)
@@ -18,12 +18,12 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 #include "make.h"
 #include "dep.h"
-#include "commands.h"
-#include "file.h"
+#include "filedef.h"
 #include "variable.h"
 #include "job.h"
+#include "commands.h"
 
-extern int remote_kill ();
+extern int remote_kill PARAMS ((int id, int sig));
 
 #ifndef        HAVE_UNISTD_H
 extern int getpid ();
@@ -154,8 +154,11 @@ set_file_variables (file)
 
        bcopy (c, cp, len);
        cp += len;
+#if VMS
+        *cp++ = ',';
+#else
        *cp++ = ' ';
-
+#endif
        if (! d->changed)
          qmark_len -= len + 1; /* Don't space in $? for this one.  */
       }
@@ -193,13 +196,20 @@ set_file_variables (file)
 
        bcopy (c, cp, len);
        cp += len;
+#if VMS
+       *cp++ = ',';
+#else
        *cp++ = ' ';
-
+#endif
        if (d->changed)
          {
            bcopy (c, qp, len);
            qp += len;
+#if VMS
+           *qp++ = ',';
+#else
            *qp++ = ' ';
+#endif
          }
       }
 
@@ -413,7 +423,7 @@ fatal_error_signal (sig)
   if (sig == SIGQUIT)
     /* We don't want to send ourselves SIGQUIT, because it will
        cause a core dump.  Just exit instead.  */
-    exit (1);
+    exit (EXIT_FAILURE);
 
   /* Signal the same code; this time it will really be fatal.  The signal
      will be unblocked when we return and arrive then to kill us.  */
index 31de16a..c55fa67 100644 (file)
@@ -36,7 +36,7 @@ struct commands
 #define        COMMANDS_SILENT         2 /* Silent: @.  */
 #define        COMMANDS_NOERROR        4 /* No errors: -.  */
 
-extern void execute_file_commands ();
-extern void print_commands ();
-extern void delete_child_targets ();
-extern void chop_commands ();
+extern void execute_file_commands PARAMS ((struct file *file));
+extern void print_commands PARAMS ((struct commands *cmds));
+extern void delete_child_targets PARAMS ((struct child *child));
+extern void chop_commands PARAMS ((struct commands *cmds));
index dd70ded..0755b0b 100644 (file)
@@ -122,7 +122,7 @@ srcs = $(srcdir)/commands.c $(srcdir)/job.c $(srcdir)/dir.c         \
        $(srcdir)/ar.c $(srcdir)/arscan.c                               \
        $(srcdir)/signame.c $(srcdir)/signame.h                         \
        $(srcdir)/getopt.c $(srcdir)/getopt1.c $(srcdir)/getopt.h       \
-       $(srcdir)/commands.h $(srcdir)/dep.h $(srcdir)/file.h           \
+       $(srcdir)/commands.h $(srcdir)/dep.h $(srcdir)/filedef.h                \
        $(srcdir)/job.h $(srcdir)/make.h $(srcdir)/rule.h               \
        $(srcdir)/variable.h $(ALLOCA_SRC) $(srcdir)/config.h.in
 
diff --git a/config.h-vms.template b/config.h-vms.template
new file mode 100644 (file)
index 0000000..7211919
--- /dev/null
@@ -0,0 +1,292 @@
+/* config.h-vms. Generated by hand by Klaus Kämpf <kkaempf@didymus.rmi.de> */
+/* config.h.  Generated automatically by configure.  */
+/* config.h.in.  Generated automatically from configure.in by autoheader.  */
+
+/* Define if on AIX 3.
+   System headers sometimes define this.
+   We just want to avoid a redefinition error message.  */
+#ifndef _ALL_SOURCE
+/* #undef _ALL_SOURCE */
+#endif
+
+/* Define if using alloca.c.  */
+/* #undef C_ALLOCA */
+
+/* Define to empty if the keyword does not work.  */
+/* #undef const */
+
+/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems.
+   This function is required for alloca.c support on those systems.  */
+/* #undef CRAY_STACKSEG_END */
+
+/* Define for DGUX with <sys/dg_sys_info.h>.  */
+/* #undef DGUX */
+
+/* Define if the `getloadavg' function needs to be run setuid or setgid.  */
+/* #undef GETLOADAVG_PRIVILEGED 1 */
+
+/* Define to `int' if <sys/types.h> doesn't define.  */
+/* #undef gid_t */
+
+/* Define if you have alloca, as a function or macro.  */
+#define HAVE_ALLOCA 1
+
+/* Define if you have <alloca.h> and it should be used (not on Ultrix).  */
+/* #undef HAVE_ALLOCA_H 1 */
+
+/* Define if you don't have vprintf but do have _doprnt.  */
+/* #undef HAVE_DOPRNT */
+
+/* Define if your system has its own `getloadavg' function.  */
+/* #undef HAVE_GETLOADAVG */
+
+/* Define if you have the getmntent function.  */
+/* #undef HAVE_GETMNTENT */
+
+/* Define if the `long double' type works.  */
+/* #undef HAVE_LONG_DOUBLE */
+
+/* Define if you support file names longer than 14 characters.  */
+#define HAVE_LONG_FILE_NAMES 1
+
+/* Define if you have a working `mmap' system call.  */
+/* #undef HAVE_MMAP */
+
+/* Define if system calls automatically restart after interruption
+   by a signal.  */
+/* #undef HAVE_RESTARTABLE_SYSCALLS */
+
+/* Define if your struct stat has st_blksize.  */
+/* #undef HAVE_ST_BLKSIZE */
+
+/* Define if your struct stat has st_blocks.  */
+/* #undef HAVE_ST_BLOCKS */
+
+/* Define if you have the strcoll function and it is properly defined.  */
+/* #undef HAVE_STRCOLL 1 */
+
+/* Define if your struct stat has st_rdev.  */
+/* #undef HAVE_ST_RDEV  */
+
+/* Define if you have the strftime function.  */
+/* #undef HAVE_STRFTIME */
+
+/* Define if you have <sys/wait.h> that is POSIX.1 compatible.  */
+/* #undef HAVE_SYS_WAIT_H 1 */
+
+/* Define if your struct tm has tm_zone.  */
+/* #undef HAVE_TM_ZONE */
+
+/* Define if you don't have tm_zone but do have the external array
+   tzname.  */
+/* #undef HAVE_TZNAME */
+
+/* Define if you have <unistd.h>.  */
+#ifdef __DECC
+#define HAVE_UNISTD_H 1
+#endif
+
+/* Define if utime(file, NULL) sets file's timestamp to the present.  */
+/* #undef HAVE_UTIME_NULL */
+
+/* Define if you have <vfork.h>.  */
+/* #undef HAVE_VFORK_H 1 */
+
+/* Define if you have the vprintf function.  */
+#define HAVE_VPRINTF 1
+
+/* Define if you have the wait3 system call.  */
+/* #undef HAVE_WAIT3 1 */
+
+/* Define if on MINIX.  */
+/* #undef _MINIX */
+
+/* Define if your struct nlist has an n_un member.  */
+/* #undef NLIST_NAME_UNION */
+
+/* Define if you have <nlist.h>.  */
+/* #undef NLIST_STRUCT 1 */
+
+/* Define if your C compiler doesn't accept -c and -o together.  */
+/* #undef NO_MINUS_C_MINUS_O */
+
+/* Define to `int' if <sys/types.h> doesn't define.  */
+#define pid_t int
+
+/* Define if the system does not provide POSIX.1 features except
+   with this defined.  */
+/* #undef _POSIX_1_SOURCE */
+
+/* Define if you need to in order for stat and other things to work.  */
+/* #undef _POSIX_SOURCE */
+
+/* Define as the return type of signal handlers (int or void).  */
+#define RETSIGTYPE void
+
+/* Define if the setvbuf function takes the buffering type as its second
+   argument and the buffer pointer as the third, as on System V
+   before release 3.  */
+/* #undef SETVBUF_REVERSED 1 */
+
+/* If using the C implementation of alloca, define if you know the
+   direction of stack growth for your system; otherwise it will be
+   automatically deduced at run-time.
+       STACK_DIRECTION > 0 => grows toward higher addresses
+       STACK_DIRECTION < 0 => grows toward lower addresses
+       STACK_DIRECTION = 0 => direction of growth unknown
+ */
+/* #undef STACK_DIRECTION */
+
+/* Define if the `S_IS*' macros in <sys/stat.h> do not work properly.  */
+/* #undef STAT_MACROS_BROKEN */
+
+/* Define if you have the ANSI C header files.  */
+/* #undef STDC_HEADERS */
+
+/* Define on System V Release 4.  */
+/* #undef SVR4 */
+
+/* Define if `sys_siglist' is declared by <signal.h>.  */
+/* #undef SYS_SIGLIST_DECLARED */
+
+/* Define to `int' if <sys/types.h> doesn't define.  */
+#define uid_t int
+
+/* Define for Encore UMAX.  */
+/* #undef UMAX */
+
+/* Define for Encore UMAX 4.3 that has <inq_status/cpustats.h>
+   instead of <sys/cpustats.h>.  */
+/* #undef UMAX4_3 */
+
+/* Define vfork as fork if vfork does not work.  */
+/* #undef vfork */
+
+/* Define to the name of the SCCS `get' command.  */
+/* #undef SCCS_GET "/usr/sccs/get" */
+
+/* Define this if the SCCS `get' command understands the `-G<file>' option.  */
+/* #undef SCCS_GET_MINUS_G 1 */
+
+/* Define this if the C library defines the variable `sys_siglist'.  */
+/* #undefine HAVE_SYS_SIGLIST 1 */
+
+/* Define this if the C library defines the variable `_sys_siglist'.  */
+/* #undef HAVE__SYS_SIGLIST */
+
+/* Define this if you have the `union wait' type in <sys/wait.h>.  */
+/* #undef HAVE_UNION_WAIT */
+
+/* Define this if the POSIX.1 call `sysconf (_SC_OPEN_MAX)' works properly.  */
+/* #undef HAVE_SYSCONF_OPEN_MAX */
+
+/* Define if you have the dup2 function.  */
+#define HAVE_DUP2 1
+
+/* Define if you have the getcwd function.  */
+#define HAVE_GETCWD 1
+
+/* Define if you have the getdtablesize function.  */
+/* #undef HAVE_GETDTABLESIZE 1 */
+
+/* Define if you have the getgroups function.  */
+/* #undef HAVE_GETGROUPS 1 */
+
+/* Define if you have the mktemp function.  */
+#define HAVE_MKTEMP 1
+
+/* Define if you have the psignal function.  */
+/* #undef HAVE_PSIGNAL 1 */
+
+/* Define if you have the setegid function.  */
+/* #undef HAVE_SETEGID 1 */
+
+/* Define if you have the seteuid function.  */
+/* #undef HAVE_SETEUID 1 */
+
+/* Define if you have the setlinebuf function.  */
+/* #undef HAVE_SETLINEBUF 1 */
+
+/* Define if you have the setregid function.  */
+/* #undefine HAVE_SETREGID 1 */
+
+/* Define if you have the setreuid function.  */
+/* #define HAVE_SETREUID 1 */
+
+/* Define if you have the sigsetmask function.  */
+#define HAVE_SIGSETMASK 1
+
+/* Define if you have the strerror function.  */
+#define HAVE_STRERROR 1
+
+/* Define if you have the strsignal function.  */
+/* #undef HAVE_STRSIGNAL */
+
+/* Define if you have the wait3 function.  */
+/* #define HAVE_WAIT3 1 */
+
+/* Define if you have the waitpid function.  */
+/* #undef HAVE_WAITPID 1 */
+
+/* Define if you have the <dirent.h> header file.  */
+/* #unddef HAVE_DIRENT_H 1 */
+
+/* Define if you have the <fcntl.h> header file.  */
+#ifdef __DECC
+#define HAVE_FCNTL_H 1
+#endif
+
+/* Define if you have the <limits.h> header file.  */
+#define HAVE_LIMITS_H 1
+
+/* Define if you have the <mach/mach.h> header file.  */
+/* #undef HAVE_MACH_MACH_H */
+
+/* Define if you have the <memory.h> header file.  */
+/* #undef HAVE_MEMORY_H 1 */
+
+/* Define if you have the <ndir.h> header file.  */
+/* #undef HAVE_NDIR_H */
+
+/* Define if you have the <string.h> header file.  */
+#define HAVE_STRING_H 1
+
+/* Define if you have the <pwd.h> header file.  */
+/* #undef HAVE_PWD_H */
+
+/* Define if you have the <sys/dir.h> header file.  */
+/* #undef HAVE_SYS_DIR_H */
+
+/* Define if you have the <sys/ndir.h> header file.  */
+/* #undef HAVE_SYS_NDIR_H */
+
+/* Define if you have the <sys/param.h> header file.  */
+/* #undef HAVE_SYS_PARAM_H 1 */
+
+/* Define if you have the <sys/timeb.h> header file.  */
+#define HAVE_SYS_TIMEB_H 1
+
+/* Define if you have the <sys/wait.h> header file.  */
+/* #undef HAVE_SYS_WAIT_H 1 */
+
+/* Define if you have the dgc library (-ldgc).  */
+/* #undef HAVE_LIBDGC */
+
+/* Define if you have the sun library (-lsun).  */
+/* #undef HAVE_LIBSUN */
+
+/* VMS specific */
+
+#define HAVE_VMSDIR_H 1
+#define HAVE_STDLIB_H 1
+#define INCLUDEDIR "sys$sysroot:[syslib]"
+#define LIBDIR "sys$sysroot:[syslib]"
+
+#if defined (__cplusplus) || (defined (__STDC__) && __STDC__)
+#undef  PARAMS
+#define PARAMS(protos)  protos
+#else /* Not C++ or ANSI C.  */
+#undef  PARAMS
+#define PARAMS(protos)  ()   
+#endif /* C++ or ANSI C.  */
+
index 7c487d1..5f5d2b5 100644 (file)
--- a/default.c
+++ b/default.c
@@ -19,7 +19,8 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "make.h"
 #include "rule.h"
 #include "dep.h"
-#include "file.h"
+#include "filedef.h"
+#include "job.h"
 #include "commands.h"
 #include "variable.h"
 
@@ -35,9 +36,15 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
    a `.c' or `.p' or ... file rather than from a .s file.  */
 
 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 \
+.w .ch .cweb .web .com .sh .elc .el";
+#else
   = ".out .a .ln .o .c .cc .C .p .f .F .r .y .l .s .S \
 .mod .sym .def .h .info .dvi .tex .texinfo .texi .txinfo \
 .w .ch .web .sh .elc .el";
+#endif
 
 static struct pspec default_pattern_rules[] =
   {
@@ -47,9 +54,13 @@ static struct pspec default_pattern_rules[] =
     /* The X.out rules are only in BSD's default set because
        BSD Make has no null-suffix rules, so `foo.out' and
        `foo' are the same thing.  */
+#ifdef VMS
+    { "%.exe", "%",
+        "copy $< $@" },
+#else
     { "%.out", "%",
        "@rm -f $@ \n cp $< $@" },
-
+#endif
     /* Syntax is "ctangle foo.w foo.ch foo.c".  */
     { "%.c", "%.w %.ch",
        "$(CTANGLE) $^ $@" },
@@ -61,6 +72,20 @@ static struct pspec default_pattern_rules[] =
 
 static struct pspec default_terminal_rules[] =
   {
+#ifdef VMS
+    /* RCS.  */
+    { "%", "%$$5lv", /* Multinet style */
+        "if f$$search($@) .nes. \"\" then +$(CHECKOUT,v)" },
+    { "%", "[.$$rcs]%$$5lv", /* Multinet style */
+        "if f$$search($@) .nes. \"\" then +$(CHECKOUT,v)" },
+    { "%", "%_v", /* Normal style */
+        "if f$$search($@) .nes. \"\" then +$(CHECKOUT,v)" },
+    { "%", "[.rcs]%_v", /* Normal style */
+        "if f$$search($@) .nes. \"\" then +$(CHECKOUT,v)" },
+
+    /* SCCS.  */
+       /* ain't no SCCS on vms */
+#else
     /* RCS.  */
     { "%", "%,v",
        "$(CHECKOUT,v)" },
@@ -72,12 +97,53 @@ static struct pspec default_terminal_rules[] =
        "$(GET) $(GFLAGS) $(SCCS_OUTPUT_OPTION) $<" },
     { "%", "SCCS/s.%",
        "$(GET) $(GFLAGS) $(SCCS_OUTPUT_OPTION) $<" },
-
+#endif /* !VMS */
     { 0, 0, 0 }
   };
 
 static char *default_suffix_rules[] =
   {
+#ifdef VMS
+    ".obj.exe",
+    "$(LINK.obj) $^ $(LOADLIBES) $(LDLIBS) /exe=$@",
+    ".mar.exe",
+    "$(LINK.mar) $^ $(LOADLIBES) $(LDLIBS) /exe=$@",
+    ".c.exe",
+    "$(COMPILE.c) $^ \n $(LINK.obj) $(subst .c,.obj,$^) $(LOADLIBES) $(LDLIBS) /exe=$@",
+    ".cc.exe",
+    "$(COMPILE.cc) $^ \n $(LINK.obj) $(subst .cc,.obj,$^) $(LOADLIBES) $(LDLIBS) /exe=$@",
+    ".for.exe",
+    "$(COMPILE.for) $^ \n $(LINK.obj) $(subst .for,.obj,$^) $(LOADLIBES) $(LDLIBS) /exe=$@",
+    ".pas.exe",
+    "$(COMPILE.pas) $^ \n $(LINK.obj) $(subst .pas,.obj,$^) $(LOADLIBES) $(LDLIBS) /exe=$@",
+
+    ".com",
+    "copy $< >$@",
+
+    ".mar.obj",
+    "$(COMPILE.mar) /obj=$@ $<",
+    ".c.obj",
+    "$(COMPILE.c) /obj=$@ $<",
+    ".cc.obj",
+    "$(COMPILE.cc) /obj=$@ $<",
+    ".for.obj",
+    "$(COMPILE.for) /obj=$@ $<",
+    ".pas.obj",
+    "$(COMPILE.pas) /obj=$@ $<",
+
+    ".y.c",
+    "$(YACC.y) $< \n rename y_tab.c $@",
+    ".l.c",
+    "$(LEX.l) $< \n rename lexyy.c $@",
+
+    ".texinfo.info",
+    "$(MAKEINFO) $<",
+
+    ".tex.dvi",
+    "$(TEX) $<",
+
+#else /* ! VMS */
+
     ".o",
     "$(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o $@",
     ".s",
@@ -195,11 +261,52 @@ static char *default_suffix_rules[] =
     ".web.tex",
     "$(WEAVE) $<",
 
+#endif /* !VMS */
+
     0, 0,
   };
 
 static char *default_variables[] =
   {
+#ifdef VMS
+    "AR", "library/obj",
+    "ARFLAGS", "/replace",
+    "AS", "macro",
+    "CC", "cc",
+    "C++", "gcc/plus",
+    "CXX", "gcc/plus",
+    "CO", "co",
+    "CPP", "$(CC) /preprocess_only",
+    "FC", "fortran",
+    /* System V uses these, so explicit rules using them should work.
+       However, there is no way to make implicit rules use them and FC.  */
+    "F77", "$(FC)",
+    "F77FLAGS", "$(FFLAGS)",
+    "LD", "link",
+    "LEX", "lex",
+    "PC", "pascal",
+    "YACC", "yacc",    /* Or "bison -y"  */
+    "MAKEINFO", "makeinfo",
+    "TEX", "tex",
+    "TEXINDEX", "texindex",
+
+    "RM", "delete/nolog",
+
+    "LINK.obj", "$(LD) $(LDFLAGS)",
+    "COMPILE.c", "$(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH)",
+    "COMPILE.cc", "$(C++) $(C++FLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c",
+    "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)",
+    "LINT.c", "$(LINT) $(LINTFLAGS) $(CPPFLAGS) $(TARGET_ARCH)",
+
+    "MV", "rename/new_version",
+    "CP", "copy",
+
+#else /* !VMS */
+
     "AR", "ar",
     "ARFLAGS", "rv",
     "AS", "as",
@@ -310,6 +417,7 @@ static char *default_variables[] =
     "SCCS_OUTPUT_OPTION", "-G$@",
 #endif
 
+#endif /* !VMS */
     0, 0
   };
 \f
diff --git a/dep.h b/dep.h
index 244cde2..550c68a 100644 (file)
--- a/dep.h
+++ b/dep.h
@@ -40,11 +40,16 @@ struct nameseq
   };
 
 
-extern struct nameseq *multi_glob (), *parse_file_seq ();
-extern char *tilde_expand ();
+extern struct nameseq *multi_glob PARAMS ((struct nameseq *chain, unsigned int size));
+#ifdef VMS
+extern struct nameseq *parse_file_seq ();
+#else
+extern struct nameseq *parse_file_seq PARAMS ((char **stringp, char stopchar, unsigned int size, int strip));
+#endif
+extern char *tilde_expand PARAMS ((char *name));
 
 #ifndef NO_ARCHIVES
-extern struct nameseq *ar_glob ();
+extern struct nameseq *ar_glob PARAMS ((char *arname, char *member_pattern, unsigned int size));
 #endif
 
 #ifndef        iAPX286
@@ -54,7 +59,7 @@ extern struct nameseq *ar_glob ();
 extern char *dep_name ();
 #endif
 
-extern struct dep *read_all_makefiles ();
+extern struct dep *read_all_makefiles PARAMS ((char **makefiles));
 
 /* Flag bits for the second argument to `read_makefile'.
    These flags are saved in the `changed' field of each
diff --git a/dir.c b/dir.c
index ba2acc5..969f52a 100644 (file)
--- a/dir.c
+++ b/dir.c
@@ -33,6 +33,9 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 # ifdef HAVE_NDIR_H
 #  include <ndir.h>
 # endif
+# ifdef HAVE_VMSDIR_H
+#  include "vmsdir.h"
+# endif /* HAVE_VMSDIR_H */
 #endif
 
 /* In GNU systems, <dirent.h> defines this macro for us.  */
@@ -92,7 +95,63 @@ dosify (filename)
   *df = 0;
   return dos_filename;
 }
-#endif
+#endif /* __MSDOS__ */
+
+#ifdef VMS
+
+static int
+vms_hash (name)
+    char *name;
+{
+  int h = 0;
+  int g;
+
+  while (*name)
+    {
+      h = (h << 4) + *name++;
+      g = h & 0xf0000000;
+      if (g)
+       {
+         h = h ^ (g >> 24);
+         h = h ^ g;
+       }
+    }
+  return h;
+}
+
+/* fake stat entry for a directory */
+static int
+vmsstat_dir (name, st)
+    char *name;
+    struct stat *st;
+{
+  char *s;
+  int h;
+  DIR *dir;
+
+  dir = opendir (name);
+  if (dir == 0)
+    return -1;
+  closedir (dir);
+  s = strchr (name, ':');      /* find device */
+  if (s)
+    {
+      *s++ = 0;
+      st->st_dev = (char *)vms_hash (name);
+    }
+  else
+    {
+      st->st_dev = 0;
+      s = name;
+    }
+  h = vms_hash (s);
+  st->st_ino[0] = h & 0xff;
+  st->st_ino[1] = h & 0xff00;
+  st->st_ino[2] = h >> 16;
+
+  return 0;
+}
+#endif /* VMS */
 \f
 /* Hash table of directories.  */
 
@@ -104,8 +163,12 @@ struct directory_contents
   {
     struct directory_contents *next;
 
-    int dev, ino;              /* Device and inode numbers of this dir.  */
-
+    dev_t dev;                 /* Device and inode numbers of this dir.  */
+#ifdef VMS
+    ino_t ino[3];
+#else
+    ino_t ino;
+#endif
     struct dirfile **files;    /* Files in this directory.  */
     DIR *dirstream;            /* Stream reading this directory.  */
   };
@@ -149,7 +212,8 @@ struct dirfile
 #define DIRFILE_BUCKETS 107
 #endif
 \f
-static int dir_contents_file_exists_p ();
+static int dir_contents_file_exists_p PARAMS ((struct directory_contents *dir, char *filename));
+static struct directory *find_directory PARAMS ((char *name));
 
 /* Find the directory named NAME and return its `struct directory'.  */
 
@@ -160,6 +224,12 @@ find_directory (name)
   register unsigned int hash = 0;
   register char *p;
   register struct directory *dir;
+#ifdef VMS
+  if ((*name == '.') && (*(name+1) == 0))
+    name = "[]";
+  else
+    name = vmsify (name,1);
+#endif
 
   for (p = name; *p != '\0'; ++p)
     HASH (hash, *p);
@@ -183,21 +253,41 @@ find_directory (name)
       /* The directory is not in the name hash table.
         Find its device and inode numbers, and look it up by them.  */
 
+#ifdef VMS
+      if (vmsstat_dir (name, &st) < 0)
+#else
       if (stat (name, &st) < 0)
+#endif
+       {
        /* Couldn't stat the directory.  Mark this by
           setting the `contents' member to a nil pointer.  */
-       dir->contents = 0;
+         dir->contents = 0;
+       }
       else
        {
          /* Search the contents hash table; device and inode are the key.  */
 
          struct directory_contents *dc;
 
+#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
          hash %= DIRECTORY_BUCKETS;
 
          for (dc = directories_contents[hash]; dc != 0; dc = dc->next)
-           if (dc->dev == st.st_dev && dc->ino == st.st_ino)
+           if (dc->dev == st.st_dev
+#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
              break;
 
          if (dc == 0)
@@ -209,15 +299,23 @@ find_directory (name)
 
              /* Enter it in the contents hash table.  */
              dc->dev = st.st_dev;
+#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->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;
+                 dc->files = 0;
+               }
              else
                {
                  /* Allocate an array of buckets for files and zero it.  */
@@ -257,19 +355,26 @@ dir_contents_file_exists_p (dir, filename)
   register struct dirent *d;
 
   if (dir == 0 || dir->files == 0)
+    {
     /* The directory could not be stat'd or opened.  */
-    return 0;
-
+      return 0;
+    }
 #ifdef __MSDOS__
   filename = dosify (filename);
 #endif
 
+#ifdef VMS
+  filename = vmsify (filename,0);
+#endif
+
   hash = 0;
   if (filename != 0)
     {
       if (*filename == '\0')
+       {
        /* Checking if the directory exists.  */
-       return 1;
+         return 1;
+       }
 
       for (p = filename; *p != '\0'; ++p)
        HASH (hash, *p);
@@ -278,16 +383,22 @@ dir_contents_file_exists_p (dir, filename)
       /* Search the list of hashed files.  */
 
       for (df = dir->files[hash]; df != 0; df = df->next)
-       if (streq (df->name, filename))
-         return !df->impossible;
+       {
+         if (streq (df->name, filename))
+           {
+             return !df->impossible;
+           }
+       }
     }
 
   /* The file was not found in the hashed list.
      Try to read the directory further.  */
 
   if (dir->dirstream == 0)
+    {
     /* The directory has been all read in.  */
-    return 0;
+      return 0;
+    }
 
   while ((d = readdir (dir->dirstream)) != 0)
     {
@@ -309,11 +420,12 @@ dir_contents_file_exists_p (dir, filename)
       dir->files[newhash] = df;
       df->name = savestring (d->d_name, len);
       df->impossible = 0;
-
       /* Check if the name matches the one we're searching for.  */
       if (filename != 0
          && newhash == hash && streq (d->d_name, filename))
-       return 1;
+       {
+         return 1;
+       }
     }
 
   /* If the directory has been completely read in,
@@ -324,7 +436,6 @@ dir_contents_file_exists_p (dir, filename)
       closedir (dir->dirstream);
       dir->dirstream = 0;
     }
-
   return 0;
 }
 
@@ -355,9 +466,16 @@ file_exists_p (name)
     return ar_member_date (name) != (time_t) -1;
 #endif
 
+#ifdef VMS
+  dirend = rindex (name, ']');
+  dirend++;
+  if (dirend == (char *)1)
+    return dir_file_exists_p ("[]", name);
+#else
   dirend = rindex (name, '/');
   if (dirend == 0)
     return dir_file_exists_p (".", name);
+#endif
 
   dirname = (char *) alloca (dirend - name + 1);
   bcopy (name, dirname, dirend - name);
@@ -379,9 +497,16 @@ file_impossible (filename)
   register struct directory *dir;
   register struct dirfile *new;
 
+#ifdef VMS
+  dirend = rindex (p, ']');
+  dirend++;
+  if (dirend == (char *)1)
+    dir = find_directory ("[]");
+#else
   dirend = rindex (p, '/');
   if (dirend == 0)
     dir = find_directory (".");
+#endif
   else
     {
       char *dirname = (char *) alloca (dirend - p + 1);
@@ -401,7 +526,13 @@ file_impossible (filename)
         structure for it, but leave it out of the contents hash table.  */
       dir->contents = (struct directory_contents *)
        xmalloc (sizeof (struct directory_contents));
+#ifdef VMS
+      dir->contents->dev = 0;
+      dir->contents->ino[0] = dir->contents->ino[1] =
+       dir->contents->ino[2] = 0;
+#else
       dir->contents->dev = dir->contents->ino = 0;
+#endif
       dir->contents->files = 0;
       dir->contents->dirstream = 0;
     }
@@ -436,9 +567,15 @@ file_impossible_p (filename)
   register struct directory_contents *dir;
   register struct dirfile *next;
 
+#ifdef VMS
+  dirend = rindex (filename, ']');
+  if (dirend == 0)
+    dir = find_directory ("[]")->contents;
+#else
   dirend = rindex (filename, '/');
   if (dirend == 0)
     dir = find_directory (".")->contents;
+#endif
   else
     {
       char *dirname = (char *) alloca (dirend - filename + 1);
@@ -455,6 +592,9 @@ file_impossible_p (filename)
 #ifdef __MSDOS__
   p = filename = dosify (p);
 #endif
+#ifdef VMS
+  p = filename = vmsify (p, 1);
+#endif
 
   for (hash = 0; *p != '\0'; ++p)
     HASH (hash, *p);
@@ -495,8 +635,15 @@ print_dir_data_base ()
        if (dir->contents == 0)
          printf ("# %s: could not be stat'd.\n", dir->name);
        else if (dir->contents->files == 0)
+#ifdef VMS
+         printf ("# %s (device %d, inode [%d,%d,%d]): could not be opened.\n",
+                 dir->name, dir->contents->dev,
+                 dir->contents->ino[0], dir->contents->ino[1],
+                 dir->contents->ino[2]);
+#else
          printf ("# %s (device %d, inode %d): could not be opened.\n",
                  dir->name, dir->contents->dev, dir->contents->ino);
+#endif
        else
          {
            register unsigned int f = 0, im = 0;
@@ -508,8 +655,15 @@ print_dir_data_base ()
                  ++im;
                else
                  ++f;
+#ifdef VMS
+           printf ("# %s (device %d, inode [%d,%d,%d]): ",
+                   dir->name, dir->contents->dev,
+                       dir->contents->ino[0], dir->contents->ino[1],
+                       dir->contents->ino[2]);
+#else
            printf ("# %s (device %d, inode %d): ",
                    dir->name, dir->contents->dev, dir->contents->ino);
+#endif
            if (f == 0)
              fputs ("No", stdout);
            else
@@ -557,15 +711,15 @@ struct dirstream
   };
 
 /* Forward declarations.  */
-static __ptr_t open_dirstream __P ((const char *));
-static struct dirent *read_dirstream __P ((__ptr_t));
+static __ptr_t open_dirstream PARAMS ((const char *));
+static struct dirent *read_dirstream PARAMS ((__ptr_t));
 
 static __ptr_t
 open_dirstream (directory)
      const char *directory;
 {
   struct dirstream *new;
-  struct directory *dir = find_directory (directory);
+  struct directory *dir = find_directory ((char *)directory);
 
   if (dir->contents == 0 || dir->contents->files == 0)
     /* DIR->contents is nil if the directory could not be stat'd.
index 7348fb2..5f46ac2 100644 (file)
--- a/expand.c
+++ b/expand.c
@@ -17,8 +17,9 @@ along with GNU Make; see the file COPYING.  If not, write to
 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 #include "make.h"
+#include "filedef.h"
+#include "job.h"
 #include "commands.h"
-#include "file.h"
 #include "variable.h"
 
 /* The next two describe the variable output buffer.
diff --git a/file.c b/file.c
index f81c9b9..5bf4708 100644 (file)
--- a/file.c
+++ b/file.c
@@ -17,9 +17,10 @@ along with GNU Make; see the file COPYING.  If not, write to
 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 #include "make.h"
-#include "commands.h"
 #include "dep.h"
-#include "file.h"
+#include "filedef.h"
+#include "job.h"
+#include "commands.h"
 #include "variable.h"
 #include <assert.h>
 
@@ -55,6 +56,10 @@ lookup_file (name)
   /* This is also done in parse_file_seq, so this is redundant
      for names read from makefiles.  It is here for names passed
      on the command line.  */
+#ifdef VMS
+  while (name[0] == '[' && name[1] == ']' && name[2] != '\0')
+      name += 2;
+#endif
   while (name[0] == '.' && name[1] == '/' && name[2] != '\0')
     {
       name += 2;
@@ -65,7 +70,11 @@ lookup_file (name)
 
   if (*name == '\0')
     /* It was all slashes after a dot.  */
+#ifdef VMS
+    name = "[]";
+#else
     name = "./";
+#endif
 
   hashval = 0;
   for (n = name; *n != '\0'; ++n)
@@ -73,8 +82,12 @@ lookup_file (name)
   hashval %= FILE_BUCKETS;
 
   for (f = files[hashval]; f != 0; f = f->next)
-    if (streq (f->name, name))
-      return f;
+    {
+      if (streq (f->name, name))
+       {
+         return f;
+       }
+    }
   return 0;
 }
 
@@ -85,10 +98,26 @@ enter_file (name)
   register struct file *f, *new;
   register char *n;
   register unsigned int hashval;
+#ifdef VMS
+  char *lname, *ln;
+#endif
 
   if (*name == '\0')
     abort ();
 
+#ifdef VMS
+  lname = (char *)malloc (strlen (name) + 1);
+  for (n = name, ln = lname; *n != '\0'; ++n, ++ln)
+    {
+      if (isupper(*n))
+       *ln = tolower(*n);
+      else
+       *ln = *n;
+    }
+  *ln = 0;
+  name = lname;
+#endif
+
   hashval = 0;
   for (n = name; *n != '\0'; ++n)
     HASH (hashval, *n);
@@ -99,7 +128,12 @@ enter_file (name)
       break;
 
   if (f != 0 && !f->double_colon)
-    return f;
+    {
+#ifdef VMS
+      free(lname);
+#endif
+      return f;
+    }
 
   new = (struct file *) xmalloc (sizeof (struct file));
   bzero ((char *) new, sizeof (struct file));
@@ -477,7 +511,9 @@ print_file (f)
      struct file *f;
 {
   register struct dep *d;
-
+#ifdef VMS
+  extern char *cvt_time PARAMS ((unsigned long));
+#endif
   putchar ('\n');
   if (!f->is_target)
     puts ("# Not a target:");
@@ -513,8 +549,13 @@ print_file (f)
   else if (f->last_mtime == (time_t) -1)
     puts ("#  File does not exist.");
   else
+#ifdef VMS
+    printf ("#  Last modified %.24s (%0lx)\n",
+           cvt_time(f->last_mtime), (unsigned long) f->last_mtime);
+#else
     printf ("#  Last modified %.24s (%ld)\n",
            ctime (&f->last_mtime), (long int) f->last_mtime);
+#endif
   printf ("#  File has%s been updated.\n",
          f->updated ? "" : " not");
   switch (f->command_state)
@@ -601,3 +642,5 @@ print_file_data_base ()
 #endif
     }
 }
+
+/* EOF */
diff --git a/filedef.h b/filedef.h
new file mode 100644 (file)
index 0000000..6070ecb
--- /dev/null
+++ b/filedef.h
@@ -0,0 +1,120 @@
+/* Definition of target file data structures for GNU Make.
+Copyright (C) 1988, 89, 90, 91, 92, 93, 94 Free Software Foundation, Inc.
+This file is part of GNU Make.
+
+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
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Make is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Make; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* Structure that represents the info on one file
+   that the makefile says how to make.
+   All of these are chained together through `next'.  */
+
+struct file
+  {
+    struct file *next;
+    char *name;
+    struct dep *deps;
+    struct commands *cmds;     /* Commands to execute for this target.  */
+    int command_flags;         /* Flags OR'd in for cmds; see commands.h.  */
+    char *stem;                        /* Implicit stem, if an implicit
+                                  rule has been used */
+    struct dep *also_make;     /* Targets that are made by making this.  */
+    time_t last_mtime;         /* File's modtime, if already known.  */
+    struct file *prev;         /* Previous entry for same file name;
+                                  used when there are multiple double-colon
+                                  entries for the same file.  */
+
+    /* File that this file was renamed to.  After any time that a
+       file could be renamed, call `check_renamed' (below).  */
+    struct file *renamed;
+
+    /* List of variable sets used for this file.  */
+    struct variable_set_list *variables;
+
+    /* Immediate dependent that caused this target to be remade,
+       or nil if there isn't one.  */
+    struct file *parent;
+
+    /* For a double-colon entry, this is the first double-colon entry for
+       the same file.  Otherwise this is null.  */
+    struct file *double_colon;
+
+    short int update_status;   /* Status of the last attempt to update,
+                                  or -1 if none has been made.  */
+
+    enum                       /* State of the commands.  */
+      {                /* Note: It is important that cs_not_started be zero.  */
+       cs_not_started,         /* Not yet started.  */
+       cs_deps_running,        /* Dep commands running.  */
+       cs_running,             /* Commands running.  */
+       cs_finished             /* Commands finished.  */
+      } command_state ENUM_BITFIELD (2);
+
+    unsigned int precious:1;   /* Non-0 means don't delete file on quit */
+    unsigned int tried_implicit:1; /* Nonzero if have searched
+                                     for implicit rule for making
+                                     this file; don't search again.  */
+    unsigned int updating:1;   /* Nonzero while updating deps of this file */
+    unsigned int updated:1;    /* Nonzero if this file has been remade.  */
+    unsigned int is_target:1;  /* Nonzero if file is described as target.  */
+    unsigned int cmd_target:1; /* Nonzero if file was given on cmd line.  */
+    unsigned int phony:1;      /* Nonzero if this is a phony file
+                                  i.e., a dependency of .PHONY.  */
+    unsigned int intermediate:1;/* Nonzero if this is an intermediate file.  */
+    /* Nonzero, for an intermediate file,
+       means remove_intermediates should not delete it.  */
+    unsigned int secondary:1;
+    unsigned int dontcare:1;   /* Nonzero if no complaint is to be made if
+                                  this target cannot be remade.  */
+  };
+
+/* Number of intermediate files entered.  */
+
+extern unsigned int num_intermediates;
+
+extern struct file *default_goal_file, *suffix_file, *default_file;
+
+
+extern struct file *lookup_file (), *enter_file ();
+extern void remove_intermediates (), snap_deps ();
+extern void rename_file (), file_hash_enter ();
+extern void set_command_state ();
+
+
+/* Return the mtime of file F (a struct file *), caching it.
+   The value is -1 if the file does not exist.  */
+#define file_mtime(f) file_mtime_1 ((f), 1)
+/* Return the mtime of file F (a struct file *), caching it.
+   Don't search using vpath for the file--if it doesn't actually exist,
+   we don't find it.
+   The value is -1 if the file does not exist.  */
+#define file_mtime_no_search(f) file_mtime_1 ((f), 0)
+extern time_t f_mtime ();
+#define file_mtime_1(f, v) \
+  ((f)->last_mtime != (time_t) 0 ? (f)->last_mtime : f_mtime ((f), v))
+
+/* Modtime value to use for `infinitely new'.  We used to get the current time
+   from the system and use that whenever we wanted `new'.  But that causes
+   trouble when the machine running make and the machine holding a file have
+   different ideas about what time it is; and can also lose for `force'
+   targets, which need to be considered newer than anything that depends on
+   them, even if said dependents' modtimes are in the future.
+
+   NOTE: This assumes 32-bit `time_t's, but I cannot think of a portable way
+   to produce the largest representable integer of a given signed type.  */
+#define NEW_MTIME      ((time_t) 0x7fffffff)
+
+
+#define check_renamed(file) \
+  while ((file)->renamed != 0) (file) = (file)->renamed /* No ; here.  */
index e5b46d7..1886f75 100644 (file)
@@ -17,17 +17,18 @@ along with GNU Make; see the file COPYING.  If not, write to
 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 #include "make.h"
+#include "filedef.h"
 #include "variable.h"
 #include "dep.h"
-#include "commands.h"
 #include "job.h"
+#include "commands.h"
 
 #ifdef __MSDOS__
 #include <process.h>
 #include <fcntl.h>
 #endif
 
-static char *string_glob ();
+static char *string_glob PARAMS ((char *line));
 \f
 /* Store into VARIABLE_BUFFER at O the result of scanning TEXT and replacing
    each occurrence of SUBST with REPLACE. TEXT is null-terminated.  SLEN is
@@ -35,7 +36,7 @@ static char *string_glob ();
    nonzero, substitutions are done only on matches which are complete
    whitespace-delimited words.  If SUFFIX_ONLY is nonzero, substitutions are
    done only at the ends of whitespace-delimited words.  */
-   
+
 char *
 subst_expand (o, text, subst, replace, slen, rlen, by_word, suffix_only)
      char *o;
@@ -337,7 +338,8 @@ expand_function (o, function, text, end)
     default:
       abort ();
       break;
-      
+
+#ifndef VMS /* not supported for vms yet */
     case function_shell:
       {
        char **argv, **envp;
@@ -349,12 +351,13 @@ expand_function (o, function, text, end)
        text = expand_argument (text, end);
 
        /* Construct the argument list.  */
-       argv = construct_command_argv (text, (char *) NULL, (struct file *) 0);
+       argv = construct_command_argv (text,
+                                      (char **) NULL, (struct file *) 0);
        if (argv == 0)
          break;
 
        /* Using a target environment for `shell' loses in cases like:
-               export var = $(shell echo foobie) 
+               export var = $(shell echo foobie)
           because target_environment hits a loop trying to expand $(var)
           to put it in the environment.  This is even more confusing when
           var was not explicitly exported, but just appeared in the
@@ -498,7 +501,7 @@ expand_function (o, function, text, end)
           unsigned int maxlen = 200;
           int cc;
           char *buffer;
+
           strcpy (tmp_output, "shXXXXXX");
           mktemp (tmp_output);
           child_stdout = open (tmp_output,
@@ -509,9 +512,9 @@ expand_function (o, function, text, end)
           dup2 (save_stdout, 1);
           close (child_stdout);
           close (save_stdout);
+
           child_stdout = open (tmp_output, O_RDONLY|O_TEXT, 0644);
+
           buffer = xmalloc (maxlen);
           i = 0;
           do
@@ -521,15 +524,15 @@ expand_function (o, function, text, end)
                   maxlen += 512;
                   buffer = (char *) xrealloc (buffer, maxlen + 1);
                 }
+
               cc = read (child_stdout, &buffer[i], maxlen - i);
               if (cc > 0)
                 i += cc;
             } while (cc > 0);
+
           close (child_stdout);
           unlink (tmp_output);
+
           if (i > 0)
             {
               if (buffer[i - 1] == '\n')
@@ -548,6 +551,7 @@ expand_function (o, function, text, end)
        free (text);
        break;
       }
+#endif /* !VMS */
 
     case function_origin:
       /* Expand the argument.  */
@@ -590,7 +594,7 @@ expand_function (o, function, text, end)
 
       free (text);
       break;
-      
+
     case function_sort:
       /* Expand the argument.  */
       text = expand_argument (text, end);
@@ -610,7 +614,7 @@ expand_function (o, function, text, end)
                nwords *= 2;
                words = (char **) xrealloc ((char *) words,
                                            nwords * sizeof (char *));
-             } 
+             }
            words[wordi++] = savestring (p, len);
          }
 
@@ -640,7 +644,7 @@ expand_function (o, function, text, end)
 
       free (text);
       break;
-      
+
     case function_foreach:
       {
        /* Get three comma-separated arguments but
@@ -733,7 +737,7 @@ expand_function (o, function, text, end)
        if (p == end)
          BADARGS (function == function_filter ? "filter" : "filter-out");
        p2 = expand_argument (text, p);
-       
+
        text = expand_argument (p + 1, end);
 
        /* Chop TEXT up into words and then run each pattern through.  */
@@ -792,7 +796,7 @@ expand_function (o, function, text, end)
        free (text);
       }
       break;
-      
+
     case function_patsubst:
       /* Get three comma-separated arguments and expand each one.  */
       count = 0;
@@ -825,9 +829,9 @@ expand_function (o, function, text, end)
       text = expand_argument (text, p2);
       p3 = expand_argument (p2 + 1, p);
       p2 = expand_argument (p + 1, end);
-      
+
       o = patsubst_expand (o, p2, text, p3, (char *) 0, (char *) 0);
-      
+
       free (text);
       free (p3);
       free (p2);
@@ -850,7 +854,7 @@ expand_function (o, function, text, end)
       text = expand_argument (text, p);
 
       p = expand_argument (p + 1, end);
-      
+
       {
        /* Write each word of the first argument directly followed
           by the corresponding word of the second argument.
@@ -866,11 +870,11 @@ expand_function (o, function, text, end)
            tp = find_next_token (&p2, &tlen);
            if (tp != 0)
              o = variable_buffer_output (o, tp, tlen);
-           
+
            pp = find_next_token (&p3, &plen);
            if (pp != 0)
              o = variable_buffer_output (o, pp, plen);
-           
+
            if (tp != 0 || pp != 0)
              {
                o = variable_buffer_output (o, " ", 1);
@@ -882,11 +886,11 @@ expand_function (o, function, text, end)
          /* Kill the last blank.  */
          --o;
       }
-      
+
       free (text);
       free (p);
       break;
-      
+
     case function_strip:
       /* Expand the argument.  */
       text = expand_argument (text, end);
@@ -901,19 +905,19 @@ expand_function (o, function, text, end)
       if (doneany)
        /* Kill the last space.  */
        --o;
-      
+
       free (text);
       break;
-      
+
     case function_wildcard:
       text = expand_argument (text, end);
-      
+
       p = string_glob (text);
       o = variable_buffer_output (o, p, strlen (p));
-      
+
       free (text);
       break;
-      
+
     case function_subst:
       /* Get three comma-separated arguments and expand each one.  */
       count = 0;
@@ -946,14 +950,14 @@ expand_function (o, function, text, end)
       text = expand_argument (text, p2);
       p3 = expand_argument (p2 + 1, p);
       p2 = expand_argument (p + 1, end);
-      
+
       o = subst_expand (o, p2, text, p3, strlen (text), strlen (p3), 0, 0);
-      
+
       free (text);
       free (p3);
       free (p2);
       break;
-      
+
     case function_firstword:
       /* Expand the argument.  */
       text = expand_argument (text, end);
@@ -963,10 +967,10 @@ expand_function (o, function, text, end)
       p = find_next_token (&p2, &i);
       if (p != 0)
        o = variable_buffer_output (o, p, i);
-      
+
       free (text);
       break;
-      
+
     case function_word:
       /* Get two comma-separated arguments and expand each one.  */
       count = 0;
@@ -1058,11 +1062,11 @@ index argument");
       i = strlen (text);
       if (sindex (p, 0, text, i) != 0)
        o = variable_buffer_output (o, text, i);
-      
+
       free (p);
       free (text);
       break;
-      
+
     case function_addsuffix:
     case function_addprefix:
       /* Get two comma-separated arguments and expand each one.  */
@@ -1082,7 +1086,7 @@ index argument");
       i = strlen (text);
 
       p2 = expand_argument (p + 1, end);
-      
+
       p3 = p2;
       while ((p = find_next_token (&p3, &len)) != 0)
        {
@@ -1097,11 +1101,11 @@ index argument");
       if (doneany)
        /* Kill last space.  */
        --o;
-      
+
       free (p2);
       free (text);
       break;
-      
+
     case function_dir:
     case function_basename:
       /* Expand the argument.  */
@@ -1111,7 +1115,11 @@ index argument");
       while ((p2 = find_next_token (&p3, &len)) != 0)
        {
          p = p2 + len;
+#ifdef VMS
+         while (p >= p2 && *p != (function == function_dir ? ']' : '.'))
+#else
          while (p >= p2 && *p != (function == function_dir ? '/' : '.'))
+#endif
            --p;
          if (p >= p2)
            {
@@ -1120,7 +1128,11 @@ index argument");
              o = variable_buffer_output (o, p2, p - p2);
            }
          else if (function == function_dir)
+#ifdef VMS
+            o = variable_buffer_output (o, "[]", 2);
+#else
             o = variable_buffer_output (o, "./", 2);
+#endif
          else
            /* The entire name is the basename.  */
            o = variable_buffer_output (o, p2, len);
@@ -1131,10 +1143,10 @@ index argument");
       if (doneany)
        /* Kill last space.  */
        --o;
-      
+
       free (text);
       break;
-      
+
     case function_notdir:
     case function_suffix:
       /* Expand the argument.  */
@@ -1144,7 +1156,11 @@ index argument");
       while ((p2 = find_next_token (&p3, &len)) != 0)
        {
          p = p2 + len;
+#ifdef VMS
+         while (p >= p2 && *p != (function == function_notdir ? ']' : '.'))
+#else
          while (p >= p2 && *p != (function == function_notdir ? '/' : '.'))
+#endif
            --p;
          if (p >= p2)
            {
index 947ab4a..2ccf354 100644 (file)
@@ -19,9 +19,10 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "make.h"
 #include "rule.h"
 #include "dep.h"
-#include "file.h"
+#include "filedef.h"
 
-static int pattern_search ();
+static int pattern_search PARAMS ((struct file *file, int archive, unsigned int depth,
+               unsigned int recursions));
 \f
 /* For a FILE which has no commands specified, try to figure out some
    from the implicit pattern rules.
@@ -162,7 +163,11 @@ pattern_search (file, archive, depth, recursions)
       /* Set LASTSLASH to point at the last slash in FILENAME
         but not counting any slash at the end.  (foo/bar/ counts as
         bar/ in directory foo/, not empty in directory foo/bar/.)  */
+#ifdef VMS
+      lastslash = rindex (filename, ']');
+#else
       lastslash = rindex (filename, '/');
+#endif
       if (lastslash != 0 && lastslash[1] == '\0')
        lastslash = 0;
     }
@@ -210,7 +215,11 @@ pattern_search (file, archive, depth, recursions)
          /* Set CHECK_LASTSLASH if FILENAME contains a directory
             prefix and the target pattern does not contain a slash.  */
 
+#ifdef VMS
+         check_lastslash = lastslash != 0 && index (target, ']') == 0;
+#else
          check_lastslash = lastslash != 0 && index (target, '/') == 0;
+#endif
          if (check_lastslash)
            {
              /* In that case, don't include the
diff --git a/job.c b/job.c
index e5d4d1c..90ae9d9 100644 (file)
--- a/job.c
+++ b/job.c
@@ -18,9 +18,9 @@ along with GNU Make; see the file COPYING.  If not, write to
 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 #include "make.h"
-#include "commands.h"
 #include "job.h"
-#include "file.h"
+#include "filedef.h"
+#include "commands.h"
 #include "variable.h"
 #include <assert.h>
 
@@ -36,6 +36,13 @@ static char *dos_bename;
 static int dos_batch_file;
 #endif /* MSDOS.  */
 
+#ifdef VMS
+#include <time.h>
+#include <processes.h>
+#include <starlet.h>
+#include <lib$routines.h>
+#endif
+
 #ifdef HAVE_FCNTL_H
 #include <fcntl.h>
 #else
@@ -102,22 +109,40 @@ extern int wait ();
 
 #endif /* Don't have `union wait'.  */
 
+#ifdef VMS
+static int vms_jobsefnmask=0;
+#endif /* !VMS */
 
 #ifndef        HAVE_UNISTD_H
 extern int dup2 ();
 extern int execve ();
 extern void _exit ();
-extern int geteuid (), getegid ();
-extern int setgid (), getgid ();
+#ifndef VMS
+extern int geteuid ();
+extern int getegid ();
+extern int setgid ();
+extern int getgid ();
+#endif
 #endif
 
-extern int getloadavg ();
-extern int start_remote_job_p ();
-extern int start_remote_job (), remote_status ();
-
-RETSIGTYPE child_handler ();
-static void free_child (), start_job_command ();
-static int load_too_high (), job_next_command ();
+extern char *allocated_variable_expand_for_file PARAMS ((char *line, struct file *file));
+
+extern int getloadavg PARAMS ((double loadavg[], int nelem));
+extern int start_remote_job PARAMS ((char **argv, char **envp, int stdin_fd,
+               int *is_remote, int *id_ptr, int *used_stdin));
+extern int start_remote_job_p PARAMS ((void));
+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));
+static int job_next_command PARAMS ((struct child *));
+static int start_waiting_job PARAMS ((struct child *));
+#ifdef VMS
+static void vmsWaitForChildren PARAMS ((int *));
+#endif
 \f
 /* Chain of all live (or recently deceased) children.  */
 
@@ -148,6 +173,10 @@ child_error (target_name, exit_code, exit_sig, coredump, ignored)
   if (ignored && silent_flag)
     return;
 
+#ifdef VMS
+  if (!(exit_code & 1))
+      error("*** [%s] Error 0x%x%s", target_name, exit_code, ((ignored)? " (ignored)" : ""));
+#else
   if (exit_sig == 0)
     error (ignored ? "[%s] Error %d (ignored)" :
           "*** [%s] Error %d",
@@ -156,10 +185,31 @@ child_error (target_name, exit_code, exit_sig, coredump, ignored)
     error ("*** [%s] %s%s",
           target_name, strsignal (exit_sig),
           coredump ? " (core dumped)" : "");
+#endif
 }
 \f
 static unsigned int dead_children = 0;
 
+#ifdef VMS
+/* Wait for nchildren children to terminate */
+static void
+vmsWaitForChildren(int *status)
+{
+  while (1)
+    {
+      if (!vms_jobsefnmask)
+       {
+         *status = 0;
+         return;
+       }
+
+      *status = sys$wflor (32, vms_jobsefnmask);
+    }
+  return;
+}
+#endif
+
+
 /* Notice that a child died.
    reap_children should be called when convenient.  */
 RETSIGTYPE
@@ -215,7 +265,7 @@ reap_children (block, err)
         and we might print the "Waiting for unfinished jobs" message above
         when not necessary.  */
 
-      if (dead_children != 0)
+      if (dead_children > 0)
        --dead_children;
 
       any_remote = 0;
@@ -228,6 +278,9 @@ reap_children (block, err)
            printf ("Live child 0x%08lx PID %d%s\n",
                    (unsigned long int) c,
                    c->pid, c->remote ? " (remote)" : "");
+#ifdef VMS
+         break;
+#endif
        }
 
       /* First, check for remote children.  */
@@ -235,6 +288,7 @@ reap_children (block, err)
        pid = remote_status (&exit_code, &exit_sig, &coredump, 0);
       else
        pid = 0;
+
       if (pid < 0)
        {
        remote_status_lose:
@@ -251,19 +305,24 @@ reap_children (block, err)
 
          if (any_local)
            {
-#ifdef WAIT_NOHANG
+#ifdef VMS
+             vmsWaitForChildren (&status);
+             pid = c->pid;
+#else
+#ifdef WAIT_NOHANG
              if (!block)
                pid = WAIT_NOHANG (&status);
              else
 #endif
                pid = wait (&status);
+#endif /* !VMS */
            }
          else
            pid = 0;
 
          if (pid < 0)
            {
-#ifdef EINTR
+#ifdef EINTR
              if (errno == EINTR)
                continue;
 #endif
@@ -442,7 +501,8 @@ reap_children (block, err)
            free_child (c);
 
          /* There is now another slot open.  */
-         --job_slots_used;
+         if (job_slots_used > 0)
+           --job_slots_used;
 
          /* If the job failed, and the -k flag was not given, die,
             unless we are already in the process of dying.  */
@@ -453,6 +513,7 @@ reap_children (block, err)
       /* Only block for one child.  */
       block = 0;
     }
+  return;
 }
 \f
 /* Free the storage allocated for CHILD.  */
@@ -514,7 +575,11 @@ start_job_command (child)
   static int bad_stdin = -1;
   register char *p;
   int flags;
+#ifdef VMS
+  char *argv;
+#else
   char **argv;
+#endif
 
   /* Combine the flags parsed for the line itself with
      the flags specified globally for this target.  */
@@ -523,6 +588,7 @@ start_job_command (child)
 
   p = child->command_ptr;
   child->noerror = flags & COMMANDS_NOERROR;
+
   while (*p != '\0')
     {
       if (*p == '@')
@@ -553,8 +619,12 @@ start_job_command (child)
   /* Figure out an argument list from this command line.  */
 
   {
-    char *end;
+    char *end = 0;
+#ifdef VMS
+    argv = p;
+#else
     argv = construct_command_argv (p, &end, child->file);
+#endif
     if (end == NULL)
       child->command_ptr = NULL;
     else
@@ -568,8 +638,10 @@ start_job_command (child)
     {
       /* Go on to the next command.  It might be the recursive one.
         We construct ARGV only to find the end of the command line.  */
+#ifndef VMS
       free (argv[0]);
       free ((char *) argv);
+#endif
       argv = 0;
     }
 
@@ -608,8 +680,10 @@ start_job_command (child)
 
   if (just_print_flag && !(flags & COMMANDS_RECURSE))
     {
+#ifndef VMS
       free (argv[0]);
       free ((char *) argv);
+#endif
       goto next_command;
     }
 
@@ -618,6 +692,8 @@ start_job_command (child)
   fflush (stdout);
   fflush (stderr);
 
+#ifndef VMS
+
   /* Set up a bad standard input that reads from a broken pipe.  */
 
   if (bad_stdin == -1)
@@ -652,6 +728,8 @@ start_job_command (child)
   if (child->good_stdin)
     good_stdin_used = 1;
 
+#endif /* !VMS */
+
   child->deleted = 0;
 
   /* Set up the environment for the child.  */
@@ -660,6 +738,7 @@ start_job_command (child)
 
 #ifndef        __MSDOS__
 
+#ifndef VMS
   /* start_waiting_job has set CHILD->remote if we can start a remote job.  */
   if (child->remote)
     {
@@ -680,6 +759,7 @@ start_job_command (child)
        }
     }
   else
+#endif /* !VMS */
     {
       /* Fork the child process.  */
 
@@ -694,6 +774,17 @@ start_job_command (child)
 #endif
 
       child->remote = 0;
+
+#ifdef VMS
+
+      if (!child_execute_job (argv, child)) {
+        /* Fork failed!  */
+        perror_with_name ("vfork", "");
+        goto error;
+      }
+
+#else
+
       parent_environ = environ;
       child->pid = vfork ();
       environ = parent_environ;        /* Restore value child may have clobbered.  */
@@ -711,9 +802,11 @@ start_job_command (child)
          perror_with_name ("vfork", "");
          goto error;
        }
+#endif /* !VMS */
     }
 
 #else  /* MSDOS.  */
+
   dos_status = spawnvpe (P_WAIT, argv[0], argv, child->environment);
   ++dead_children;
   child->pid = dos_pid++;
@@ -735,15 +828,17 @@ start_job_command (child)
   set_command_state (child->file, cs_running);
 
   /* Free the storage used by the child's argument list.  */
-
+#ifndef VMS
   free (argv[0]);
   free ((char *) argv);
+#endif
 
   return;
 
  error:
   child->file->update_status = 2;
   notice_finished_file (child->file);
+  return;
 }
 
 /* Try to start a child running.
@@ -949,13 +1044,15 @@ new_job (file)
 
   /* The job is now primed.  Start it running.
      (This will notice if there are in fact no commands.)  */
-  start_waiting_job (c);
+  (void)start_waiting_job (c);
 
   if (job_slots == 1)
     /* Since there is only one job slot, make things run linearly.
        Wait for the child to die, setting the state to `cs_finished'.  */
     while (file->command_state == cs_running)
       reap_children (1, 0);
+
+  return;
 }
 \f
 /* Move CHILD's pointers to the next command for it to execute.
@@ -984,10 +1081,9 @@ job_next_command (child)
 static int
 load_too_high ()
 {
-#ifdef __MSDOS__
+#if defined(__MSDOS__) || defined(VMS)
   return 1;
 #else
-  extern int getloadavg ();
   double load;
 
   if (max_load_average < 0)
@@ -1036,10 +1132,226 @@ start_waiting_jobs ()
 
       /* Try to start that job.  We break out of the loop as soon
         as start_waiting_job puts one back on the waiting list.  */
-    } while (start_waiting_job (job) && waiting_jobs != 0);
+    }
+  while (start_waiting_job (job) && waiting_jobs != 0);
+
+  return;
 }
 \f
-/* Replace the current process with one executing the command in ARGV.
+#ifdef VMS
+#include <descrip.h>
+#include <clidef.h>
+
+/* This is called as an AST when a child process dies (it won't get
+   interrupted by anything except a higher level AST).
+*/
+int vmsHandleChildTerm(struct child *child)
+{
+    int status;
+    register struct child *lastc, *c;
+    int child_failed;
+
+    vms_jobsefnmask &= ~(1 << (child->efn - 32));
+
+    lib$free_ef(&child->efn);
+
+    (void) sigblock (fatal_signal_mask);
+
+    child_failed = !(child->cstatus & 1 || ((child->cstatus & 7) == 0));
+
+    /* Search for a child matching the deceased one.  */
+    lastc = 0;
+#if defined(RECURSIVEJOBS) /* I've had problems with recursive stuff and process handling */
+    for (c = children; c != 0 && c != child; lastc = c, c = c->next);
+#else
+    c = child;
+#endif
+
+    if (child_failed && !c->noerror && !ignore_errors_flag)
+      {
+       /* The commands failed.  Write an error message,
+          delete non-precious targets, and abort.  */
+       child_error (c->file->name, c->cstatus, 0, 0, 0);
+       c->file->update_status = 1;
+       delete_child_targets (c);
+      }
+    else
+      {
+       if (child_failed)
+         {
+           /* The commands failed, but we don't care.  */
+           child_error (c->file->name, c->cstatus, 0, 0, 1);
+           child_failed = 0;
+         }
+
+#if defined(RECURSIVEJOBS) /* I've had problems with recursive stuff and process handling */
+       /* If there are more commands to run, try to start them.  */
+       start_job (c);
+
+       switch (c->file->command_state)
+         {
+         case cs_running:
+           /* Successfully started.  */
+           break;
+
+         case cs_finished:
+           if (c->file->update_status != 0) {
+               /* We failed to start the commands.  */
+               delete_child_targets (c);
+           }
+           break;
+
+         default:
+           error ("internal error: `%s' command_state \
+%d in child_handler", c->file->name);
+           abort ();
+           break;
+         }
+#endif /* RECURSIVEJOBS */
+      }
+
+    /* Set the state flag to say the commands have finished.  */
+    c->file->command_state = cs_finished;
+    notice_finished_file (c->file);
+
+#if defined(RECURSIVEJOBS) /* I've had problems with recursive stuff and process handling */
+    /* Remove the child from the chain and free it.  */
+    if (lastc == 0)
+      children = c->next;
+    else
+      lastc->next = c->next;
+    free_child (c);
+#endif /* RECURSIVEJOBS */
+
+    /* There is now another slot open.  */
+    if (job_slots_used > 0)
+      --job_slots_used;
+
+    /* If the job failed, and the -k flag was not given, die.  */
+    if (child_failed && !keep_going_flag)
+      die (EXIT_FAILURE);
+
+    (void) sigsetmask (sigblock (0) & ~(fatal_signal_mask));
+
+    return 1;
+}
+
+/* VMS:
+   Spawn a process executing the command in ARGV and return its pid. */
+
+#define MAXCMDLEN 200
+
+int
+child_execute_job (argv, child)
+     char *argv;
+     struct child *child;
+{
+  int i;
+  static struct dsc$descriptor_s cmddsc;
+#ifndef DONTWAITFORCHILD
+  int spflags = 0;
+#else
+  int spflags = CLI$M_NOWAIT;
+#endif
+  int status;
+  char cmd[4096],*p,*c;
+  char comname[50];
+
+/* Remove backslashes */
+  for (p = argv, c = cmd; *p; p++,c++)
+    {
+      if (*p == '\\') p++;
+       *c = *p;
+    }
+  *c = *p;
+
+  /* check for maximum dcl length and create *.com file if neccesary */
+
+  comname[0] = '\0';
+
+  if (strlen (cmd) > MAXCMDLEN)
+    {
+      FILE *outfile;
+      char tmp;
+
+      strcpy (comname, "sys$scratch:CMDXXXXXX.COM");
+      (void) mktemp (comname);
+
+      outfile = fopen (comname, "w");
+      if (outfile == 0)
+       pfatal_with_name (comname);
+
+      fprintf (outfile, "$ ");
+      c = cmd;
+
+      while (c)
+       {
+         p = strchr (c, ',');
+         if ((p == NULL) || (p-c > MAXCMDLEN))
+           p = strchr (c, ' ');
+         if (p != NULL)
+           {
+             p++;
+             tmp = *p;
+             *p = '\0';
+           }
+         else
+           tmp = '\0';
+         fprintf (outfile, "%s%s\n", c, (tmp == '\0')?"":" -");
+         if (p != NULL)
+           *p = tmp;
+         c = p;
+       }
+
+      fclose (outfile);
+
+      sprintf (cmd, "$ @%s", comname);
+
+      if (debug_flag)
+       printf ("Executing %s instead\n", cmd);
+    }
+
+  cmddsc.dsc$w_length = strlen(cmd);
+  cmddsc.dsc$a_pointer = cmd;
+  cmddsc.dsc$b_dtype = DSC$K_DTYPE_T;
+  cmddsc.dsc$b_class = DSC$K_CLASS_S;
+
+  child->efn = 0;
+  while (child->efn < 32 || child->efn > 63)
+    {
+      status = lib$get_ef(&child->efn);
+      if (!(status & 1))
+       return 0;
+    }
+
+  sys$clref(child->efn);
+
+  vms_jobsefnmask |= (1 << (child->efn - 32));
+
+#ifndef DONTWAITFORCHILD
+  status = lib$spawn(&cmddsc,0,0,&spflags,0,&child->pid,&child->cstatus,
+                      &child->efn,0,0);
+  vmsHandleChildTerm(child);
+#else
+  status = lib$spawn(&cmddsc,0,0,&spflags,0,&child->pid,&child->cstatus,
+                      &child->efn,vmsHandleChildTerm,child);
+#endif
+
+  if (!(status & 1))
+    {
+      printf("Error spawning, %d\n",status);
+      fflush(stdout);
+    }
+
+  unlink (comname);
+
+  return (status & 1);
+}
+
+#else /* !VMS */
+
+/* UNIX:
+   Replace the current process with one executing the command in ARGV.
    STDIN_FD and STDOUT_FD are used as the process's stdin and stdout; ENVP is
    the environment of the new program.  This function does not return.  */
 
@@ -1060,6 +1372,7 @@ child_execute_job (stdin_fd, stdout_fd, argv, envp)
   /* Run the command.  */
   exec_command (argv, envp);
 }
+#endif /* !VMS */
 \f
 /* Replace the current process with one running the command in ARGV,
    with environment ENVP.  This function does not return.  */
@@ -1068,6 +1381,12 @@ void
 exec_command (argv, envp)
      char **argv, **envp;
 {
+#ifdef VMS
+    /* Run the program.  */
+    execve (argv[0], argv, envp);
+    perror_with_name ("execve: ", argv[0]);
+    _exit (EXIT_FAILURE);
+#else
   /* Be the user, permanently.  */
   child_access ();
 
@@ -1119,8 +1438,10 @@ exec_command (argv, envp)
     }
 
   _exit (127);
+#endif /* !VMS */
 }
 \f
+#ifndef 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
    when no backslash, $ or ` characters are seen in the quotes.  Starting
@@ -1364,7 +1685,7 @@ construct_command_argv_internal (line, restp, shell, ifs)
     {
       /* Free the old argument list we were working on.  */
       free (new_argv[0]);
-      free (new_argv);
+      free ((void *)new_argv);
     }
 
 #ifdef __MSDOS__
@@ -1496,6 +1817,7 @@ construct_command_argv (line, restp, file)
 
   return argv;
 }
+#endif /* !VMS */
 \f
 #ifndef        HAVE_DUP2
 int
diff --git a/job.h b/job.h
index 572bb33..82814aa 100644 (file)
--- a/job.h
+++ b/job.h
@@ -16,6 +16,9 @@ You should have received a copy of the GNU General Public License
 along with GNU Make; see the file COPYING.  If not, write to
 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
+#ifndef SEEN_JOB_H
+#define SEEN_JOB_H
+
 /* Structure describing a running or dead child process.  */
 
 struct child
@@ -31,6 +34,10 @@ struct child
     char *command_ptr;         /* Ptr into command_lines[command_line].  */
 
     pid_t pid;                 /* Child process's ID number.  */
+#ifdef VMS
+    int efn;                   /* Completion event flag number */
+    int cstatus;               /* Completion status */
+#endif
     unsigned int remote:1;     /* Nonzero if executing remotely.  */
 
     unsigned int noerror:1;    /* Nonzero if commands contained a `-'.  */
@@ -41,18 +48,22 @@ struct child
 
 extern struct child *children;
 
-extern void new_job ();
-extern void reap_children ();
-extern void start_waiting_jobs ();
+extern void new_job PARAMS ((struct file *file));
+extern void reap_children PARAMS ((int block, int err));
+extern void start_waiting_jobs PARAMS ((void));
 
-extern char **construct_command_argv ();
-extern void child_execute_job ();
-extern void exec_command ();
+extern char **construct_command_argv PARAMS ((char *line, char **restp, struct file *file));
+#ifdef VMS
+extern int child_execute_job PARAMS ((char *argv, struct child *child));
+#else
+extern void child_execute_job PARAMS ((int stdin_fd, int stdout_fd, char **argv, char **envp));
+#endif
+extern void exec_command PARAMS ((char **argv, char **envp));
 
 extern unsigned int job_slots_used;
 
 #ifdef POSIX
-extern void unblock_sigs ();
+extern void unblock_sigs PARAMS ((void));
 #else
 #ifdef HAVE_SIGSETMASK
 extern int fatal_signal_mask;
@@ -61,3 +72,5 @@ extern int fatal_signal_mask;
 #define        unblock_sigs()
 #endif
 #endif
+
+#endif /* SEEN_JOB_H */
diff --git a/main.c b/main.c
index a03397f..efbd70e 100644 (file)
--- a/main.c
+++ b/main.c
@@ -17,20 +17,23 @@ along with GNU Make; see the file COPYING.  If not, write to
 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 #include "make.h"
-#include "commands.h"
 #include "dep.h"
-#include "file.h"
+#include "filedef.h"
 #include "variable.h"
 #include "job.h"
+#include "commands.h"
 #include "getopt.h"
 #include <assert.h>
 
+extern void init_dir PARAMS ((void));
+extern RETSIGTYPE fatal_error_signal PARAMS ((int sig));
+extern RETSIGTYPE child_handler PARAMS ((int sig));
 
-extern void print_variable_data_base ();
-extern void print_dir_data_base ();
-extern void print_rule_data_base ();
-extern void print_file_data_base ();
-extern void print_vpath_data_base ();
+extern void print_variable_data_base PARAMS ((void));
+extern void print_dir_data_base PARAMS ((void));
+extern void print_rule_data_base PARAMS ((void));
+extern void print_file_data_base PARAMS ((void));
+extern void print_vpath_data_base PARAMS ((void));
 
 #ifndef        HAVE_UNISTD_H
 extern int chdir ();
@@ -43,10 +46,12 @@ extern double atof ();
 #endif
 extern char *mktemp ();
 
-static void print_data_base (), print_version ();
-static void decode_switches (), decode_env_switches ();
-static void define_makeflags ();
-static char *quote_as_word ();
+static void print_data_base PARAMS((void));
+static void print_version PARAMS ((void));
+static void decode_switches PARAMS ((int argc, char **argv, int env));
+static void decode_env_switches PARAMS ((char *envar, unsigned int len));
+static void define_makeflags PARAMS ((int all, int makefile));
+static char *quote_as_word PARAMS ((char *out, char *in, int double_dollars));
 \f
 /* The structure that describes an accepted command switch.  */
 
@@ -415,7 +420,6 @@ main (argc, argv, envp)
      char **argv;
      char **envp;
 {
-  extern RETSIGTYPE fatal_error_signal (), child_handler ();
   register struct file *f;
   register unsigned int i;
   char **p;
@@ -486,7 +490,11 @@ main (argc, argv, envp)
     program = "make";
   else
     {
+#ifdef VMS
+      program = rindex (argv[0], ']');
+#else
       program = rindex (argv[0], '/');
+#endif
 #ifdef __MSDOS__
       if (program == 0)
        program = rindex (argv[0], '\\');
@@ -560,7 +568,7 @@ main (argc, argv, envp)
   if (print_version_flag)
     die (0);
 
-#ifndef __MSDOS__
+#if !defined(__MSDOS__) && !defined(VMS)
   /* Set the "MAKE_COMMAND" variable to the name we were invoked with.
      (If it is a relative pathname with a slash, prepend our directory name
      so the result will run the same program regardless of the current dir.
@@ -699,7 +707,12 @@ main (argc, argv, envp)
 
            /* Make a unique filename.  */
 #ifdef HAVE_MKTEMP
+
+#ifdef VMS
+           static char name[] = "sys$scratch:GmXXXXXX";
+#else
            static char name[] = "/tmp/GmXXXXXX";
+#endif
            (void) mktemp (name);
 #else
            static char name[L_tmpnam];
@@ -1101,15 +1114,15 @@ main (argc, argv, envp)
            /* Nothing happened.  */
          case 0:
            /* Updated successfully.  */
-           status = 0;
+           status = EXIT_SUCCESS;
            break;
          case 2:
            /* Updating failed.  */
-           status = 2;
+           status = EXIT_FAILURE;
            break;
          case 1:
            /* We are under -q and would run some commands.  */
-           status = 1;
+           status = EXIT_FAILURE;
            break;
          default:
            abort ();
@@ -1589,7 +1602,11 @@ quote_as_word (out, in, double_dollars)
 {
   while (*in != '\0')
     {
+#ifdef VMS
+      if (index ("^;'\"*?$<>(){}|&~`\\ \t\r\n\f\v", *in) != 0)
+#else
       if (index ("^;'\"*?[]$<>(){}|&~`\\ \t\r\n\f\v", *in) != 0)
+#endif
        *out++ = '\\';
       if (double_dollars && *in == '$')
        *out++ = '$';
diff --git a/make.h b/make.h
index b44c339..04bc1e9 100644 (file)
--- a/make.h
+++ b/make.h
@@ -1,5 +1,5 @@
 /* Miscellaneous global declarations and portability cruft for GNU Make.
-Copyright (C) 1988, 89, 90, 91, 92, 93, 94, 95 Free Software Foundation, Inc.
+Copyright (C) 1988,89,90,91,92,93,94,95,96 Free Software Foundation, Inc.
 This file is part of GNU Make.
 
 GNU Make is free software; you can redistribute it and/or modify
@@ -28,6 +28,17 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #undef HAVE_CONFIG_H
 #define HAVE_CONFIG_H
 
+
+/* Use prototypes if available.  */
+#if defined (__cplusplus) || (defined (__STDC__) && __STDC__)
+#undef  PARAMS
+#define PARAMS(protos)  protos
+#else /* Not C++ or ANSI C.  */
+#undef  PARAMS
+#define PARAMS(protos)  ()
+#endif /* C++ or ANSI C.  */
+
+
 #ifdef CRAY
 /* This must happen before #include <signal.h> so
    that the declaration therein is changed.  */
@@ -67,9 +78,7 @@ extern int errno;
 #endif
 
 /* Some systems define _POSIX_VERSION but are not really POSIX.1.  */
-#if (defined (butterfly) || defined (__arm) || \
-     (defined (__mips) && defined (_SYSTYPE_SVR3)) || \
-     (defined (sequent) && defined (i386)))
+#if (defined (butterfly) || defined (__arm) || (defined (__mips) && defined (_SYSTYPE_SVR3)) || (defined (sequent) && defined (i386)))
 #undef POSIX
 #endif
 
@@ -132,7 +141,7 @@ extern char *sys_siglist[];
 #define        PATH_VAR(var)   char var[PATH_MAX]
 #else
 #define        NEED_GET_PATH_MAX
-extern unsigned int get_path_max ();
+extern unsigned int get_path_max PARAMS ((void));
 #define        GET_PATH_MAX    (get_path_max ())
 #define        PATH_VAR(var)   char *var = (char *) alloca (GET_PATH_MAX)
 #endif
@@ -153,8 +162,16 @@ extern unsigned int get_path_max ();
 #define        S_ISDIR(mode)   (((mode) & S_IFMT) == S_IFDIR)
 #endif
 
+#ifdef VMS
+#include <stdio.h>
+#include <types.h>
+#include <unixlib.h>
+#include <unixio.h>
+#include <errno.h>
+#include <perror.h>
+#endif
 
-#if    (defined (STDC_HEADERS) || defined (__GNU_LIBRARY__))
+#if    (defined (STDC_HEADERS) || defined (__GNU_LIBRARY__) || defined(VMS))
 #include <stdlib.h>
 #include <string.h>
 #define        ANSI_STRING
@@ -170,10 +187,12 @@ extern unsigned int get_path_max ();
 #include <memory.h>
 #endif
 
-extern char *malloc (), *realloc ();
-extern void free ();
+extern char *malloc PARAMS ((int));
+extern char *realloc PARAMS ((char *, int));
+extern void free PARAMS ((char *));
 
-extern void abort (), exit ();
+extern void abort PARAMS ((void));
+extern void exit PARAMS ((int));
 
 #endif /* Standard headers.  */
 
@@ -214,8 +233,8 @@ extern void bcopy ();
 /* SCO Xenix has a buggy macro definition in <string.h>.  */
 #undef strerror
 
-#ifndef ANSI_STRING
-extern char *strerror ();
+#if !defined(ANSI_STRING) && !defined(__DECC)
+extern char *strerror PARAMS ((int errnum));
 #endif
 
 
@@ -258,19 +277,30 @@ extern char *alloca ();
 #endif
 \f
 extern void die ();
-extern void message (), fatal (), error ();
+extern void message ();
+extern void fatal ();
+extern void error ();
 extern void log_working_directory ();
-extern void makefile_error (), makefile_fatal ();
-extern void pfatal_with_name (), perror_with_name ();
-extern char *savestring (), *concat ();
-extern char *xmalloc (), *xrealloc ();
-extern char *find_next_token (), *next_token (), *end_of_token ();
-extern void collapse_continuations (), remove_comments ();
-extern char *sindex (), *lindex ();
+extern void makefile_error ();
+extern void makefile_fatal ();
+extern void pfatal_with_name ();
+extern void perror_with_name ();
+extern char *savestring ();
+extern char *concat ();
+extern char *xmalloc ();
+extern char *xrealloc ();
+extern char *find_next_token ();
+extern char *next_token ();
+extern char *end_of_token ();
+extern void collapse_continuations ();
+extern void remove_comments ();
+extern char *sindex ();
+extern char *lindex ();
 extern int alpha_compare ();
 extern void print_spaces ();
 extern struct dep *copy_dep_chain ();
-extern char *find_char_unquote (), *find_percent ();
+extern char *find_char_unquote ();
+extern char *find_percent ();
 
 #ifndef        NO_ARCHIVES
 extern int ar_name ();
@@ -280,16 +310,22 @@ extern time_t ar_member_date ();
 #endif
 
 extern void dir_load ();
-extern int dir_file_exists_p (), file_exists_p (), file_impossible_p ();
+extern int dir_file_exists_p ();
+extern int file_exists_p ();
+extern int file_impossible_p ();
 extern void file_impossible ();
 extern char *dir_name ();
 
 extern void define_default_variables ();
-extern void set_default_suffixes (), install_default_suffix_rules ();
-extern void install_default_implicit_rules (), count_implicit_rule_limits ();
-extern void convert_to_pattern (), create_pattern_rule ();
-
-extern void build_vpath_lists (), construct_vpath_list ();
+extern void set_default_suffixes ();
+extern void install_default_suffix_rules ();
+extern void install_default_implicit_rules ();
+extern void count_implicit_rule_limits ();
+extern void convert_to_pattern ();
+extern void create_pattern_rule ();
+
+extern void build_vpath_lists ();
+extern void construct_vpath_list ();
 extern int vpath_search ();
 
 extern void construct_include_path ();
@@ -298,8 +334,9 @@ extern void uniquize_deps ();
 extern int update_goal_chain ();
 extern void notice_finished_file ();
 
-extern void user_access (), make_access (), child_access ();
-
+extern void user_access ();
+extern void make_access ();
+extern void child_access ();
 
 #ifdef HAVE_VFORK_H
 #include <vfork.h>
@@ -311,12 +348,17 @@ extern void user_access (), make_access (), child_access ();
 #if !defined (__GNU_LIBRARY__) && !defined (POSIX) && !defined (_POSIX_VERSION)
 
 extern long int atol ();
+#ifndef VMS
 extern long int lseek ();
+#endif
 
 #endif /* Not GNU C library or POSIX.  */
 
 #ifdef HAVE_GETCWD
 extern char *getcwd ();
+#ifdef VMS
+extern char *getwd PARAMS ((char *));
+#endif
 #else
 extern char *getwd ();
 #define        getcwd(buf, len)        getwd (buf)
@@ -349,3 +391,26 @@ extern int handling_fatal_signal;
 #define DEBUGPR(msg) \
   do if (debug_flag) { print_spaces (depth); printf (msg, file->name); \
                       fflush (stdout); } while (0)
+
+#ifdef VMS
+# ifndef EXIT_FAILURE
+#  define EXIT_FAILURE 3
+# endif
+# ifndef EXIT_SUCCESS
+#  define EXIT_SUCCESS 1
+# endif
+# ifndef EXIT_TROUBLE
+#  define EXIT_TROUBLE 2
+# endif
+#else
+# ifndef EXIT_FAILURE
+#  define EXIT_FAILURE 2
+# endif
+# ifndef EXIT_SUCCESS
+#  define EXIT_SUCCESS 0
+# endif
+# ifndef EXIT_TROUBLE
+#  define EXIT_TROUBLE 1
+# endif
+#endif
+
diff --git a/makefile.com b/makefile.com
new file mode 100644 (file)
index 0000000..cba8fda
--- /dev/null
@@ -0,0 +1,34 @@
+$!
+$! Makefile.com - builds GNU Make for VMS
+$!
+$! P1 is non-empty if you want to link with the VAXCRTL library instead
+$!    of the shareable executable
+$!
+$ def/nolog sys sys$library:
+$ filelist = "alloca commands default dir expand file function implicit job main misc read remake remote-stub rule signame variable version vmsfunctions vmsify vpath [.glob]glob [.glob]fnmatch getopt getopt1"
+$ copy config.h-vms config.h
+$ n=0
+$ loop:
+$ cfile = f$elem(n," ",filelist)
+$ if cfile .eqs. " " then goto linkit
+$ write sys$output "Compiling ''cfile'..."
+$ call compileit 'cfile' 'p1'
+$ n = n + 1
+$ goto loop
+$ linkit:
+$ if p1 .nes. "" then goto link_using_library
+$ link/exe=make alloca,commands,default,dir,expand,file,function,-
+               implicit,job,main,misc,read,remake,remote-stub,rule,-
+               signame,variable,version,vmsfunctions,vmsify,vpath,-
+               glob,fnmatch,getopt,getopt1
+$ exit
+$ link_using_library:
+$ link/exe=make alloca,commands,default,dir,expand,file,function,-
+               implicit,job,main,misc,read,remake,remote-stub,rule,-
+               signame,variable,version,vmsfunctions,vmsfiy,vpath,-
+               glob,fnmatch,getopt,getopt1,sys$library:vaxcrtl/lib
+$!
+$ compileit : subroutine
+$ cc/include=([],[.glob])/define=("allocated_variable_expand_for_file=alloc_var_expand_for_file","unlink=remove","HAVE_CONFIG_H","VMS","NO_ARCHIVES") 'p1'
+$ exit
+$ endsubroutine : compileit
diff --git a/makefile.vms b/makefile.vms
new file mode 100644 (file)
index 0000000..d98afa8
--- /dev/null
@@ -0,0 +1,121 @@
+# Copyright (C) 1988, 1989 Free Software Foundation, Inc.
+# This file is part of GNU Make.
+#
+# VMS extensions from GNU Make 3.60 imported by
+#  Klaus Kämpf (kkaempf@didymus.rmi.de)
+#
+# 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
+# the Free Software Foundation; either version 1, or (at your option)
+# any later version.
+#
+# GNU Make is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with GNU Make; see the file COPYING.  If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+CC = cc/warn
+CP = copy
+
+%.obj: %.c
+       $(CC) $(CFLAGS)/obj=$@ $<
+#
+#      Makefile for GNU Make
+#
+
+CFLAGS = $(defines) /debug/noopt/include=([],[.glob])
+#LDFLAGS = /deb
+LDFLAGS = 
+
+defines = /define=("unlink=remove","HAVE_CONFIG_H","VMS","NO_ARCHIVES","allocated_variable_expand_for_file=alloc_var_expand_for_file")
+
+LOAD_AVG = /define="NO_LDAV"
+
+# If you don't want archive support, comment these out.
+#ARCHIVES = ,ar.obj,arscan.obj
+#ARCHIVES_SRC = ar.c arscan.c
+
+# If your system needs extra libraries loaded in, define them here.
+# System V probably need -lPW for alloca.
+# if on vax, uncomment the following line
+#LOADLIBES = ,c.opt/opt
+LOADLIBES =
+
+# 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
+
+# If there are remote execution facilities defined,
+# enable them with switches here (see remote-*.c).
+REMOTE =
+
+# Any extra object files your system needs.
+extras = ,signame.obj,remote-stub.obj,vmsfunctions.obj,vmsify.obj
+#,directory.obj
+# as an alternative: 
+glob = ,[.glob]glob.obj,[.glob]fnmatch.obj
+getopt = ,getopt.obj,getopt1.obj
+# Directory to install `make' in.
+bindir = []
+# Directory to install the man page in.
+mandir = []
+# Number to put on the man page filename.
+manext = 1
+
+objs = commands.obj,job.obj,dir.obj,file.obj,misc.obj,\
+       main.obj,read.obj,remake.obj,rule.obj,implicit.obj,\
+       default.obj,variable.obj,expand.obj,function.obj,\
+       vpath.obj,version.obj$(ARCHIVES)$(ALLOCA)$(extras)$(getopt)$(glob)
+srcs = commands.c job.c dir.c file.c misc.c \
+       main.c read.c remake.c rule.c implicit.c \
+       default.c variable.c expand.c function.c \
+       vpath.c version.c vmsfunctions.c vmsify.c $(ARCHIVES_SRC) $(ALLOCASRC) \
+       commands.h dep.h filedef.h job.h make.h rule.h variable.h
+
+
+.PHONY: all doc
+all: config.h make.exe
+
+doc: make.info make.dvi
+
+
+make.exe: $(objs)
+       $(LD)$(LDFLAGS)/exe=$@ $^$(LOADLIBES)
+
+.PHONY: clean realclean
+clean:
+       -$(RM) make.exe;,*.obj;*
+
+# Automatically generated dependencies.
+commands.obj: commands.c make.h dep.h commands.h filedef.h variable.h job.h 
+job.obj: job.c make.h commands.h job.h filedef.h variable.h 
+dir.obj: dir.c make.h 
+file.obj: file.c make.h commands.h dep.h filedef.h variable.h 
+misc.obj: misc.c make.h dep.h 
+main.obj: main.c make.h commands.h dep.h filedef.h variable.h job.h 
+read.obj: read.c make.h commands.h dep.h filedef.h variable.h 
+remake.obj: remake.c make.h commands.h job.h dep.h filedef.h 
+rule.obj: rule.c make.h commands.h dep.h filedef.h variable.h rule.h 
+implicit.obj: implicit.c make.h rule.h dep.h filedef.h 
+default.obj: default.c make.h rule.h dep.h filedef.h commands.h variable.h 
+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 
+arscan.obj: arscan.c 
+ar.obj: ar.c make.h filedef.h 
+signame.obj: signame.c
+remote-stub.obj: remote-stub.c
+[.glob]glob.obj: [.glob]glob.c
+[.glob]fnmatch.obj: [.glob]fnmatch.c
+getopt.obj: getopt.c
+getopt1.obj: getopt1.c
+
+config.h: config.h-vms
+       $(CP) $< $@
diff --git a/misc.c b/misc.c
index 88dfd60..10fce3a 100644 (file)
--- a/misc.c
+++ b/misc.c
@@ -271,7 +271,9 @@ strerror (errnum)
      int errnum;
 {
   extern int errno, sys_nerr;
+#ifndef __DECC
   extern char *sys_errlist[];
+#endif
   static char buf[] = "Unknown error 12345678901234567890";
 
   if (errno < sys_nerr)
@@ -540,6 +542,7 @@ log_access (flavor)
 static void
 init_access ()
 {
+#ifndef VMS
   user_uid = getuid ();
   user_gid = getgid ();
 
@@ -553,6 +556,7 @@ init_access ()
   log_access ("Initialized");
 
   current_access = make;
+#endif
 }
 
 #endif /* GETLOADAVG_PRIVILEGED */
diff --git a/read.c b/read.c
index edbaf48..95c2169 100644 (file)
--- a/read.c
+++ b/read.c
@@ -17,9 +17,10 @@ along with GNU Make; see the file COPYING.  If not, write to
 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 #include "make.h"
-#include "commands.h"
 #include "dep.h"
-#include "file.h"
+#include "filedef.h"
+#include "job.h"
+#include "commands.h"
 #include "variable.h"
 
 /* This is POSIX.2, but most systems using -DPOSIX probably don't have it.  */
@@ -29,15 +30,11 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "glob/glob.h"
 #endif
 
+#ifndef VMS
 #include <pwd.h>
-struct passwd *getpwnam ();
-
-
-static int read_makefile ();
-static unsigned int readline (), do_define ();
-static int conditional_line ();
-static void record_files ();
-
+#else
+struct passwd *getpwnam PARAMS ((char *name));
+#endif
 
 /* A `struct linebuffer' is a structure which holds a line of text.
    `readline' reads a line from a stream into a linebuffer
@@ -104,6 +101,18 @@ unsigned int *reading_lineno_ptr;
 /* The chain of makefiles read by read_makefile.  */
 
 static struct dep *read_makefiles = 0;
+
+static int read_makefile PARAMS ((char *filename, int flags));
+static unsigned int readline PARAMS ((struct linebuffer *linebuffer, FILE *stream,
+                       char *filename, unsigned int lineno));
+static unsigned int do_define PARAMS ((char *name, unsigned int namelen, enum variable_origin origin,
+                       unsigned int lineno, FILE *infile, char *filename));
+static int conditional_line PARAMS ((char *line, char *filename, unsigned int lineno));
+static void record_files PARAMS ((struct nameseq *filenames, char *pattern, char *pattern_percent,
+                       struct dep *deps, unsigned int commands_started, char *commands,
+                       unsigned int commands_idx, int two_colon, char *filename,
+                       unsigned int lineno, int set_default));
+static char *find_semicolon PARAMS  ((char *s));
 \f
 /* Read in all the makefiles and return the chain of their names.  */
 
@@ -138,6 +147,7 @@ read_all_makefiles (makefiles)
     /* Set NAME to the start of next token and LENGTH to its length.
        MAKEFILES is updated for finding remaining tokens.  */
     p = value;
+
     while ((name = find_next_token (&p, &length)) != 0)
       {
        if (*p != '\0')
@@ -176,7 +186,12 @@ read_all_makefiles (makefiles)
   if (num_makefiles == 0)
     {
       static char *default_makefiles[] =
+#if VMS
+       /* all lower case since readdir() (the vms version) 'lowercasifies' */
+       { "makefile.vms", "gnumakefile", "makefile", 0 };
+#else
        { "GNUmakefile", "makefile", "Makefile", 0 };
+#endif
       register char **p = default_makefiles;
       while (*p != 0 && !file_exists_p (*p))
        ++p;
@@ -302,7 +317,6 @@ read_makefile (filename, flags)
   /* If the makefile wasn't found and it's either a makefile from
      the `MAKEFILES' variable or an included makefile,
      search the included makefile search path for this makefile.  */
-
   if (infile == 0 && (flags & RM_INCLUDED) && *filename != '/')
     {
       register unsigned int i;
@@ -586,7 +600,7 @@ read_makefile (filename, flags)
            {
              struct nameseq *next = files->next;
              char *name = files->name;
-             free (files);
+             free ((char *)files);
              files = next;
 
              if (! read_makefile (name, (RM_INCLUDED | RM_NO_TILDE
@@ -1303,7 +1317,7 @@ record_files (filenames, pattern, pattern_percent, deps, commands_started,
                {
                  struct dep *nextd = d->next;
                  free (d->name);
-                 free (d);
+                 free ((char *)d);
                  d = nextd;
                }
              f->deps = 0;
@@ -1520,9 +1534,16 @@ parse_file_seq (stringp, stopchar, size, strip)
   register char *p = *stringp;
   char *q;
   char *name;
-  char stopchars[2];
+  char stopchars[3];
+
+#ifdef VMS
+  stopchars[0] = ',';
+  stopchars[1] = stopchar;
+  stopchars[2] = '\0';
+#else
   stopchars[0] = stopchar;
   stopchars[1] = '\0';
+#endif
 
   while (1)
     {
@@ -1532,9 +1553,16 @@ parse_file_seq (stringp, stopchar, size, strip)
        break;
       if (*p == stopchar)
        break;
+
       /* Yes, find end of next name.  */
       q = p;
       p = find_char_unquote (q, stopchars, 1);
+#ifdef VMS
+       /* convert comma separated list to space separated */
+      if (p && *p == ',')
+       *p =' ';
+#endif
+
 #ifdef __MSDOS__
       /* For MS-DOS, skip a "C:\...".  */
       if (stopchar == ':' && p != 0 && p[1] == '\\' && isalpha (p[-1]))
@@ -1544,8 +1572,13 @@ parse_file_seq (stringp, stopchar, size, strip)
        p = q + strlen (q);
 
       if (strip)
+#ifdef VMS
+       /* Skip leading `[]'s.  */
+       while (p - q > 2 && q[0] == '[' && q[1] == ']')
+#else
        /* Skip leading `./'s.  */
        while (p - q > 2 && q[0] == '.' && q[1] == '/')
+#endif
          {
            q += 2;             /* Skip "./".  */
            while (q < p && *q == '/')
@@ -1556,10 +1589,40 @@ parse_file_seq (stringp, stopchar, size, strip)
       /* Extract the filename just found, and skip it.  */
 
       if (q == p)
-       /* ".///" was stripped to "".  */
+       /* ".///" was stripped to "". */
+#ifdef VMS
+       continue;
+#else
        name = savestring ("./", 2);
+#endif
       else
+#ifdef VMS
+/* VMS filenames can have a ':' in them but they have to be '\'ed but we need
+ *  to remove this '\' before we can use the filename.
+ * Savestring called because q may be read-only string constant.
+ */
+       {
+         char *qbase = savestring(q, strlen(q));
+         char *pbase = qbase + (p-q);
+         char *q1 = qbase;
+         char *q2 = q1;
+         char *p1 = pbase;
+
+         while (q1 != pbase)
+           {
+             if (*q1 == '\\' && *(q1+1) == ':')
+               {
+                 q1++;
+                 p1--;
+               }
+             *q2++ = *q1++; 
+           }
+         name = savestring (qbase, p1 - qbase);
+         free (qbase);
+       }
+#else
        name = savestring (q, p - q);
+#endif
 
       /* Add it to the front of the chain.  */
       new1 = (struct nameseq *) xmalloc (size);
@@ -1787,8 +1850,11 @@ construct_include_path (arg_dirs)
      char **arg_dirs;
 {
   register unsigned int i;
+#ifdef VAXC            /* just don't ask ... */
+  stat_t stbuf;
+#else
   struct stat stbuf;
-
+#endif
   /* Table to hold the dirs.  */
 
   register unsigned int defsize = (sizeof (default_include_directories)
@@ -1860,6 +1926,7 @@ char *
 tilde_expand (name)
      char *name;
 {
+#ifndef VMS
   if (name[1] == '/' || name[1] == '\0')
     {
       extern char *getenv ();
@@ -1919,7 +1986,7 @@ tilde_expand (name)
       else if (userend != 0)
        *userend = '/';
     }
-
+#endif /* !VMS */
   return 0;
 }
 
@@ -2037,7 +2104,7 @@ multi_glob (chain, size)
              }
            globfree (&gl);
            free (old->name);
-           free (old);
+           free ((char *)old);
            break;
          }
 
diff --git a/readme.vms b/readme.vms
new file mode 100644 (file)
index 0000000..f54be73
--- /dev/null
@@ -0,0 +1,62 @@
+This is the VMS port of GNU Make version 3.74.
+
+It is based on the VMS port of GNU Make 3.60 by Mike Moretti.
+
+This port was done by Klaus Kämpf (kkaempf@didymus.rmi.de)
+
+To build Make, simply type @makefile.  This should compile all the
+necessary files and link Make.
+There is also a file called makefile.vms.  If you already have GNU
+Make 3.74 built you can just use Make with this makefile to rebuild.
+
+Here are some notes about GNU Make for VMS:
+
+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).
+
+See defaults.c for VMS default suffixes and my definitions for default
+rules and variables.
+
+The shell function is not implemented yet.
+
+Load average routines haven't been implemented for VMS yet.
+
+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 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
+somewhere in the future. Be warned, the time resolution inside make is
+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]
+
+None of the stuff in vpath.c has been implemented yet.
+
+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.
+
+Multiple line DCL commands, such as "if" statements, must be put inside
+command files.  You can run a command file by using \@.
+
+
+VMS changes made for 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.
+
index 7245531..befb7ad 100644 (file)
--- a/remake.c
+++ b/remake.c
@@ -17,10 +17,10 @@ along with GNU Make; see the file COPYING.  If not, write to
 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 #include "make.h"
-#include "commands.h"
+#include "filedef.h"
 #include "job.h"
+#include "commands.h"
 #include "dep.h"
-#include "file.h"
 #include <assert.h>
 
 #ifdef HAVE_FCNTL_H
@@ -29,17 +29,30 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include <sys/file.h>
 #endif
 
-extern int try_implicit_rule ();
+#ifdef VMS
+#include <starlet.h>
+#endif
+
+extern int try_implicit_rule PARAMS ((struct file *file, unsigned int depth));
 
 
 /* Incremented when a command is started (under -n, when one would be).  */
 unsigned int commands_started = 0;
 
-static int update_file (), update_file_1 (), check_dep (), touch_file ();
-static void remake_file ();
-static time_t name_mtime ();
-static int library_search ();
-extern time_t f_mtime ();
+static int update_file PARAMS ((struct file *file, unsigned int depth));
+static int update_file_1 PARAMS ((struct file *file, unsigned int depth));
+static int check_dep PARAMS ((struct file *file, unsigned int depth, time_t this_mtime, int *must_make_ptr));
+static int touch_file PARAMS ((struct file *file));
+static void remake_file PARAMS ((struct file *file));
+static time_t name_mtime PARAMS ((char *name));
+static int library_search PARAMS ((char **lib, time_t *mtime_ptr));
+
+extern time_t f_mtime PARAMS ((struct file *file, int search));
+
+#ifdef VMS
+extern int vms_stat PARAMS ((char *name, struct stat *buf));
+#endif
+
 \f
 /* Remake all the goals in the `struct dep' chain GOALS.  Return -1 if nothing
    was done, 0 if all goals were updated successfully, or 1 if a goal failed.
@@ -100,6 +113,7 @@ update_goal_chain (goals, makefiles)
          /* Iterate over all double-colon entries for this file.  */
          struct file *file = g->file;
          int stop, any_not_updated = 0;
+
          for (file = g->file->double_colon ? g->file->double_colon : g->file;
               file != NULL;
               file = file->prev)
@@ -108,7 +122,6 @@ update_goal_chain (goals, makefiles)
              int x;
              time_t mtime = MTIME (file);
              check_renamed (file);
-
              if (makefiles)
                {
                  if (file->cmd_target)
@@ -229,7 +242,6 @@ update_goal_chain (goals, makefiles)
       just_print_flag = n;
       job_slots = j;
     }
-
   return status;
 }
 \f
@@ -1015,12 +1027,28 @@ f_mtime (file, search)
        unrecoverably absent.  */
 
     static time_t now;
+#ifdef VMS
+    /* Handle vms 64bit to 32bit time hack introduced in vms_stat() ... */
+    static unsigned long vms_now[2]; /* assumes 32 bit long ! */
+    static int vms_now_set = 0;
+
+    if (!vms_now_set)
+      {
+       sys$gettim(vms_now);
+       now = ((vms_now[0]>>24) & 0xff) + ((vms_now[1]<<8) & 0xffffff00);
+       vms_now_set = 1;
+      }
+#endif
     if (mtime > now && ! file->updated)
       {
        /* This file's time appears to be in the future.
           Update our concept of the present, and compare again.  */
+#ifndef VMS
        extern time_t time ();
        if (mtime > time (&now))
+#else
+       if ((mtime != -1) && (mtime > now))
+#endif
          {
            error ("*** File `%s' has modification time in the future",
                   file->name);
@@ -1050,7 +1078,11 @@ name_mtime (name)
 {
   struct stat st;
 
+#ifdef VMS
+  if (vms_stat (name, &st) < 0)
+#else
   if (stat (name, &st) < 0)
+#endif
     return (time_t) -1;
 
   return (time_t) st.st_mtime;
index 24a860b..439c35e 100644 (file)
@@ -17,6 +17,8 @@ along with GNU Make; see the file COPYING.  If not, write to
 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 #include "make.h"
+#include "filedef.h"
+#include "job.h"
 #include "commands.h"
 
 
diff --git a/rule.c b/rule.c
index b69212d..d38cf54 100644 (file)
--- a/rule.c
+++ b/rule.c
@@ -17,13 +17,14 @@ along with GNU Make; see the file COPYING.  If not, write to
 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 #include "make.h"
-#include "commands.h"
 #include "dep.h"
-#include "file.h"
+#include "filedef.h"
+#include "job.h"
+#include "commands.h"
 #include "variable.h"
 #include "rule.h"
 
-static void freerule ();
+static void freerule PARAMS ((struct rule *rule, struct rule *lastrule));
 \f
 /* Chain of all pattern rules.  */
 
@@ -96,9 +97,13 @@ count_implicit_rule_limits ()
       for (dep = rule->deps; dep != 0; dep = dep->next)
        {
          unsigned int len = strlen (dep->name);
+
+#ifdef VMS
+         char *p = rindex (dep->name, ']');
+#else
          char *p = rindex (dep->name, '/');
+#endif
          char *p2 = p != 0 ? index (dep->name, '%') : 0;
-
          ndeps++;
 
          if (len > max_pattern_dep_length)
@@ -125,7 +130,11 @@ count_implicit_rule_limits ()
                 nonexistent subdirectory.  */
 
              dep->changed = !dir_file_exists_p (name, "");
+#ifdef VMS
+             if (dep->changed && *name == ']')
+#else
              if (dep->changed && *name == '/')
+#endif
                {
                  /* The name is absolute and the directory does not exist.
                     This rule can never possibly match, since this dependency
@@ -173,7 +182,11 @@ convert_suffix_rule (target, source, cmds)
     /* Special case: TARGET being nil means we are defining a
        `.X.a' suffix rule; the target pattern is always `(%.o)'.  */
     {
+#ifdef VMS
+      targname = savestring ("(%.obj)", 7);
+#else
       targname = savestring ("(%.o)", 5);
+#endif
       targpercent = targname + 1;
     }
   else
diff --git a/rule.h b/rule.h
index 75d43d6..9c6b1b0 100644 (file)
--- a/rule.h
+++ b/rule.h
@@ -49,5 +49,5 @@ extern struct file *suffix_file;
 extern unsigned int maxsuffix;
 
 
-extern void install_pattern_rule ();
-int new_pattern_rule ();
+extern void install_pattern_rule PARAMS ((struct pspec *p, int terminal));
+extern int new_pattern_rule PARAMS ((struct rule *rule, int override));
index 319826f..a414516 100644 (file)
@@ -17,10 +17,11 @@ along with GNU Make; see the file COPYING.  If not, write to
 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 #include "make.h"
+#include "dep.h"
+#include "filedef.h"
+#include "job.h"
 #include "commands.h"
 #include "variable.h"
-#include "dep.h"
-#include "file.h"
 
 /* Hash table of all global variable definitions.  */
 
@@ -39,6 +40,11 @@ static struct variable_set global_variable_set
 static struct variable_set_list global_setlist
   = { 0, &global_variable_set };
 struct variable_set_list *current_variable_set_list = &global_setlist;
+
+static struct variable *define_variable_in_set PARAMS ((char *name, unsigned int length,
+                                                       char *value, enum variable_origin origin,
+                                                       int recursive, struct variable_set *set));
+
 \f
 /* Implement variables.  */
 
index 8096179..79d9739 100644 (file)
@@ -70,31 +70,40 @@ struct variable_set_list
 
 extern struct variable_set_list *current_variable_set_list;
 
-
-extern void push_new_variable_scope (), pop_variable_scope ();
-
-extern int handle_function ();
-
-extern char *variable_buffer_output ();
-extern char *variable_expand (), *variable_expand_for_file ();
-extern char *allocated_variable_expand_for_file ();
+/* expand.c */
+extern char *variable_buffer_output PARAMS ((char *ptr, char *string, unsigned int length));
+extern char *variable_expand PARAMS ((char *line));
+extern char *variable_expand_for_file PARAMS ((char *line, struct file *file));
+extern char *allocated_variable_expand_for_file PARAMS ((char *line, struct file *file));
 #define        allocated_variable_expand(line) \
   allocated_variable_expand_for_file (line, (struct file *) 0)
-extern char *expand_argument ();
-
-extern void define_automatic_variables ();
-extern void initialize_file_variables ();
-extern void print_file_variables ();
-
-extern void merge_variable_set_lists ();
-
-extern struct variable *try_variable_definition ();
-
-extern struct variable *lookup_variable (), *define_variable ();
-extern struct variable *define_variable_for_file ();
-
-extern int pattern_matches ();
-extern char *subst_expand (), *patsubst_expand (), *recursively_expand ();
+extern char *expand_argument PARAMS ((char *str, char *end));
+
+/* function.c */
+extern int handle_function PARAMS ((char **op, char **stringp));
+extern int pattern_matches PARAMS ((char *pattern, char *percent, char *word));
+extern char *subst_expand PARAMS ((char *o, char *text, char *subst, char *replace,
+               unsigned int slen, unsigned int rlen, int by_word, int suffix_only));
+extern char *patsubst_expand PARAMS ((char *o, char *text, char *pattern, char *replace,
+               char *pattern_percent, char *replace_percent));
+
+/* expand.c */
+extern char *recursively_expand PARAMS ((struct variable *v));
+
+/* variable.c */
+extern void push_new_variable_scope PARAMS ((void));
+extern void pop_variable_scope PARAMS ((void));
+extern void define_automatic_variables PARAMS ((void));
+extern void initialize_file_variables PARAMS ((struct file *file));
+extern void print_file_variables PARAMS ((struct file *file));
+extern void merge_variable_set_lists PARAMS ((struct variable_set_list **setlist0, struct variable_set_list *setlist1));
+extern struct variable *try_variable_definition PARAMS ((char *filename, unsigned int lineno, char *line, enum variable_origin origin));
+
+extern struct variable *lookup_variable PARAMS ((char *name, unsigned int length));
+extern struct variable *define_variable PARAMS ((char *name, unsigned int length, char *value,
+               enum variable_origin origin, int recursive));
+extern struct variable *define_variable_for_file PARAMS ((char *name, unsigned int length,
+               char *value, enum variable_origin origin, int recursive, struct file *file));
+extern char **target_environment PARAMS ((struct file *file));
 
-extern char **target_environment ();
 extern int export_all_variables;
diff --git a/vmsdir.h b/vmsdir.h
new file mode 100644 (file)
index 0000000..50b50e8
--- /dev/null
+++ b/vmsdir.h
@@ -0,0 +1,40 @@
+/* dirent.h for vms */
+
+#include <rms.h>
+
+#define        MAXNAMLEN       255
+
+typedef unsigned long u_long;
+typedef unsigned short u_short;
+
+struct direct {
+  off_t d_off;
+  u_long d_fileno;
+  u_short d_reclen;
+  u_short d_namlen;
+  char d_name[MAXNAMLEN + 1];
+};
+
+#undef DIRSIZ
+#define DIRSIZ(dp)  \
+       (((sizeof (struct direct) - (MAXNAMLEN+1) + ((dp)->d_namlen+1)) + 3) & ~3)
+
+#define d_ino  d_fileno                /* compatability */
+
+
+/*
+ * Definitions for library routines operating on directories.
+ */
+
+typedef struct FAB 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 */
diff --git a/vmsfunctions.c b/vmsfunctions.c
new file mode 100644 (file)
index 0000000..a76609c
--- /dev/null
@@ -0,0 +1,234 @@
+#define KDEBUG 0
+/* vmsfunctions.c */
+
+#include <stdio.h>
+#include "make.h"
+#ifdef __DECC
+#include <starlet.h>
+#endif
+#include <descrip.h>
+#include <rms.h>
+#include <iodef.h>
+#include <atrdef.h>
+#include <fibdef.h>
+#include "vmsdir.h"
+
+DIR *opendir(char *dspec)
+{
+  static struct FAB *dfab;
+  struct NAM *dnam;
+  char *searchspec;
+
+  if ((dfab = (struct FAB *)xmalloc(sizeof (struct FAB))) == NULL) {
+    printf("Error mallocing for FAB\n");
+    return(NULL);
+  }
+  if ((dnam = (struct NAM *)xmalloc(sizeof (struct NAM))) == NULL) {
+    printf("Error mallocing for NAM\n");
+    free(dfab);
+    return(NULL);
+  }
+  if ((searchspec = (char *)xmalloc(MAXNAMLEN+1)) == NULL) {
+    printf("Error mallocing for searchspec\n");
+    free(dfab);
+    free(dnam);
+    return(NULL);
+  }
+
+  sprintf(searchspec,"%s*.*;",dspec);
+
+  *dfab = cc$rms_fab;
+  dfab->fab$l_fna = searchspec;
+  dfab->fab$b_fns = strlen(searchspec);
+  dfab->fab$l_nam = dnam;
+
+  *dnam = cc$rms_nam;
+  dnam->nam$l_esa = searchspec;
+  dnam->nam$b_ess = MAXNAMLEN;
+
+  if (!(sys$parse(dfab) & 1)) {
+    free(dfab);
+    free(dnam);
+    free(searchspec);
+    return(NULL);
+  }
+
+  return(dfab);
+}
+
+#include <ctype.h>
+#define uppercasify(str) { char *tmp; for(tmp = (str); *tmp != '\0'; tmp++) if(islower(*tmp)) *tmp = toupper(*tmp); }
+
+struct direct *readdir(DIR *dfd)
+{
+  static struct direct *dentry;
+  static char resultspec[MAXNAMLEN+1];
+  int i;
+
+  if ((dentry = (struct direct *)xmalloc(sizeof (struct direct))) == NULL) {
+    printf("Error mallocing for direct\n");
+    return(NULL);
+  }
+
+  dfd->fab$l_nam->nam$l_rsa = resultspec;
+  dfd->fab$l_nam->nam$b_rss = MAXNAMLEN;
+
+  if (debug_flag)
+    printf(".");
+
+  if (!((i = sys$search(dfd)) & 1)) {
+    if (debug_flag)
+      printf("sys$search failed with %d\n", i);
+    free(dentry);
+    return(NULL);
+  }
+
+  dentry->d_off = 0;
+  if (dfd->fab$l_nam->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_reclen = sizeof (struct direct);
+/*
+  if (!strcmp(dfd->fab$l_nam->nam$l_type,".DIR"))
+    dentry->d_namlen = dfd->fab$l_nam->nam$b_name;
+  else
+*/
+    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_name[dentry->d_namlen] = '\0';
+  uppercasify(dentry->d_name);
+/*  uvUnFixRCSSeparator(dentry->d_name);*/
+
+  return(dentry);
+}
+
+closedir(DIR *dfd)
+{
+  if (dfd != NULL) {
+    if (dfd->fab$l_nam != NULL)
+      free(dfd->fab$l_nam->nam$l_esa);
+    free(dfd->fab$l_nam);
+    free(dfd);
+  }
+}
+
+char *getwd(char *cwd)
+{
+  static char buf[512];
+
+    if (cwd)
+      return(getcwd(cwd,512));
+    else
+      return(getcwd(buf,512));
+}
+
+int
+vms_stat (name, buf)
+     char *name;
+     struct stat *buf;
+{
+  int status;
+  int i;
+
+  static struct FAB Fab;
+  static struct NAM Nam;
+  static struct fibdef Fib; /* short fib */
+  static struct dsc$descriptor FibDesc =
+    {sizeof(Fib), DSC$K_DTYPE_Z, DSC$K_CLASS_S, (char *)&Fib};
+  static struct dsc$descriptor_s DevDesc =
+    {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, &Nam.nam$t_dvi[1]};
+  static char EName[NAM$C_MAXRSS];
+  static char RName[NAM$C_MAXRSS];
+  static struct dsc$descriptor_s FileName =
+    {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0};
+  static struct dsc$descriptor_s string =
+    {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0};  
+  static unsigned long Rdate[2];
+  static unsigned long Cdate[2];
+  static struct atrdef Atr[] = {  
+    {sizeof(Rdate),ATR$C_REVDATE,&Rdate[0]}, /* Revision date */
+    {sizeof(Cdate),ATR$C_CREDATE,&Cdate[0]}, /* Creation date */
+    {0,0,0}
+  };
+  static short int DevChan;
+  static short int iosb[4];
+
+  name = vmsify (name, 0);
+
+  /* initialize RMS structures, we need a NAM to retrieve the FID */
+  Fab = cc$rms_fab;
+  Fab.fab$l_fna = name ; /* name of file */
+  Fab.fab$b_fns = strlen(name);
+  Fab.fab$l_nam = &Nam; /* FAB has an associated NAM */
+      
+  Nam = cc$rms_nam;
+  Nam.nam$l_esa = EName; /* expanded filename */
+  Nam.nam$b_ess = sizeof(EName);
+  Nam.nam$l_rsa = RName; /* resultant filename */
+  Nam.nam$b_rss = sizeof(RName);
+
+  /* do $PARSE and $SEARCH here */
+  status = sys$parse(&Fab);
+  if (!(status & 1))
+    return -1;
+
+  DevDesc.dsc$w_length = Nam.nam$t_dvi[0];
+  status = sys$assign(&DevDesc,&DevChan,0,0);
+  if (!(status & 1))
+    return -1;
+
+  FileName.dsc$a_pointer = Nam.nam$l_name;
+  FileName.dsc$w_length = Nam.nam$b_name+Nam.nam$b_type+Nam.nam$b_ver;
+  
+  /* Initialize the FIB */
+  for (i=0;i<3;i++)
+    {
+#if __DECC
+      Fib.fib$w_fid[i]=Nam.nam$w_fid[i];
+      Fib.fib$w_did[i]=Nam.nam$w_did[i];
+#else
+      Fib.fib$r_fid_overlay.fib$w_fid[i]=Nam.nam$w_fid[i];
+      Fib.fib$r_did_overlay.fib$w_did[i]=Nam.nam$w_did[i];
+#endif
+    }
+
+  status = sys$qiow(0,DevChan,IO$_ACCESS,&iosb,0,0,
+                        &FibDesc,&FileName,0,0,&Atr,0);
+  if (!(status & 1))
+    return -1;
+  status = iosb[0];
+  if (!(status & 1))
+    return -1;
+
+  status = stat (name, buf);
+  if (status)
+    return -1;
+
+  buf->st_mtime = ((Rdate[0]>>24) & 0xff) + ((Rdate[1]<<8) & 0xffffff00);
+  buf->st_ctime = ((Cdate[0]>>24) & 0xff) + ((Cdate[1]<<8) & 0xffffff00);
+  return 0;
+}
+
+char *
+cvt_time(tval)
+  unsigned long tval;
+{
+  static long int date[2];
+  static char str[27];
+  static struct dsc$descriptor date_str =
+    {26, DSC$K_DTYPE_T, DSC$K_CLASS_S, str};
+
+  date[0] = (tval & 0xff) << 24;
+  date[1] = ((tval>>8) & 0xffffff);
+
+  if ((date[0]==0) && (date[1]==0))
+    return("never");
+  sys$asctim(0,&date_str,date,0);
+  str[26]='\0';
+
+  return(str);
+}
+  
+/* EOF */
diff --git a/vmsify.c b/vmsify.c
new file mode 100644 (file)
index 0000000..7d1fa6f
--- /dev/null
+++ b/vmsify.c
@@ -0,0 +1,925 @@
+/*
+  vmsify.c
+
+  Module for vms <-> unix file name conversion
+
+  Written by Klaus Kämpf (kkaempf@didymus.rmi.de)
+
+*/
+
+#include <string.h>
+#include <ctype.h>
+
+#if VMS
+#include <unixlib.h>
+#include <stdlib.h>
+#include <jpidef.h>
+#include <descrip.h>
+#include <uaidef.h>
+#include <ssdef.h>
+#include <starlet.h>
+#include <lib$routines.h>
+/* Initialize a string descriptor (struct dsc$descriptor_s) for an
+   arbitrary string.   ADDR is a pointer to the first character
+   of the string, and LEN is the length of the string. */
+
+#define INIT_DSC_S(dsc, addr, len) do { \
+  (dsc).dsc$b_dtype = DSC$K_DTYPE_T;    \
+  (dsc).dsc$b_class = DSC$K_CLASS_S;    \
+  (dsc).dsc$w_length = (len);           \
+  (dsc).dsc$a_pointer = (addr);         \
+} while (0)
+
+/* Initialize a string descriptor (struct dsc$descriptor_s) for a
+   NUL-terminated string.  S is a pointer to the string; the length
+   is determined by calling strlen(). */
+
+#define INIT_DSC_CSTRING(dsc, s) INIT_DSC_S(dsc, s, strlen(s))
+#endif
+
+/*
+  copy 'from' to 'to' up to but not including 'upto'
+  return 0 if eos on from
+  return 1 if upto found
+
+  return 'to' at last char + 1
+  return 'from' at match + 1 or eos if no match
+
+  if as_dir == 1, change all '.' to '_'
+  else change all '.' but the last to '_'
+*/
+
+static int
+copyto (char **to, char **from, char upto, int as_dir)
+{
+  char *s;
+
+  s = strrchr (*from, '.');
+
+  while (**from)
+    {
+      if (**from == upto)
+       {
+         do
+           {
+             (*from)++;
+           }
+         while (**from == upto);
+         return 1;
+       }
+      if (**from == '.')
+       {
+         if ((as_dir == 1)
+             || (*from != s))
+           **to = '_';
+         else
+           **to = '.';
+       }
+      else
+       {
+         if (islower (**from))
+           **to = toupper (**from);
+         else
+           **to = **from;
+       }
+      (*to)++;
+      (*from)++;
+    }
+
+  return 0;
+}
+
+
+/*
+  get translation of logical name
+
+*/
+
+static char *
+trnlog (char *name)
+{
+  int stat;
+  static char reslt[1024];
+  $DESCRIPTOR (reslt_dsc, reslt);
+  short resltlen;
+  struct dsc$descriptor_s name_dsc;
+  char *s;
+
+  INIT_DSC_CSTRING (name_dsc, name);
+
+  stat = lib$sys_trnlog (&name_dsc, &resltlen, &reslt_dsc);
+
+  if ((stat&1) == 0)
+    {
+      return "";
+    }
+  if (stat == SS$_NOTRAN)
+    {
+      return "";
+    }
+  reslt[resltlen] = '\0';
+
+  s = (char *)malloc (resltlen+1);
+  if (s == 0)
+    return "";
+  strcpy (s, reslt);
+  return s;
+}
+
+enum namestate { N_START, N_DEVICE, N_OPEN, N_DOT, N_CLOSED, N_DONE };
+
+/*
+  convert unix style name to vms style
+  type = 0 -> name is a full name (directory and filename part)
+  type = 1 -> name is a directory
+  type = 2 -> name is a filename without directory
+
+  The following conversions are applied
+                       (0)             (1)                     (2)
+       input           full name       dir name                file name
+
+1      ./              <cwd>           []                      <current directory>.dir
+2      ../             <home of cwd>   <home of cwd>           <home of cwd>.dir
+
+3      //              <dev of cwd>:   <dev of cwd>:[000000]   <dev of cwd>:000000.dir
+4      //a             a:              a:                      a:
+5      //a/            a:              a:                      a:000000.dir
+
+9      /               [000000]        [000000]                000000.dir
+10     /a              [000000]a       [a]                     [000000]a
+11     /a/             [a]             [a]                     [000000]a.dir
+12     /a/b            [a]b            [a.b]                   [a]b
+13     /a/b/           [a.b]           [a.b]                   [a]b.dir
+14     /a/b/c          [a.b]c          [a.b.c]                 [a.b]c
+15     /a/b/c/         [a.b.c]         [a.b.c]                 [a.b]c.dir
+
+16     a               a               [.a]                    a
+17     a/              [.a]            [.a]                    a.dir
+18     a/b             [.a]b           [.a.b]                  [.a]b
+19     a/b/            [.a.b]          [.a.b]                  [.a]b.dir
+20     a/b/c           [.a.b]c         [.a.b.c]                [.a.b]c
+21     a/b/c/          [.a.b.c]        [.a.b.c]                [.a.b]c.dir
+
+22     a.b.c           a_b.c           [.a_b_c]                a_b_c.dir
+
+23     [x][y]z         [x.y]z          [x.y]z                  [x.y]z
+24     [x][.y]z        [x.y]z          [x.y]z                  [x.y]z
+
+25  filenames with '$'  are left unchanged if they contain no '/'
+25  filenames with ':' are left unchanged
+26  filenames with a single pair of '[' ']' are left unchanged
+
+  the input string is not written to
+*/
+
+char *
+vmsify (name, type)
+    char *name;
+    int type;
+{
+/* max 255 device
+   max 39 directory
+   max 39 filename
+   max 39 filetype
+   max 5 version
+*/
+#define MAXPATHLEN 512
+
+  enum namestate nstate;
+  static char vmsname[MAXPATHLEN+1];
+  char *fptr;
+  char *vptr;
+  char *s,*s1;
+  int as_dir;
+  int count;
+
+  if (name == 0)
+    return 0;
+  fptr = name;
+  vptr = vmsname;
+  nstate = N_START;
+
+  /* case 25a */
+
+  s = strpbrk (name, "$:");
+  if (s != 0)
+    {
+      if (*s == '$')
+       {
+         if (strchr (name, '/') == 0)
+           {
+             return name;
+           }
+       }
+      else
+       {
+         return name;
+       }
+    }
+
+  /* case 26 */
+
+  s = strchr (name, '[');
+
+  if (s != 0)
+    {
+      s1 = strchr (s+1, '[');
+      if (s1 == 0)
+       {
+         return name;                  /* single [, keep unchanged */
+       }
+      s1--;
+      if (*s1 != ']')
+       {
+         return name;                  /* not ][, keep unchanged */
+       }
+
+      /* we have ][ */
+
+      s = name;
+
+      /* s  -> starting char
+        s1 -> ending ']'  */
+
+      do
+       {
+         strncpy (vptr, s, s1-s);      /* copy up to but not including ']' */
+         vptr += s1-s;
+         if (*s1 == 0)
+           break;
+         s = s1 + 1;                   /* s -> char behind ']' */
+         if (*s != '[')                /* was '][' ? */
+           break;                      /* no, last ] found, exit */
+         s++;
+         if (*s != '.')
+           *vptr++ = '.';
+         s1 = strchr (s, ']');
+         if (s1 == 0)                  /* no closing ] */
+           s1 = s + strlen (s);
+       }
+      while (1);
+
+      *vptr++ = ']';
+
+      fptr = s;
+
+    }
+
+  else         /* no [ in name */
+
+    {
+
+      int state;
+      int rooted = 1;  /* flag if logical is rooted, else insert [000000] */
+
+      state = 0;
+
+      do
+       {
+
+      switch (state)
+       {
+         case 0:                               /* start of loop */
+           if (*fptr == '/')
+             {
+               fptr++;
+               state = 1;
+             }
+           else if (*fptr == '.')
+             {
+               fptr++;
+               state = 10;
+             }
+           else
+             state = 2;
+           break;
+
+         case 1:                               /* '/' at start */
+           if (*fptr == '/')
+             {
+               fptr++;
+               state = 3;
+             }
+           else
+             state = 4;
+           break;
+
+         case 2:                               /* no '/' at start */
+           s = strchr (fptr, '/');
+           if (s == 0)                 /* no '/' (16) */
+             {
+               if (type == 1)
+                 {
+                   strcpy (vptr, "[.");
+                   vptr += 2;
+                 }
+               copyto (&vptr, &fptr, 0, (type==1));
+               if (type == 1)
+                 *vptr++ = ']';
+               state = -1;
+             }
+           else                        /* found '/' (17..21) */
+             {
+               if ((type == 2)
+                   && (*(s+1) == 0))   /* 17(2) */
+                 {
+                   copyto (&vptr, &fptr, '/', 1);
+                   state = 7;
+                 }
+               else
+                 {
+                   strcpy (vptr, "[.");
+                   nstate = N_DOT;
+                   vptr += 2;
+                   copyto (&vptr, &fptr, '/', 1);
+                   state = 9;
+                 }
+             }
+           break;
+
+         case 3:                               /* '//' at start */
+           while (*fptr == '/')        /* collapse all '/' */
+             fptr++;
+           if (*fptr == 0)             /* just // */
+             {
+               char cwdbuf[MAXPATHLEN+1];
+
+               s1 = getcwd(cwdbuf, MAXPATHLEN);
+               if (s1 == 0)
+                 {
+                   return "";          /* FIXME, err getcwd */
+                 }
+               s = strchr (s1, ':');
+               if (s == 0)
+                 {
+                   return "";          /* FIXME, err no device */
+                 }
+               strncpy (vptr, s1, s-s1+1);
+               vptr += s-s1+1;
+               state = -1;
+               break;
+             }
+
+           s = vptr;
+
+           if (copyto (&vptr, &fptr, '/', 1) == 0)     /* copy device part */
+             {
+               *vptr++ = ':';
+               state = -1;
+               break;
+             }
+           *vptr = ':';
+           nstate = N_DEVICE;
+           if (*fptr == 0)     /* just '//a/' */
+             {
+               strcpy (vptr+1, "[000000]");
+               vptr += 9;
+               state = -1;
+               break;
+             }
+           *vptr = 0;
+                               /* check logical for [000000] insertion */
+           s1 = trnlog (s);
+           if (*s1 != 0)
+             {                 /* found translation */
+               char *s2;
+               for (;;)        /* loop over all nested logicals */
+                 {
+                   s2 = s1 + strlen (s1) - 1;
+                   if (*s2 == ':')     /* translation ends in ':' */
+                     {
+                       s2 = trnlog (s1);
+                       free (s1);
+                       if (*s2 == 0)
+                         {
+                           rooted = 0;
+                           break;
+                         }
+                       s1 = s2;
+                       continue;       /* next iteration */
+                     }
+                   if (*s2 == ']')     /* translation ends in ']' */
+                     {
+                       if (*(s2-1) == '.')     /* ends in '.]' */
+                         {
+                           if (strncmp (fptr, "000000", 6) != 0)
+                             rooted = 0;
+                         }
+                       else
+                         {
+                           strcpy (vmsname, s1);
+                           s = strchr (vmsname, ']');
+                           *s = '.';
+                           nstate = N_DOT;
+                           vptr = s;
+                         }
+                     }
+                   break;
+                 }
+               free (s1);
+             }
+           else
+             rooted = 0;
+
+           if (*vptr == 0)
+             {
+               nstate = N_DEVICE;
+               *vptr++ = ':';
+             }
+           else
+             vptr++;
+
+           if (rooted == 0)
+             {
+               strcpy (vptr, "[000000.");
+               vptr += 8;
+               s1 = vptr-1;
+               nstate = N_DOT;
+             }
+           else
+             s1 = 0;
+
+       /* s1-> '.' after 000000 or NULL */
+
+           s = strchr (fptr, '/');
+           if (s == 0)
+             {                         /* no next '/' */
+               if (*(vptr-1) == '.')
+                 *(vptr-1) = ']';
+               else if (rooted == 0)
+                 *vptr++ = ']';
+               copyto (&vptr, &fptr, 0, (type == 1));
+               state = -1;
+               break;
+             }
+           else
+             {
+               while (*(s+1) == '/')   /* skip multiple '/' */
+                 s++;
+             }
+
+           if ((rooted != 0)
+               && (*(vptr-1) != '.'))
+             {
+               *vptr++ = '[';
+               nstate = N_DOT;
+             }
+           else
+             if ((nstate == N_DOT)
+                && (s1 != 0)
+                && (*(s+1) == 0))
+               {
+                 if (type == 2)
+                   {
+                     *s1 = ']';
+                     nstate = N_CLOSED;
+                   }
+               }
+           state = 9;
+           break;
+
+         case 4:                               /* single '/' at start (9..15) */
+           if (*fptr == 0)
+             state = 5;
+           else
+             state = 6;
+           break;
+
+         case 5:                               /* just '/' at start (9) */
+           if (type != 2)
+             {
+               *vptr++ = '[';
+               nstate = N_OPEN;
+             }
+           strcpy (vptr, "000000");
+           vptr += 6;
+           if (type == 2)
+             state = 7;
+           else
+             state = 8;
+           break;
+
+         case 6:                               /* chars following '/' at start 10..15 */
+           *vptr++ = '[';
+           nstate = N_OPEN;
+           s = strchr (fptr, '/');
+           if (s == 0)                 /* 10 */
+             {
+               if (type != 1)
+                 {
+                   strcpy (vptr, "000000]");
+                   vptr += 7;
+                 }
+               copyto (&vptr, &fptr, 0, (type == 1));
+               if (type == 1)
+                 {
+                   *vptr++ = ']';
+                 }
+               state = -1;
+             }
+           else                        /* 11..15 */
+             {
+               if ( (type == 2)
+                  && (*(s+1) == 0))    /* 11(2) */
+                 {
+                   strcpy (vptr, "000000]");
+                   nstate = N_CLOSED;
+                   vptr += 7;
+                 }
+               copyto (&vptr, &fptr, '/', (*(vptr-1) != ']'));
+               state = 9;
+             }
+           break;
+
+         case 7:                               /* add '.dir' and exit */
+           if ((nstate == N_OPEN)
+               || (nstate == N_DOT))
+             {
+               s = vptr-1;
+               while (s > vmsname)
+                 {
+                   if (*s == ']')
+                     {
+                       break;
+                     }
+                   if (*s == '.')
+                     {
+                       *s = ']';
+                       break;
+                     }
+                   s--;
+                 }
+             }
+           strcpy (vptr, ".dir");
+           vptr += 4;
+           state = -1;
+           break;
+
+         case 8:                               /* add ']' and exit */
+           *vptr++ = ']';
+           state = -1;
+           break;
+
+         case 9:                               /* 17..21, fptr -> 1st '/' + 1 */
+           if (*fptr == 0)
+             {
+               if (type == 2)
+                 {
+                   state = 7;
+                 }
+               else
+                 state = 8;
+               break;
+             }
+           s = strchr (fptr, '/');
+           if (s == 0)
+             {
+               if (type != 1)
+                 {
+                   if (nstate == N_OPEN)
+                     {
+                       *vptr++ = ']';
+                       nstate = N_CLOSED;
+                     }
+                   as_dir = 0;
+                 }
+               else
+                 {
+                   if (nstate == N_OPEN)
+                     {
+                       *vptr++ = '.';
+                       nstate = N_DOT;
+                     }
+                   as_dir = 1;
+                 }
+             }
+           else
+             {
+               while (*(s+1) == '/')
+                 s++;
+               if ( (type == 2)
+                   && (*(s+1) == 0))           /* 19(2), 21(2)*/
+                 {
+                   if (nstate != N_CLOSED)
+                     {
+                       *vptr++ = ']';
+                       nstate = N_CLOSED;
+                     }
+                   as_dir = 1;
+                 }
+               else
+                 {
+                   if (nstate == N_OPEN)
+                     {
+                       *vptr++ = '.';
+                       nstate = N_DOT;
+                     }
+                   as_dir = 1;
+                 }
+             }
+           if ( (*fptr == '.')                 /* check for '..' or '../' */
+               && (*(fptr+1) == '.')
+               && ((*(fptr+2) == '/')
+                   || (*(fptr+2) == 0)) )
+             {
+               fptr += 2;
+               if (*fptr == '/')
+                 {
+                   do
+                     {
+                       fptr++;
+                     }
+                   while (*fptr == '/');
+                 }
+               else if (*fptr == 0)
+                 type = 1;
+               vptr--;                         /* vptr -> '.' or ']' */
+               s1 = vptr;
+               for (;;)
+                 {
+                   s1--;
+                   if (*s1 == '.')             /* one back */
+                     {
+                       vptr = s1;
+                       nstate = N_OPEN;
+                       break;
+                     }
+                   if (*s1 == '[')             /* top level reached */
+                     {
+                       if (*fptr == 0)
+                         {
+                           strcpy (s1, "[000000]");
+                           vptr = s1 + 8;
+                           nstate = N_CLOSED;
+                           s = 0;
+                           break;
+                         }
+                       else
+                         {
+                           vptr = s1+1;
+                           nstate = N_OPEN;
+                           break;
+                         }
+                     } 
+                 }
+             }
+           else
+             {
+               copyto (&vptr, &fptr, '/', as_dir);
+               if (nstate == N_DOT)
+                 nstate = N_OPEN;
+             }
+           if (s == 0)
+             {                                 /* 18,20 */
+               if (type == 1)
+                 *vptr++ = ']';
+               state = -1;
+             }
+           else
+             {
+               if (*(s+1) == 0)
+                 {
+                   if (type == 2)              /* 19,21 */
+                     {
+                       state = 7;
+                     }
+                   else
+                     {
+                       *vptr++ = ']';
+                       state = -1;
+                     }
+                 }
+             }
+           break;
+
+         case 10:                              /* 1,2 first is '.' */
+           if (*fptr == '.')
+             {
+               fptr++;
+               state = 11;
+             }
+           else
+             state = 12;
+           break;
+
+         case 11:                              /* 2, '..' at start */
+           count = 1;
+           if (*fptr != 0)
+             {
+               if (*fptr != '/')               /* got ..xxx */
+                 {
+                   return name;
+                 }
+               do                              /* got ../ */
+                 {
+                   fptr++;
+                   while (*fptr == '/') fptr++;
+                   if (*fptr != '.')
+                     break;
+                   if (*(fptr+1) != '.')
+                     break;
+                   fptr += 2;
+                   if ((*fptr == 0)
+                       || (*fptr == '/'))
+                     count++;
+                 }
+               while (*fptr == '/');
+             }
+           {                                   /* got '..' or '../' */
+             char cwdbuf[MAXPATHLEN+1];
+
+             s1 = getcwd(cwdbuf, MAXPATHLEN);
+             if (s1 == 0)
+               {
+                 return "";        /* FIXME, err getcwd */
+               }
+             strcpy (vptr, s1);
+             s = strchr (vptr, ']');
+             if (s != 0)
+               {
+                 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 += strlen (vptr);
+           }
+           break;
+
+         case 12:                              /* 1, '.' at start */
+           if (*fptr != 0)
+             {
+               if (*fptr != '/')
+                 {
+                   return name;
+                 }
+               fptr++;
+             }
+
+           {
+             char cwdbuf[MAXPATHLEN+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;
+       }
+
+       }
+      while (state > 0);
+      
+
+    }
+
+
+  /* directory conversion done
+     fptr -> filename part of input string
+     vptr -> free space in vmsname
+  */
+
+  *vptr++ = 0;
+
+  return vmsname;
+}
+
+
+
+/*
+  convert from vms-style to unix-style
+
+  dev:[dir1.dir2]      //dev/dir1/dir2/
+*/
+
+char *
+unixify (char *name)
+{
+  static char piece[512];
+  char *s, *p;
+
+  if (strchr (name, '/') != 0)         /* already in unix style */
+    return name;
+
+  p = piece;
+  *p = 0;
+
+  /* device part */
+
+  s = strchr (name, ':');
+
+  if (s != 0)
+    {
+      *s = 0;
+      *p++ = '/';
+      *p++ = '/';
+      strcpy (p, name);
+      p += strlen (p);
+      *s = ':';
+    }
+
+  /* directory part */
+
+  *p++ = '/';
+  s = strchr (name, '[');
+
+  if (s != 0)
+    {
+      s++;
+      switch (*s)
+        {
+         case ']':             /* [] */
+           strcat (p, "./");
+           break;
+         case '-':             /* [- */
+           strcat (p, "../");
+           break;
+         case '.':
+           strcat (p, "./");   /* [. */
+           break;
+         default:
+           s--;
+           break;
+        }
+      s++;
+      while (*s)
+        {
+         if (*s == '.')
+           *p++ = '/';
+         else
+           *p++ = *s;
+         s++;
+         if (*s == ']')
+           {
+             s++;
+             break;
+           }
+        }
+      if (*s != 0)             /* more after ']' ?? */
+        {
+         if (*(p-1) != '/')
+           *p++ = '/';
+         strcpy (p, s);                /* copy it anyway */
+        }
+    }
+
+  else         /* no '[' anywhere */
+
+    {
+      *p++ = 0;
+    }
+
+  /* force end with '/' */
+
+  if (*(p-1) != '/')
+    *p++ = '/';
+  *p = 0;
+
+  return piece;
+}
+
+/* EOF */
diff --git a/vpath.c b/vpath.c
index 499864b..3e78a9a 100644 (file)
--- a/vpath.c
+++ b/vpath.c
@@ -17,7 +17,7 @@ along with GNU Make; see the file COPYING.  If not, write to
 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 #include "make.h"
-#include "file.h"
+#include "filedef.h"
 #include "variable.h"
 
 
@@ -41,7 +41,7 @@ static struct vpath *vpaths;
 
 static struct vpath *general_vpath;
 \f
-static int selective_vpath_search ();
+static int selective_vpath_search PARAMS ((struct vpath *path, char **file, time_t *mtime_ptr));
 
 /* Reverse the chain of selective VPATH lists so they
    will be searched in the order given in the makefiles