* Merge VMS patches by Hartmut Becker.

This commit is contained in:
Paul Smith 2000-01-22 05:43:03 +00:00
parent b7b83d6398
commit 5577cdc261
20 changed files with 1236 additions and 317 deletions

View file

@ -1,3 +1,13 @@
2000-01-21 Paul D. Smith <psmith@gnu.org>
Installed patches for the VMS port.
Patches provided by: Hartmut Becker <Hartmut.Becker@compaq.com>
* readme.vms, arscan.c, config.h-vms, default.c, dir.c, file.c:
* implicit.c, job.c, make.h, makefile.com, makefile.vms, rule.c:
* variable.c, vmsdir.h, vmsfunctions.c, vmsify.c, glob/glob.c:
* glob/glob.h: Installed patches. See readme.vms for details.
2000-01-11 Paul D. Smith <psmith@gnu.org>
Resolve PR/xxxx: don't automatically evaluate the $(call ...)

7
NEWS
View file

@ -1,8 +1,8 @@
GNU make NEWS -*-indented-text-*-
History of user-visible changes.
21 Nov 1999
21 Jan 2000
Copyright (C) 1992,93,94,95,96,97,98,1999 Free Software Foundation, Inc.
Copyright (C) 1992,93,94,95,96,97,98,99,2000 Free Software Foundation, Inc.
See the end for copying conditions.
All changes mentioned here are more fully described in the GNU make
@ -43,6 +43,9 @@ Version 3.79
a minimal amount information is generated, displaying the names of
"normal" targets (not makefiles) were deemed out of date and in need
of being rebuilt.
* Hartmut Becker provided many updates for the VMS port of GNU make.
See the readme.vms file for more details.
Version 3.78

View file

@ -78,7 +78,9 @@ VMS_get_member_info (module, rfa)
mhd = (struct mhddef *) filename;
#ifdef __DECC
val = decc$fix_time (&mhd->mhd$l_datim);
#endif
for (i = 0; i < module->dsc$w_length; i++)
filename[i] = _tolower ((unsigned char)module->dsc$a_pointer[i]);

View file

@ -1,4 +1,4 @@
/* config.h-vms. Generated by hand by Klaus Kämpf <kkaempf@progis.de> */
/* config.h-vms. Generated by hand by Klaus Kämpf <kkaempf@rmi.de> */
/* config.h. Generated automatically by configure. */
/* config.h.in. Generated automatically from configure.in by autoheader. */
@ -11,6 +11,10 @@
/* Define if using alloca.c. */
/* #undef C_ALLOCA */
/* maybe this should be placed into make.h */
#if defined(__VAX) && defined(__DECC)
#define alloca(n) __ALLOCA(n)
#endif
/* Define if the closedir function returns void instead of int. */
/* #undef CLOSEDIR_VOID */
@ -117,18 +121,17 @@
/* #undef NO_MINUS_C_MINUS_O */
/* Define to `int' if <sys/types.h> doesn't define. */
/* #undef pid_t */
/* I assume types.h is available for all 5.0 cc/cxx compilers */
#if __DECC_VER < 50090000
#define pid_t int
#endif
/* Define if the system does not provide POSIX.1 features except
with this defined. */
/* #undef _POSIX_1_SOURCE */
#include <sys/types.h>
#include <ctype.h>
#include <signal.h>
/* Define if you need to in order for stat and other things to work. */
#define _POSIX_C_SOURCE 1
/* #undef _POSIX_SOURCE */
/* Define as the return type of signal handlers (int or void). */
#define RETSIGTYPE void
@ -160,7 +163,9 @@
/* #undef SYS_SIGLIST_DECLARED */
/* Define to `int' if <sys/types.h> doesn't define. */
/* #undef uid_t */
#if __DECC_VER < 50090000
#define uid_t int
#endif
/* Define for Encore UMAX. */
/* #undef UMAX */
@ -267,7 +272,7 @@
/* #undef HAVE_WAITPID */
/* Define if you have the <dirent.h> header file. */
/* #undef HAVE_DIRENT_H */
#define HAVE_DIRENT_H 1
/* Define if you have the <fcntl.h> header file. */
#ifdef __DECC
@ -302,36 +307,55 @@
/* #undef HAVE_SYS_PARAM_H */
/* Define if you have the <sys/timeb.h> header file. */
#ifndef __GNUC__
#define HAVE_SYS_TIMEB_H 1
#endif
/* Define if you have the <sys/wait.h> header file. */
/* #undef HAVE_SYS_WAIT_H */
/* Define if you have the <unistd.h> header file. */
/* #undef HAVE_UNISTD_H */
/* Define if you have the dgc library (-ldgc). */
/* #undef HAVE_LIBDGC */
/* Define if you have the kstat library (-lkstat). */
/* #undef HAVE_LIBKSTAT */
/* #undef HAVE_LIBKSTAT *
/* Define if you have the sun library (-lsun). */
/* #undef HAVE_LIBSUN */
/* VMS specific */
/* Define for case insensitve filenames */
#define HAVE_CASE_INSENSITIVE_FS 1
/* VMS specific, define it if you want to use case sensitve targets */
/* #undef WANT_CASE_SENSITIVE_TARGETS */
/* VMS specific, V7.0 has opendir() and friends, so it's undefined */
/* Define first or both if you want to use non-VMS code for opendir() etc. */
/* #undef HAVE_VMSDIR_H */
/* #undef _DIRENT_HAVE_D_NAMLEN */
/* On older systems with older CRTLs force non-VMS-code */
#if __CRTL_VER < 70000000 && !defined(HAVE_VMSDIR_H)
#define HAVE_VMSDIR_H 1
#endif
#if defined(HAVE_VMSDIR_H) && defined(HAVE_DIRENT_H)
#undef HAVE_DIRENT_H
#endif
#define HAVE_STDLIB_H 1
#define INCLUDEDIR "sys$sysroot:[syslib]"
#define LIBDIR "sys$sysroot:[syslib]"
/* Avoid broken RTL functions on OpenVMS */
#include <unixlib.h>
/* Don't use RTL functions of OpenVMS */
#ifdef __DECC
#include <stdio.h>
#include <unistd.h>
#define getopt gnu_getopt
#define optarg gnu_optarg
#define optopt gnu_optopt
#define optind gnu_optind
#define opterr gnu_opterr
#endif
#if defined (__cplusplus) || (defined (__STDC__) && __STDC__)
#undef PARAMS

View file

@ -38,8 +38,8 @@ Boston, MA 02111-1307, USA. */
static char default_suffixes[]
#ifdef VMS
= ".exe .olb .ln .obj .c .cc .pas .p .for .f .r .y .l .mar \
.mod .sym .def .h .info .dvi .tex .texinfo .texi .txinfo \
= ".exe .olb .ln .obj .c .cxx .cc .pas .p .for .f .r .y .l .mar \
.s .ss .i .ii .mod .sym .def .h .info .dvi .tex .texinfo .texi .txinfo \
.w .ch .cweb .web .com .sh .elc .el";
#else
= ".out .a .ln .o .c .cc .C .cpp .p .f .F .r .y .l .s .S \
@ -108,13 +108,21 @@ static char *default_suffix_rules[] =
{
#ifdef VMS
".obj.exe",
"$(LINK.obj) $^ $(LOADLIBES) $(LDLIBS) /exe=$@",
"$(LINK.obj) $^ $(LOADLIBES) $(LDLIBS) $(CRT0) /exe=$@",
".mar.exe",
"$(LINK.mar) $^ $(LOADLIBES) $(LDLIBS) /exe=$@",
"$(COMPILE.mar) $^ \n $(LINK.obj) $(subst .mar,.obj,$^) $(LOADLIBES) $(LDLIBS) $(CRT0) /exe=$@",
".s.exe",
"$(COMPILE.s) $^ \n $(LINK.obj) $(subst .s,.obj,$^) $(LOADLIBES) $(LDLIBS) $(CRT0) /exe=$@",
".c.exe",
"$(COMPILE.c) $^ \n $(LINK.obj) $(subst .c,.obj,$^) $(LOADLIBES) $(LDLIBS) /exe=$@",
"$(COMPILE.c) $^ \n $(LINK.obj) $(subst .c,.obj,$^) $(LOADLIBES) $(LDLIBS) $(CRT0) /exe=$@",
".cc.exe",
"$(COMPILE.cc) $^ \n $(LINK.obj) $(subst .cc,.obj,$^) $(LOADLIBES) $(LDLIBS) /exe=$@",
#ifdef GCC_IS_NATIVE
"$(COMPILE.cc) $^ \n $(LINK.obj) $(CXXSTARTUP),sys$$disk:[]$(subst .cc,.obj,$^) $(LOADLIBES) $(LXLIBS) $(LDLIBS) $(CXXRT0) /exe=$@",
#else
"$(COMPILE.cc) $^ \n $(CXXLINK.obj) $(subst .cc,.obj,$^) $(LOADLIBES) $(LXLIBS) $(LDLIBS) $(CXXRT0) /exe=$@",
".cxx.exe",
"$(COMPILE.cxx) $^ \n $(CXXLINK.obj) $(subst .cxx,.obj,$^) $(LOADLIBES) $(LXLIBS) $(LDLIBS) $(CXXRT0) /exe=$@",
#endif
".for.exe",
"$(COMPILE.for) $^ \n $(LINK.obj) $(subst .for,.obj,$^) $(LOADLIBES) $(LDLIBS) /exe=$@",
".pas.exe",
@ -125,8 +133,24 @@ static char *default_suffix_rules[] =
".mar.obj",
"$(COMPILE.mar) /obj=$@ $<",
".s.obj",
"$(COMPILE.s) /obj=$@ $<",
".ss.obj",
"$(COMPILE.s) /obj=$@ $<",
".c.i",
"$(COMPILE.c)/prep /list=$@ $<",
".c.s",
"$(COMPILE.c)/noobj/machine /list=$@ $<",
".i.s",
"$(COMPILE.c)/noprep/noobj/machine /list=$@ $<",
".c.obj",
"$(COMPILE.c) /obj=$@ $<",
".cc.ii",
"$(COMPILE.cc)/prep /list=$@ $<",
".cc.ss",
"$(COMPILE.cc)/noobj/machine /list=$@ $<",
".ii.ss",
"$(COMPILE.cc)/noprep/noobj/machine /list=$@ $<",
".cc.obj",
"$(COMPILE.cc) /obj=$@ $<",
".for.obj",
@ -276,12 +300,31 @@ static char *default_suffix_rules[] =
static char *default_variables[] =
{
#ifdef VMS
#ifdef __ALPHA
"ARCH", "ALPHA",
#else
"ARCH", "VAX",
#endif
"AR", "library/obj",
"ARFLAGS", "/replace",
"AS", "macro",
"MACRO", "macro",
#ifdef GCC_IS_NATIVE
"CC", "gcc",
#else
"CC", "cc",
#endif
"CD", "builtin_cd",
"MAKE", "make",
"ECHO", "write sys$$output \"",
#ifdef GCC_IS_NATIVE
"C++", "gcc/plus",
"CXX", "gcc/plus",
#else
"C++", "cxx",
"CXX", "cxx",
"CXXLD", "cxxlink",
#endif
"CO", "co",
"CPP", "$(CC) /preprocess_only",
"FC", "fortran",
@ -292,21 +335,43 @@ static char *default_variables[] =
"LD", "link",
"LEX", "lex",
"PC", "pascal",
"YACC", "yacc", /* Or "bison -y" */
"YACC", "bison/yacc",
"YFLAGS", "/Define/Verbose",
"BISON", "bison",
"MAKEINFO", "makeinfo",
"TEX", "tex",
"TEXINDEX", "texindex",
"RM", "delete/nolog",
"CSTARTUP", "",
#ifdef GCC_IS_NATIVE
"CRT0", ",sys$$library:vaxcrtl.olb/lib,gnu_cc_library:crt0.obj",
"CXXSTARTUP", "gnu_cc_library:crtbegin.obj",
"CXXRT0", ",sys$$library:vaxcrtl.olb/lib,gnu_cc_library:crtend.obj,gnu_cc_library:gxx_main.obj",
"LXLIBS", ",gnu_cc_library:libstdcxx.olb/lib,gnu_cc_library:libgccplus.olb/lib",
"LDLIBS", ",gnu_cc_library:libgcc.olb/lib",
#else
"CRT0", "",
"CXXSTARTUP", "",
"CXXRT0", "",
"LXLIBS", "",
"LDLIBS", "",
#endif
"LINK.obj", "$(LD) $(LDFLAGS)",
#ifndef GCC_IS_NATIVE
"CXXLINK.obj", "$(CXXLD) $(LDFLAGS)",
"COMPILE.cxx", "$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH)",
#endif
"COMPILE.c", "$(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH)",
"COMPILE.cc", "$(C++) $(C++FLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c",
"COMPILE.cc", "$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH)",
"YACC.y", "$(YACC) $(YFLAGS)",
"LEX.l", "$(LEX) $(LFLAGS)",
"COMPILE.for", "$(FC) $(FFLAGS) $(TARGET_ARCH)",
"COMPILE.pas", "$(PC) $(PFLAGS) $(CPPFLAGS) $(TARGET_ARCH)",
"COMPILE.mar", "$(AS) $(ASFLAGS) $(TARGET_MACH)",
"COMPILE.mar", "$(MACRO) $(MACROFLAGS)",
"COMPILE.s", "$(AS) $(ASFLAGS) $(TARGET_MACH)",
"LINT.c", "$(LINT) $(LINTFLAGS) $(CPPFLAGS) $(TARGET_ARCH)",
"MV", "rename/new_version",

75
dir.c
View file

@ -22,6 +22,9 @@ Boston, MA 02111-1307, USA. */
#ifdef HAVE_DIRENT_H
# include <dirent.h>
# define NAMLEN(dirent) strlen((dirent)->d_name)
# ifdef VMS
extern char *vmsify PARAMS ((char *name, int type));
# endif
#else
# define dirent direct
# define NAMLEN(dirent) (dirent)->d_namlen
@ -41,18 +44,18 @@ Boston, MA 02111-1307, USA. */
/* In GNU systems, <dirent.h> defines this macro for us. */
#ifdef _D_NAMLEN
#undef NAMLEN
#define NAMLEN(d) _D_NAMLEN(d)
# undef NAMLEN
# define NAMLEN(d) _D_NAMLEN(d)
#endif
#if (defined (POSIX) || defined (WINDOWS32)) && !defined (__GNU_LIBRARY__)
#if (defined (POSIX) || defined (VMS) || defined (WINDOWS32)) && !defined (__GNU_LIBRARY__)
/* Posix does not require that the d_ino field be present, and some
systems do not provide it. */
#define REAL_DIR_ENTRY(dp) 1
#define FAKE_DIR_ENTRY(dp)
# define REAL_DIR_ENTRY(dp) 1
# define FAKE_DIR_ENTRY(dp)
#else
#define REAL_DIR_ENTRY(dp) (dp->d_ino != 0)
#define FAKE_DIR_ENTRY(dp) (dp->d_ino = 1)
# define REAL_DIR_ENTRY(dp) (dp->d_ino != 0)
# define FAKE_DIR_ENTRY(dp) (dp->d_ino = 1)
#endif /* POSIX */
#ifdef __MSDOS__
@ -156,7 +159,8 @@ vms_hash (name)
while (*name)
{
h = (h << 4) + *name++;
h = (h << 4) + (isupper (*name) ? tolower (*name) : *name);
name++;
g = h & 0xf0000000;
if (g)
{
@ -333,12 +337,12 @@ find_directory (name)
if (vmsstat_dir (name, &st) < 0)
#else
#ifdef WINDOWS32
# ifdef WINDOWS32
/* Remove any trailing '\'. Windows32 stat fails even on valid
directories if they end in '\'. */
if (p[-1] == '\\')
p[-1] = '\0';
#endif
# endif
if (stat (name, &st) < 0)
#endif
{
@ -356,14 +360,14 @@ find_directory (name)
w32_path = w32ify(name, 1);
hash = ((unsigned int) st.st_dev << 16) | (unsigned int) st.st_ctime;
#else
#ifdef VMS
hash = ((unsigned int) st.st_dev << 16)
| ((unsigned int) st.st_ino[0]
+ (unsigned int) st.st_ino[1]
+ (unsigned int) st.st_ino[2]);
#else
# ifdef VMS
hash = (((unsigned int) st.st_dev << 16)
| ((unsigned int) st.st_ino[0]
+ (unsigned int) st.st_ino[1]
+ (unsigned int) st.st_ino[2]));
# else
hash = ((unsigned int) st.st_dev << 16) | (unsigned int) st.st_ino;
#endif
# endif
#endif
hash %= DIRECTORY_BUCKETS;
@ -372,13 +376,14 @@ find_directory (name)
if (strieq(dc->path_key, w32_path))
#else
if (dc->dev == st.st_dev
#ifdef VMS
# ifdef VMS
&& dc->ino[0] == st.st_ino[0]
&& dc->ino[1] == st.st_ino[1]
&& dc->ino[2] == st.st_ino[2])
#else
&& dc->ino == st.st_ino)
#endif
&& dc->ino[2] == st.st_ino[2]
# else
&& dc->ino == st.st_ino
# endif
)
#endif /* WINDOWS32 */
break;
@ -413,24 +418,22 @@ find_directory (name)
else
dc->fs_flags = FS_UNKNOWN;
#else
#ifdef VMS
# ifdef VMS
dc->ino[0] = st.st_ino[0];
dc->ino[1] = st.st_ino[1];
dc->ino[2] = st.st_ino[2];
#else
# else
dc->ino = st.st_ino;
#endif
# endif
#endif /* WINDOWS32 */
dc->next = directories_contents[hash];
directories_contents[hash] = dc;
dc->dirstream = opendir (name);
if (dc->dirstream == 0)
{
/* Couldn't open the directory. Mark this by
setting the `files' member to a nil pointer. */
dc->files = 0;
}
/* Couldn't open the directory. Mark this by
setting the `files' member to a nil pointer. */
dc->files = 0;
else
{
/* Allocate an array of buckets for files and zero it. */
@ -553,6 +556,14 @@ dir_contents_file_exists_p (dir, filename)
unsigned int len;
register unsigned int i;
#if defined(VMS) && defined(HAVE_DIRENT_H)
/* In VMS we get file versions too, which have to be stripped off */
{
char *p = strrchr (d->d_name, ';');
if (p)
*p = '\0';
}
#endif
if (!REAL_DIR_ENTRY (d))
continue;
@ -636,6 +647,8 @@ file_exists_p (name)
#ifdef VMS
dirend = strrchr (name, ']');
if (dirend == 0)
dirend = strrchr (name, ':');
dirend++;
if (dirend == (char *)1)
return dir_file_exists_p ("[]", name);
@ -694,6 +707,8 @@ file_impossible (filename)
#ifdef VMS
dirend = strrchr (p, ']');
if (dirend == 0)
dirend = strrchr (name, ':');
dirend++;
if (dirend == (char *)1)
dir = find_directory ("[]");

16
file.c
View file

@ -54,7 +54,7 @@ lookup_file (name)
register struct file *f;
register char *n;
register unsigned int hashval;
#ifdef VMS
#if defined(VMS) && !defined(WANT_CASE_SENSITIVE_TARGETS)
register char *lname, *ln;
#endif
@ -65,11 +65,13 @@ lookup_file (name)
for names read from makefiles. It is here for names passed
on the command line. */
#ifdef VMS
# ifndef WANT_CASE_SENSITIVE_TARGETS
lname = (char *)malloc(strlen(name) + 1);
for (n=name, ln=lname; *n != '\0'; ++n, ++ln)
*ln = isupper((unsigned char)*n) ? tolower((unsigned char)*n) : *n;
*ln = '\0';
name = lname;
# endif
while (name[0] == '[' && name[1] == ']' && name[2] != '\0')
name += 2;
@ -103,13 +105,13 @@ lookup_file (name)
{
if (strieq (f->hname, name))
{
#ifdef VMS
#if defined(VMS) && !defined(WANT_CASE_SENSITIVE_TARGETS)
free (lname);
#endif
return f;
}
}
#ifdef VMS
#if defined(VMS) && !defined(WANT_CASE_SENSITIVE_TARGETS)
free (lname);
#endif
return 0;
@ -122,14 +124,14 @@ enter_file (name)
register struct file *f, *new;
register char *n;
register unsigned int hashval;
#ifdef VMS
#if defined(VMS) && !defined(WANT_CASE_SENSITIVE_TARGETS)
char *lname, *ln;
#endif
if (*name == '\0')
abort ();
#ifdef VMS
#if defined(VMS) && !defined(WANT_CASE_SENSITIVE_TARGETS)
lname = (char *)malloc (strlen (name) + 1);
for (n = name, ln = lname; *n != '\0'; ++n, ++ln)
{
@ -139,6 +141,8 @@ enter_file (name)
*ln = *n;
}
*ln = 0;
/* Creates a possible leak, old value of name is unreachable, but I
currently don't know how to fix it. */
name = lname;
#endif
@ -153,7 +157,7 @@ enter_file (name)
if (f != 0 && !f->double_colon)
{
#ifdef VMS
#if defined(VMS) && !defined(WANT_CASE_SENSITIVE_TARGETS)
free(lname);
#endif
return f;

View file

@ -299,6 +299,12 @@ static int glob_in_dir __P ((const char *pattern, const char *directory,
static int prefix_array __P ((const char *prefix, char **array, size_t n));
static int collated_compare __P ((const __ptr_t, const __ptr_t));
#ifdef VMS
/* these compilers like prototypes */
#if !defined _LIBC || !defined NO_GLOB_PATTERN_P
int __glob_pattern_p (const char *pattern, int quote);
#endif
#endif
/* Find the end of the sub-pattern in a brace expression. We define
this as an inline function if the compiler permits. */
@ -609,7 +615,12 @@ glob (pattern, flags, errfunc, pglob)
if (dirname[1] == '\0' || dirname[1] == '/')
{
/* Look up home directory. */
const char *home_dir = getenv ("HOME");
#ifdef VMS
/* This isn't obvious, RTLs of DECC and VAXC know about "HOME" */
const char *home_dir = getenv ("SYS$LOGIN");
#else
const char *home_dir = getenv ("HOME");
#endif
# ifdef _AMIGA
if (home_dir == NULL || home_dir[0] == '\0')
home_dir = "SYS:";
@ -618,6 +629,11 @@ glob (pattern, flags, errfunc, pglob)
if (home_dir == NULL || home_dir[0] == '\0')
home_dir = "c:/users/default"; /* poor default */
# else
# ifdef VMS
/* Again, this isn't obvious, if "HOME" isn't known "SYS$LOGIN" should be set */
if (home_dir == NULL || home_dir[0] == '\0')
home_dir = "SYS$DISK:[]";
# else
if (home_dir == NULL || home_dir[0] == '\0')
{
int success;
@ -676,6 +692,7 @@ glob (pattern, flags, errfunc, pglob)
else
home_dir = "~"; /* No luck. */
}
# endif /* VMS */
# endif /* WINDOWS32 */
# endif
/* Now construct the full directory. */
@ -696,7 +713,7 @@ glob (pattern, flags, errfunc, pglob)
dirname = newp;
}
}
# if !defined _AMIGA && !defined WINDOWS32
# if !defined _AMIGA && !defined WINDOWS32 && !defined VMS
else
{
char *end_name = strchr (dirname, '/');
@ -776,7 +793,7 @@ glob (pattern, flags, errfunc, pglob)
home directory. */
return GLOB_NOMATCH;
}
# endif /* Not Amiga && not WINDOWS32. */
# endif /* Not Amiga && not WINDOWS32 && not VMS. */
}
#endif /* Not VMS. */
@ -1213,6 +1230,10 @@ glob_in_dir (pattern, directory, flags, errfunc, pglob)
int meta;
int save;
#ifdef VMS
if (*directory == 0)
directory = "[]";
#endif
meta = __glob_pattern_p (pattern, !(flags & GLOB_NOESCAPE));
if (meta == 0)
{

View file

@ -51,7 +51,15 @@ extern "C" {
typedef __SIZE_TYPE__ __size_t;
# else
/* This is a guess. */
/*hb
* Conflicts with DECCs aready defined type __size_t.
* Defining an own type with a name beginning with '__' is no good.
* Anyway if DECC is used and __SIZE_T is defined then __size_t is
* already defined (and I hope it's exactly the one we need here).
*/
#if !(defined __DECC && defined __SIZE_T)
typedef unsigned long int __size_t;
#endif
# endif
#else
/* The GNU CC stddef.h version defines __size_t as empty. We need a real
@ -118,7 +126,11 @@ typedef struct
struct dirent *(*gl_readdir) __PMT ((void *));
__ptr_t (*gl_opendir) __PMT ((__const char *));
int (*gl_lstat) __PMT ((__const char *, struct stat *));
#if defined(VMS) && defined(__DECC) && !defined(_POSIX_C_SOURCE)
int (*gl_stat) __PMT ((__const char *, struct stat *, ...));
#else
int (*gl_stat) __PMT ((__const char *, struct stat *));
#endif
} glob_t;
#ifdef _LARGEFILE64_SOURCE

View file

@ -163,6 +163,8 @@ pattern_search (file, archive, depth, recursions)
bar/ in directory foo/, not empty in directory foo/bar/.) */
#ifdef VMS
lastslash = strrchr (filename, ']');
if (lastslash == 0)
lastslash = strrchr (filename, ':');
#else
lastslash = strrchr (filename, '/');
#if defined(__MSDOS__) || defined(WINDOWS32)
@ -225,7 +227,9 @@ pattern_search (file, archive, depth, recursions)
prefix and the target pattern does not contain a slash. */
#ifdef VMS
check_lastslash = lastslash != 0 && strchr (target, ']') == 0;
check_lastslash = lastslash != 0
&& ((strchr (target, ']') == 0)
&& (strchr (target, ':') == 0));
#else
check_lastslash = lastslash != 0 && strchr (target, '/') == 0;
#endif

587
job.c
View file

@ -46,7 +46,12 @@ extern int MyExecute (char **);
directories we could trust). */
char *default_shell = "command.com";
# else /* __MSDOS__ */
# ifdef VMS
# include <descrip.h>
char default_shell[] = "";
# else
char default_shell[] = "/bin/sh";
# endif /* VMS */
# endif /* __MSDOS__ */
int batch_mode_shell = 0;
# endif /* _AMIGA */
@ -70,7 +75,9 @@ static int amiga_batch_file;
#ifdef VMS
# include <time.h>
# include <processes.h>
# ifndef __GNUC__
# include <processes.h>
# endif
# include <starlet.h>
# include <lib$routines.h>
#endif
@ -186,6 +193,7 @@ extern int start_remote_job_p PARAMS ((int));
extern int remote_status PARAMS ((int *exit_code_ptr, int *signal_ptr,
int *coredump_ptr, int block));
RETSIGTYPE child_handler PARAMS ((int));
static void free_child PARAMS ((struct child *));
static void start_job_command PARAMS ((struct child *child));
static int load_too_high PARAMS ((void));
@ -226,7 +234,6 @@ int w32_kill(int pid, int sig)
}
#endif /* WINDOWS32 */
/* Write an error message describing the exit status given in
EXIT_CODE, EXIT_SIG, and COREDUMP, for the target TARGET_NAME.
Append "(ignored)" if IGNORED is nonzero. */
@ -272,6 +279,98 @@ vmsWaitForChildren(int *status)
}
return;
}
/* Set up IO redirection. */
char *
vms_redirect (desc, fname, ibuf)
struct dsc$descriptor_s *desc;
char *fname;
char *ibuf;
{
char *fptr;
extern char *vmsify ();
ibuf++;
while (isspace (*ibuf))
ibuf++;
fptr = ibuf;
while (*ibuf && !isspace (*ibuf))
ibuf++;
*ibuf = 0;
if (strcmp (fptr, "/dev/null") != 0)
{
strcpy (fname, vmsify (fptr, 0));
if (strchr (fname, '.') == 0)
strcat (fname, ".");
}
desc->dsc$w_length = strlen(fname);
desc->dsc$a_pointer = fname;
desc->dsc$b_dtype = DSC$K_DTYPE_T;
desc->dsc$b_class = DSC$K_CLASS_S;
if (*fname == 0)
printf ("Warning: Empty redirection\n");
return ibuf;
}
/*
found apostrophe at (p-1)
inc p until after closing apostrophe. */
static char *
handle_apos (char *p)
{
int alast;
int inside;
#define SEPCHARS ",/()= "
inside = 0;
while (*p != 0)
{
if (*p == '"')
{
if (inside)
{
while ((alast > 0)
&& (*p == '"'))
{
p++;
alast--;
}
if (alast == 0)
inside = 0;
else
{
fprintf (stderr, "Syntax error, still inside '\"'\n");
exit (3);
}
}
else
{
p++;
if (strchr (SEPCHARS, *p))
break;
inside = 1;
alast = 1;
while (*p == '"')
{
alast++;
p++;
}
}
}
else
p++;
}
return p;
}
#endif
@ -1603,6 +1702,76 @@ int vmsHandleChildTerm(struct child *child)
#define MAXCMDLEN 200
/* local helpers to make ctrl+c and ctrl+y working, see below */
#include <iodef.h>
#include <libclidef.h>
#include <ssdef.h>
static int ctrlMask= LIB$M_CLI_CTRLY;
static int oldCtrlMask;
static int setupYAstTried= 0;
static int pidToAbort= 0;
static int chan= 0;
static void reEnableAst(void) {
lib$enable_ctrl (&oldCtrlMask,0);
}
static astHandler (void) {
if (pidToAbort) {
sys$forcex (&pidToAbort, 0, SS$_ABORT);
pidToAbort= 0;
}
kill (getpid(),SIGQUIT);
}
static void tryToSetupYAst(void) {
$DESCRIPTOR(inputDsc,"SYS$COMMAND");
int status;
struct {
short int status, count;
int dvi;
} iosb;
setupYAstTried++;
if (!chan) {
status= sys$assign(&inputDsc,&chan,0,0);
if (!(status&SS$_NORMAL)) {
lib$signal(status);
return;
}
}
status= sys$qiow (0, chan, IO$_SETMODE|IO$M_CTRLYAST,&iosb,0,0,
astHandler,0,0,0,0,0);
if (status==SS$_ILLIOFUNC) {
sys$dassgn(chan);
#ifdef CTRLY_ENABLED_ANYWAY
fprintf (stderr, "-warning, CTRL-Y will leave "
"sub-process(es) around.\n");
#else
return;
#endif
}
if (status==SS$_NORMAL)
status= iosb.status;
if (!(status&SS$_NORMAL)) {
lib$signal(status);
return;
}
/* called from AST handler ? */
if (setupYAstTried>1)
return;
if (atexit(reEnableAst))
fprintf (stderr, "-warning, you may have to re-enable CTRL-Y"
"handling from DCL.\n");
status= lib$disable_ctrl (&ctrlMask, &oldCtrlMask);
if (!(status&SS$_NORMAL)) {
lib$signal(status);
return;
}
}
int
child_execute_job (argv, child)
char *argv;
@ -1610,32 +1779,187 @@ child_execute_job (argv, child)
{
int i;
static struct dsc$descriptor_s cmddsc;
#ifndef DONTWAITFORCHILD
int spflags = 0;
#else
static struct dsc$descriptor_s pnamedsc;
static struct dsc$descriptor_s ifiledsc;
static struct dsc$descriptor_s ofiledsc;
static struct dsc$descriptor_s efiledsc;
int have_redirection = 0;
int have_newline = 0;
int spflags = CLI$M_NOWAIT;
#endif
int status;
char cmd[4096],*p,*c;
char *cmd = alloca (strlen (argv) + 512), *p, *q;
char ifile[256], ofile[256], efile[256];
char comname[50];
char procname[100];
/* Remove backslashes */
for (p = argv, c = cmd; *p; p++,c++)
/* Parse IO redirection. */
ifile[0] = 0;
ofile[0] = 0;
efile[0] = 0;
if (debug_flag)
printf ("child_execute_job (%s)\n", argv);
while (isspace (*argv))
argv++;
if (*argv == 0)
return 0;
sprintf (procname, "GMAKE_%05x", getpid () & 0xfffff);
pnamedsc.dsc$w_length = strlen(procname);
pnamedsc.dsc$a_pointer = procname;
pnamedsc.dsc$b_dtype = DSC$K_DTYPE_T;
pnamedsc.dsc$b_class = DSC$K_CLASS_S;
/* Handle comments and redirection. */
for (p = argv, q = cmd; *p; p++, q++)
{
if (*p == '\\') p++;
*c = *p;
switch (*p)
{
case '#':
*p-- = 0;
*q-- = 0;
break;
case '\\':
p++;
if (*p == '\n')
p++;
if (isspace (*p))
{
do { p++; } while (isspace (*p));
p--;
}
*q = *p;
break;
case '<':
p = vms_redirect (&ifiledsc, ifile, p);
*q = ' ';
have_redirection = 1;
break;
case '>':
have_redirection = 1;
if (*(p-1) == '2')
{
q--;
if (strncmp (p, ">&1", 3) == 0)
{
p += 3;
strcpy (efile, "sys$output");
efiledsc.dsc$w_length = strlen(efile);
efiledsc.dsc$a_pointer = efile;
efiledsc.dsc$b_dtype = DSC$K_DTYPE_T;
efiledsc.dsc$b_class = DSC$K_CLASS_S;
}
else
{
p = vms_redirect (&efiledsc, efile, p);
}
}
else
{
p = vms_redirect (&ofiledsc, ofile, p);
}
*q = ' ';
break;
case '\n':
have_newline = 1;
default:
*q = *p;
break;
}
}
*c = *p;
*q = *p;
/* Check for maximum DCL length and create *.com file if neccesary.
Also create a .com file if the command is more than one line long. */
if (strncmp (cmd, "builtin_", 8) == 0)
{
child->pid = 270163;
child->efn = 0;
child->cstatus = 1;
if (debug_flag)
printf ("BUILTIN [%s][%s]\n", cmd, cmd+8);
p = cmd + 8;
if ((*(p) == 'c')
&& (*(p+1) == 'd')
&& ((*(p+2) == ' ') || (*(p+2) == '\t')))
{
p += 3;
while ((*p == ' ') || (*p == '\t'))
p++;
if (debug_flag)
printf ("BUILTIN CD %s\n", p);
if (chdir (p))
return 0;
else
return 1;
}
else if ((*(p) == 'r')
&& (*(p+1) == 'm')
&& ((*(p+2) == ' ') || (*(p+2) == '\t')))
{
int in_arg;
/* rm */
p += 3;
while ((*p == ' ') || (*p == '\t'))
p++;
in_arg = 1;
if (debug_flag)
printf ("BUILTIN RM %s\n", p);
while (*p)
{
switch (*p)
{
case ' ':
case '\t':
if (in_arg)
{
*p++ = ';';
in_arg = 0;
}
break;
default:
break;
}
p++;
}
}
else
{
printf("Unknown builtin command '%s'\n", cmd);
fflush(stdout);
return 0;
}
}
/* Create a *.com file if either the command is too long for
lib$spawn, or the command contains a newline, or if redirection
is desired. Forcing commands with newlines into DCLs allows to
store search lists on user mode logicals. */
comname[0] = '\0';
if (strlen (cmd) > MAXCMDLEN || strchr (cmd, '\n'))
if (strlen (cmd) > MAXCMDLEN
|| (have_redirection != 0)
|| (have_newline != 0))
{
FILE *outfile;
char tmp;
char c;
char *sep;
int alevel = 0; /* apostrophe level */
if (strlen (cmd) == 0)
{
printf ("Error, empty command\n");
fflush (stdout);
return 0;
}
strcpy (comname, "sys$scratch:CMDXXXXXX.COM");
(void) mktemp (comname);
@ -1644,28 +1968,82 @@ child_execute_job (argv, child)
if (outfile == 0)
pfatal_with_name (comname);
fprintf (outfile, "$ ");
c = cmd;
while (c)
if (ifile[0])
{
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;
fprintf (outfile, "$ assign/user %s sys$input\n", ifile);
DB (DB_JOBS, (_("Redirected input from %s\n"), ifile));
ifiledsc.dsc$w_length = 0;
}
if (efile[0])
{
fprintf (outfile, "$ define sys$error %s\n", efile);
DB (DB_JOBS, (_("Redirected error to %s\n"), efile));
efiledsc.dsc$w_length = 0;
}
if (ofile[0])
{
fprintf (outfile, "$ define sys$output %s\n", ofile);
DB (DB_JOBS, (_("Redirected output to %s\n"), ofile));
ofiledsc.dsc$w_length = 0;
}
p = sep = q = cmd;
for (c = '\n'; c; c = *q++)
{
switch (c)
{
case '\n':
/* At a newline, skip any whitespace around a leading $
from the command and issue exactly one $ into the DCL. */
while (isspace (*p))
p++;
if (*p == '$')
p++;
while (isspace (*p))
p++;
fwrite (p, 1, q - p, outfile);
fputc ('$', outfile);
fputc (' ', outfile);
/* Reset variables. */
p = sep = q;
break;
/* Nice places for line breaks are after strings, after
comma or space and before slash. */
case '"':
q = handle_apos (q + 1);
sep = q;
break;
case ',':
case ' ':
sep = q;
break;
case '/':
case '\0':
sep = q - 1;
break;
default:
break;
}
if (sep - p > 78)
{
/* Enough stuff for a line. */
fwrite (p, 1, sep - p, outfile);
p = sep;
if (*sep)
{
/* The command continues. */
fputc ('-', outfile);
}
fputc ('\n', outfile);
}
}
fwrite (p, 1, q - p, outfile);
fputc ('\n', outfile);
fclose (outfile);
sprintf (cmd, "$ @%s", comname);
@ -1681,31 +2059,98 @@ child_execute_job (argv, child)
child->efn = 0;
while (child->efn < 32 || child->efn > 63)
{
status = lib$get_ef(&child->efn);
status = lib$get_ef ((unsigned long *)&child->efn);
if (!(status & 1))
return 0;
}
sys$clref(child->efn);
sys$clref (child->efn);
vms_jobsefnmask |= (1 << (child->efn - 32));
/*
LIB$SPAWN [command-string]
[,input-file]
[,output-file]
[,flags]
[,process-name]
[,process-id] [,completion-status-address] [,byte-integer-event-flag-num]
[,AST-address] [,varying-AST-argument]
[,prompt-string] [,cli] [,table]
*/
#ifndef DONTWAITFORCHILD
status = lib$spawn(&cmddsc,0,0,&spflags,0,&child->pid,&child->cstatus,
&child->efn,0,0);
/*
* Code to make ctrl+c and ctrl+y working.
* The problem starts with the synchronous case where after lib$spawn is
* called any input will go to the child. But with input re-directed,
* both control characters won't make it to any of the programs, neither
* the spawning nor to the spawned one. Hence the caller needs to spawn
* with CLI$M_NOWAIT to NOT give up the input focus. A sys$waitfr
* has to follow to simulate the wanted synchronous behaviour.
* The next problem is ctrl+y which isn't caught by the crtl and
* therefore isn't converted to SIGQUIT (for a signal handler which is
* already established). The only way to catch ctrl+y, is an AST
* assigned to the input channel. But ctrl+y handling of DCL needs to be
* disabled, otherwise it will handle it. Not to mention the previous
* ctrl+y handling of DCL needs to be re-established before make exits.
* One more: At the time of LIB$SPAWN signals are blocked. SIGQUIT will
* make it to the signal handler after the child "normally" terminates.
* This isn't enough. It seems reasonable for simple command lines like
* a 'cc foobar.c' spawned in a subprocess but it is unacceptable for
* spawning make. Therefore we need to abort the process in the AST.
*
* Prior to the spawn it is checked if an AST is already set up for
* ctrl+y, if not one is set up for a channel to SYS$COMMAND. In general
* this will work except if make is run in a batch environment, but there
* nobody can press ctrl+y. During the setup the DCL handling of ctrl+y
* is disabled and an exit handler is established to re-enable it.
* If the user interrupts with ctrl+y, the assigned AST will fire, force
* an abort to the subprocess and signal SIGQUIT, which will be caught by
* the already established handler and will bring us back to common code.
* After the spawn (now /nowait) a sys$waitfr simulates the /wait and
* enables the ctrl+y be delivered to this code. And the ctrl+c too,
* which the crtl converts to SIGINT and which is caught by the common
* signal handler. Because signals were blocked before entering this code
* sys$waitfr will always complete and the SIGQUIT will be processed after
* it (after termination of the current block, somewhere in common code).
* And SIGINT too will be delayed. That is ctrl+c can only abort when the
* current command completes. Anyway it's better than nothing :-)
*/
if (!setupYAstTried)
tryToSetupYAst();
status = lib$spawn (&cmddsc, /* cmd-string */
(ifiledsc.dsc$w_length == 0)?0:&ifiledsc, /* input-file */
(ofiledsc.dsc$w_length == 0)?0:&ofiledsc, /* output-file */
&spflags, /* flags */
&pnamedsc, /* proc name */
&child->pid, &child->cstatus, &child->efn,
0, 0,
0, 0, 0);
pidToAbort= child->pid;
status= sys$waitfr (child->efn);
pidToAbort= 0;
vmsHandleChildTerm(child);
#else
status = lib$spawn(&cmddsc,0,0,&spflags,0,&child->pid,&child->cstatus,
&child->efn,vmsHandleChildTerm,child);
status = lib$spawn (&cmddsc,
(ifiledsc.dsc$w_length == 0)?0:&ifiledsc,
(ofiledsc.dsc$w_length == 0)?0:&ofiledsc,
&spflags,
&pnamedsc,
&child->pid, &child->cstatus, &child->efn,
vmsHandleChildTerm, child,
0, 0, 0);
#endif
if (!(status & 1))
{
printf(_("Error spawning, %d\n"),status);
fflush(stdout);
printf ("Error spawning, %d\n",status);
fflush (stdout);
}
unlink (comname);
if (comname[0] && !ISDB (DB_JOBS)))
unlink (comname);
return (status & 1);
}
@ -1748,6 +2193,10 @@ exec_command (argv, envp)
char **argv, **envp;
{
#ifdef VMS
/* to work around a problem with signals and execve: ignore them */
#ifdef SIGCHLD
signal (SIGCHLD,SIG_IGN);
#endif
/* Run the program. */
execve (argv[0], argv, envp);
perror_with_name ("execve: ", argv[0]);
@ -2337,7 +2786,11 @@ construct_command_argv_internal (line, restp, shell, ifs, batch_filename_ptr)
argument list. */
unsigned int shell_len = strlen (shell);
#ifndef VMS
static char minus_c[] = " -c ";
#else
static char minus_c[] = "";
#endif
unsigned int line_len = strlen (line);
char *new_line = (char *) alloca (shell_len + (sizeof (minus_c) - 1)
@ -2480,6 +2933,7 @@ construct_command_argv_internal (line, restp, shell, ifs, batch_filename_ptr)
return new_argv;
}
#endif /* !VMS */
/* Figure out the argument list necessary to run LINE as a command. Try to
avoid using a shell. This routine handles only ' quoting, and " quoting
@ -2503,6 +2957,48 @@ construct_command_argv (line, restp, file, batch_filename_ptr)
char *shell, *ifs;
char **argv;
#ifdef VMS
char *cptr;
int argc;
argc = 0;
cptr = line;
for (;;)
{
while ((*cptr != 0)
&& (isspace (*cptr)))
cptr++;
if (*cptr == 0)
break;
while ((*cptr != 0)
&& (!isspace(*cptr)))
cptr++;
argc++;
}
argv = (char **)malloc (argc * sizeof (char *));
if (argv == 0)
abort ();
cptr = line;
argc = 0;
for (;;)
{
while ((*cptr != 0)
&& (isspace (*cptr)))
cptr++;
if (*cptr == 0)
break;
if (debug_flag)
printf ("argv[%d] = [%s]\n", argc, cptr);
argv[argc++] = cptr;
while ((*cptr != 0)
&& (!isspace(*cptr)))
cptr++;
if (*cptr != 0)
*cptr++ = 0;
}
#else
{
/* Turn off --warn-undefined-variables while we expand SHELL and IFS. */
int save = warn_undefined_variables_flag;
@ -2528,10 +3024,9 @@ construct_command_argv (line, restp, file, batch_filename_ptr)
free (shell);
free (ifs);
#endif /* !VMS */
return argv;
}
#endif /* !VMS */
#if !defined(HAVE_DUP2) && !defined(_AMIGA)
int

8
make.h
View file

@ -312,6 +312,9 @@ extern char *alloca ();
# define strieq(a, b) (strcmp ((a), (b)) == 0)
#endif
#define strneq(a, b, l) (strncmp ((a), (b), (l)) == 0)
#ifdef VMS
extern int strcmpi (const char *,const char *);
#endif
/* Add to VAR the hashing value of C, one character in a name. */
#define HASH(var, c) \
@ -449,10 +452,9 @@ extern long int lseek ();
#endif /* Not GNU C library or POSIX. */
#ifdef HAVE_GETCWD
# if !defined(VMS) && !defined(__DECC)
extern char *getcwd ();
# ifdef VMS
extern char *getwd PARAMS ((char *));
# endif
#endif
#else
extern char *getwd ();
# define getcwd(buf, len) getwd (buf)

View file

@ -7,6 +7,13 @@ $! P2 = DEBUG will build an image with debug information
$!
$! In case of problems with the install you might contact me at
$! zinser@decus.decus.de (preferred) or martin_zinser@exchange.de
$
$! hb
$! But don't ask Martin Zinser about the lines, I added/changed.
$! In case of an error do some cleanup
$ on error then $ goto cleanup
$! in case somebody set up her/his own symbol for cc
$ set symbol/scope=(nolocal,noglobal)
$!
$! Look for the compiler used
$!
@ -57,9 +64,16 @@ $ linkit:
$ close optf
$ if p1 .nes. "" then goto link_using_library
$ link/exe=make make.opt/opt'lopt
$ exit
$ goto cleanup
$
$ link_using_library:
$ link/exe=make make.opt/opt,sys$library:vaxcrtl/lib'lopt
$
$ cleanup:
$ if f$trnlnm("SYS").nes."" then $ deassign sys
$ if f$trnlnm("OPTF").nes."" then $ close optf
$ if f$search("make.opt").nes."" then $ del make.opt;*
$ exit
$!
$ compileit : subroutine
$ ploc = f$locate("]",p1)

View file

@ -2,7 +2,8 @@
# This file is part of GNU Make.
#
# VMS extensions from GNU Make 3.60 imported by
# Klaus Kämpf (kkaempf@progis.de) of proGIS Software, Aachen, Germany
# Klaus Kämpf (kkaempf@rmi.de)
# Modified for version 3.78.1 by Hartmut.Becker@compaq.com.
#
# GNU Make is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -19,7 +20,7 @@
# the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.
CC = cc/warn
CC = cc
CP = copy
%.obj: %.c
@ -28,11 +29,23 @@ CP = copy
# Makefile for GNU Make
#
CFLAGS = $(defines) /debug/noopt/include=([],[.glob])
ifeq ($(CC),cc)
CFLAGS = $(defines) /include=([],[.glob])/prefix=all/standard=relaxed
else
CFLAGS = $(defines) /include=([],[.glob])
endif
#LDFLAGS = /deb
LDFLAGS =
ifeq ($(CC),cc)
defines = /define=("unlink=remove","HAVE_CONFIG_H","VMS","allocated_variable_expand_for_file=alloc_var_expand_for_file")
else
ifeq ($(ARCH),VAX)
defines = /define=("HAVE_CONFIG_H","GCC_IS_NATIVE","VAX")
else
defines = /define=("HAVE_CONFIG_H","GCC_IS_NATIVE")
endif
endif
LOAD_AVG = /define="NO_LDAV"
@ -44,12 +57,17 @@ ARCHIVES_SRC = ar.c arscan.c
# System V probably need -lPW for alloca.
# if on vax, uncomment the following line
#LOADLIBES = ,c.opt/opt
LOADLIBES =,sys$$library:vaxcrtl.olb/lib
ifeq ($(CC),cc)
#LOADLIBES =,sys$$library:vaxcrtl.olb/lib
CRT0 =
else
LOADLIBES =,gnu_cc_library:libgcc.olb/lib
endif
# If your system doesn't have alloca, or the one provided is bad,
# get it from the Emacs distribution and define these.
ALLOCA = ,alloca.obj
ALLOCASRC = alloca.c
#ALLOCA = ,alloca.obj
#ALLOCASRC = alloca.c
# If there are remote execution facilities defined,
# enable them with switches here (see remote-*.c).
@ -86,11 +104,14 @@ doc: make.info make.dvi
make.exe: $(objs)
$(LD)$(LDFLAGS)/exe=$@ $^$(LOADLIBES)
$(LD)$(LDFLAGS)/exe=$@ $^$(LOADLIBES)$(CRT0)
.PHONY: clean realclean
clean:
-$(RM) make.exe;,*.obj;*
$$ purge [...]
-$(RM) make.exe;,*.obj;
-$(RM) *.opt;
-$(RM) [.glob]*.obj;
# Automatically generated dependencies.
commands.obj: commands.c make.h dep.h commands.h filedef.h variable.h job.h
@ -108,7 +129,7 @@ variable.obj: variable.c make.h commands.h variable.h dep.h filedef.h
expand.obj: expand.c make.h commands.h filedef.h variable.h
function.obj: function.c make.h variable.h dep.h commands.h job.h
vpath.obj: vpath.c make.h filedef.h variable.h
version.obj: version.c
version.obj: version.c config.h
arscan.obj: arscan.c
ar.obj: ar.c make.h filedef.h
signame.obj: signame.c
@ -117,6 +138,8 @@ remote-stub.obj: remote-stub.c
[.glob]fnmatch.obj: [.glob]fnmatch.c
getopt.obj: getopt.c
getopt1.obj: getopt1.c
vmsfunctions.obj: vmsfunctions.c make.h vmsdir.h
vmsify.obj: vmsify.c make.h
config.h: config.h-vms
$(CP) $< $@

View file

@ -1,9 +1,111 @@
This is the VMS port of GNU Make done by Hartmut.Becker@compaq.com.
It is based on the specific version 3.77k and on 3.78.1. 3.77k was done
by Klaus Kämpf <kkaempf@rmi.de>, the code was based on the VMS port of
GNU Make 3.60 by Mike Moretti.
It was ported on OpenVMS/Alpha V7.1, DECC V5.7-006. It was re-build and
tested on OpenVMS/Alpha V7.2, OpenVMS/VAX 7.1 and 5.5-2. Different
versions of DECC were used. VAXC was tried: it fails; but it doesn't
seem worth to get it working. There are still some PTRMISMATCH warnings
during the compile. Although perl is working on VMS the test scripts
don't work. The function $shell is still missing.
New in 3.78.1:
Fix a problem with automatically remaking makefiles. GNU make uses an
execve to restart itself after a successful remake of the makefile. On
UNIX systems execve replaces the running program with a new one and
resets all signal handling to the default. On VMS execve creates a child
process, signal and exit handlers of the parent are still active, and,
unfortunately, corrupt the exit code from the child. Fix in job.c:
ignore SIGCHLD.
Added some switches to reflect latest features of DECC. Modifications in
makefile.vms.
Set some definitions to reflect latest features of DECC. Modifications in
config.h-vms (which is copied to config.h).
Added extern strcmpi declaration to avoid 'implicitly declared' messages.
Modification in make.h.
Default rule for C++, conditionals for gcc (GCC_IS_NATIVE) or DEC/Digital/
Compaq c/c++ compilers. Modifications in default.c.
Usage of opendir() and friends, suppress file version. Modifications in dir.c.
Added VMS specific code to handle ctrl+c and ctrl+y to abort make.
Modifications in job.c.
Added support to have case sensitive targets and dependencies but to
still use case blind file names. This is especially useful for Java
makefiles on VMS:
.SUFFIXES :
.SUFFIXES : .class .java
.java.class :
javac "$<
HelloWorld.class : HelloWorld.java
A new macro WANT_CASE_SENSITIVE_TARGETS in config.h-vms was introduced.
It needs to be enabled to get this feature; default is disabled. The
macro HAVE_CASE_INSENSITIVE_FS must not be touched: it is still enabled.
Modifications in file.c and config.h-vms.
Bootstrap make to start building make is still makefile.com, but make
needs to be re-made with a make to make a correct version: ignore all
possible warnings, delete all objects, rename make.exe to a different
name and run it.
Made some minor modifications to the bootstrap build makefile.com.
This is the VMS port of GNU Make.
It is based on the VMS port of GNU Make 3.60 by Mike Moretti.
This port was done by Klaus Kämpf <kkaempf@progis.de> of
proGIS Software, Aachen, Germany.
This port was done by Klaus Kämpf <kkaempf@rmi.de>
There is first-level support available from proGIS Software, Germany.
Visit their web-site at http://www.progis.de to get information
about other vms software and forthcoming updates to gnu make.
New for 3.77:
/bin/sh style I/O redirection is supported. You can now write lines like
mcr sys$disk:[]program.exe < input.txt > output.txt &> error.txt
Makefile variables are looked up in the current environment. You can set
symbols or logicals in DCL and evaluate them in the Makefile via
$(<name-of-symbol-or-logical>). Variables defined in the Makefile
override VMS symbols/logicals !
Functions for file names are working now. See the GNU Make manual for
$(dir ...) and $(wildcard ...). Unix-style and VMS-style names are
supported as arguments.
The default rules are set up for GNU C. Building an executable from a
single source file is as easy as 'make file.exe'.
The variable $(ARCH) is predefined as ALPHA or VAX resp. Makefiles for
different VMS systems can now be written by checking $(ARCH) as in
ifeq ($(ARCH),ALPHA)
$(ECHO) "On the Alpha"
else
$(ECHO) "On the VAX"
endif
Command lines of excessive length are correctly broken and written to a
batch file in sys$scratch for later execution. There's no limit to the
lengths of commands (and no need for .opt files :-) any more.
Empty commands are handled correctly and don't end in a new DCL process.
New for 3.76:
John W. Eaton has updated the VMS port to support libraries and VPATH.
To build Make, simply type @makefile. This should compile all the
necessary files and link Make. There is also a file called
@ -12,6 +114,16 @@ Make with this makefile to rebuild.
Here are some notes about GNU Make for VMS:
The cd command is supported if it's called as $(CD). This invokes
the 'builtin_cd' command which changes the directory.
Calling 'set def' doesn't do the trick, since a sub-shell is
spawned for this command, the directory is changed *in this sub-shell*
and the sub-shell ends.
Libraries are not supported. They were in GNU Make 3.60 but somehow I
didn't care porting the code. If there is enough interest, I'll do it at
some later time.
The variable $^ separates files with commas instead of spaces (It's the
natural thing to do for VMS).
@ -26,8 +138,8 @@ The default include directory for including other makefiles is
SYS$SYSROOT:[SYSLIB] (I don't remember why I didn't just use
SYS$LIBRARY: instead; maybe it wouldn't work that way).
The default makefiles make looks for are: makefile.vms, gnumakefile, makefile.,
and gnumakefile. .
The default makefiles make looks for are: makefile.vms, gnumakefile,
makefile., and gnumakefile. .
The stat() function and handling of time stamps in VMS is broken, so I
replaced it with a hack in vmsfunctions.c. I will provide a full rewrite
@ -37,9 +149,9 @@ less than what vms provides. This might be a problem on the faster Alphas.
You can use a : in a filename only if you preceed it with a backslash ('\').
E.g.- hobbes\:[bogas.files]
Make ignores success, informational, or warning errors (-S-, -I-, or -W-).
But it will stop on -E- and -F- errors. (unless you do something to override
this in your makefile, or whatever).
Make ignores success, informational, or warning errors (-S-, -I-, or
-W-). But it will stop on -E- and -F- errors. (unless you do something
to override this in your makefile, or whatever).
Remote stuff isn't implemented yet.
@ -47,18 +159,10 @@ Multiple line DCL commands, such as "if" statements, must be put inside
command files. You can run a command file by using \@.
Change history:
VMS changes made for 3.74.3
3.76.x
======
Added VMS help version (make.hlp) of the Unix man page. To integrate
that with an existing Help library use a command like the following
$lib/ins/help sys$help:helplib.hlb make.hlp
3.74.3
======
Lots of default settings are adapted for VMS. See default.c.
Long command lines are now converted to command files.
Comma (',') as a separator is now allowed. See makefile.vms for an example.

8
rule.c
View file

@ -109,10 +109,14 @@ count_implicit_rule_limits ()
#ifdef VMS
char *p = strrchr (dep->name, ']');
char *p2;
if (p == 0)
p = strrchr (dep->name, ':');
p2 = p != 0 ? strchr (dep->name, '%') : 0;
#else
char *p = strrchr (dep->name, '/');
#endif
char *p2 = p != 0 ? strchr (dep->name, '%') : 0;
#endif
ndeps++;
if (len > max_pattern_dep_length)
@ -140,7 +144,7 @@ count_implicit_rule_limits ()
dep->changed = !dir_file_exists_p (name, "");
#ifdef VMS
if (dep->changed && *name == ']')
if (dep->changed && strchr (name, ':') != 0)
#else
if (dep->changed && *name == '/')
#endif

View file

@ -182,6 +182,63 @@ lookup_variable (name, length)
return v;
}
#ifdef VMS
/* since we don't read envp[] on startup, try to get the
variable via getenv() here. */
{
char *vname = alloca (length + 1);
char *value;
strncpy (vname, name, length);
vname[length] = 0;
value = getenv (vname);
if (value != 0)
{
char *sptr;
int scnt;
sptr = value;
scnt = 0;
while ((sptr = strchr (sptr, '$')))
{
scnt++;
sptr++;
}
if (scnt > 0)
{
char *nvalue;
char *nptr;
nvalue = alloca (length + scnt + 1);
sptr = value;
nptr = nvalue;
while (*sptr)
{
if (*sptr == '$')
{
*nptr++ = '$';
*nptr++ = '$';
}
else
{
*nptr++ = *sptr;
}
sptr++;
}
return define_variable (vname, length, nvalue, o_env, 1);
}
return define_variable (vname, length, value, o_env, 1);
}
}
#endif /* VMS */
return 0;
}
@ -457,6 +514,15 @@ define_automatic_variables ()
/* Define the magic D and F variables in terms of
the automatic variables they are variations of. */
#ifdef VMS
define_variable ("@D", 2, "$(dir $@)", o_automatic, 1);
define_variable ("%D", 2, "$(dir $%)", o_automatic, 1);
define_variable ("*D", 2, "$(dir $*)", o_automatic, 1);
define_variable ("<D", 2, "$(dir $<)", o_automatic, 1);
define_variable ("?D", 2, "$(dir $?)", o_automatic, 1);
define_variable ("^D", 2, "$(dir $^)", o_automatic, 1);
define_variable ("+D", 2, "$(dir $+)", o_automatic, 1);
#else
define_variable ("@D", 2, "$(patsubst %/,%,$(dir $@))", o_automatic, 1);
define_variable ("%D", 2, "$(patsubst %/,%,$(dir $%))", o_automatic, 1);
define_variable ("*D", 2, "$(patsubst %/,%,$(dir $*))", o_automatic, 1);
@ -464,6 +530,7 @@ define_automatic_variables ()
define_variable ("?D", 2, "$(patsubst %/,%,$(dir $?))", o_automatic, 1);
define_variable ("^D", 2, "$(patsubst %/,%,$(dir $^))", o_automatic, 1);
define_variable ("+D", 2, "$(patsubst %/,%,$(dir $+))", o_automatic, 1);
#endif
define_variable ("@F", 2, "$(notdir $@)", o_automatic, 1);
define_variable ("%F", 2, "$(notdir $%)", o_automatic, 1);
define_variable ("*F", 2, "$(notdir $*)", o_automatic, 1);

View file

@ -1,15 +1,21 @@
/* dirent.h for vms */
#ifndef VMSDIR_H
#define VMSDIR_H
#include <rms.h>
#define MAXNAMLEN 255
#ifndef __DECC
#if !defined (__GNUC__) && !defined (__ALPHA)
typedef unsigned long u_long;
typedef unsigned short u_short;
#endif
#endif
struct direct {
struct direct
{
off_t d_off;
u_long d_fileno;
u_short d_reclen;
@ -18,8 +24,11 @@ struct direct {
};
#undef DIRSIZ
#define DIRSIZ(dp) \
(((sizeof (struct direct) - (MAXNAMLEN+1) + ((dp)->d_namlen+1)) + 3) & ~3)
#define DIRSIZ(dp) \
(((sizeof (struct direct) \
- (MAXNAMLEN+1) \
+ ((dp)->d_namlen+1)) \
+ 3) & ~3)
#define d_ino d_fileno /* compatability */
@ -28,15 +37,25 @@ struct direct {
* Definitions for library routines operating on directories.
*/
typedef struct FAB DIR;
typedef struct DIR
{
struct direct dir;
char d_result[MAXNAMLEN + 1];
#if defined (__ALPHA) || defined (__DECC)
struct FAB fab;
#else
struct fabdef fab;
#endif
} DIR;
#ifndef NULL
#define NULL 0
#endif
extern DIR *opendir PARAMS (());
extern struct direct *readdir PARAMS ((DIR *dfd));
#define rewinddir(dirp) seekdir((dirp), (long)0)
extern int closedir PARAMS ((DIR *dfd));
extern char *vmsify PARAMS ((char *name, int type));
/* EOF */
#endif /* VMSDIR_H */

View file

@ -1,7 +1,5 @@
/* vmsfunctions.c */
#define KDEBUG 0
#include "make.h"
#include "debug.h"
@ -21,37 +19,17 @@ DIR *
opendir (dspec)
char *dspec;
{
static struct FAB *dfab;
struct NAM *dnam;
char *searchspec;
struct DIR *dir = (struct DIR *)xmalloc (sizeof (struct DIR));
struct NAM *dnam = (struct NAM *)xmalloc (sizeof (struct NAM));
struct FAB *dfab = &dir->fab;
char *searchspec = (char *)xmalloc (MAXNAMLEN + 1);
dfab = (struct FAB *) xmalloc (sizeof (struct FAB));
if (! dfab)
{
printf ("Error mallocing for FAB\n");
return (NULL);
}
dnam = (struct NAM *) xmalloc (sizeof (struct NAM));
if (! dnam)
{
printf ("Error mallocing for NAM\n");
free (dfab);
return (NULL);
}
searchspec = (char *) xmalloc (MAXNAMLEN + 1);
if (! searchspec)
{
printf ("Error mallocing for searchspec\n");
free (dfab);
free (dnam);
return (NULL);
}
sprintf (searchspec, "%s*.*;", dspec);
memset (dir, 0, sizeof *dir);
*dfab = cc$rms_fab;
*dnam = cc$rms_nam;
sprintf (searchspec, "%s*.*;", dspec);
dfab->fab$l_fna = searchspec;
dfab->fab$b_fns = strlen (searchspec);
dfab->fab$l_nam = dnam;
@ -62,13 +40,13 @@ opendir (dspec)
if (! (sys$parse (dfab) & 1))
{
free (dfab);
free (dir);
free (dnam);
free (searchspec);
return (NULL);
}
return (dfab);
return dir;
}
#define uppercasify(str) \
@ -82,65 +60,59 @@ opendir (dspec)
while (0)
struct direct *
readdir (dfd)
DIR * dfd;
readdir (dir)
DIR * dir;
{
static struct direct *dentry;
static char resultspec[MAXNAMLEN + 1];
struct FAB *dfab = &dir->fab;
struct NAM *dnam = (struct NAM *)(dfab->fab$l_nam);
struct direct *dentry = &dir->dir;
int i;
dentry = (struct direct *) xmalloc (sizeof (struct direct));
if (! dentry)
memset (dentry, 0, sizeof *dentry);
dnam->nam$l_rsa = dir->d_result;
dnam->nam$b_rss = MAXNAMLEN;
if (debug_flag)
printf (".");
if (!((i = sys$search (dfab)) & 1))
{
printf ("Error mallocing for direct\n");
return (NULL);
}
dfd->fab$l_nam->nam$l_rsa = resultspec;
dfd->fab$l_nam->nam$b_rss = MAXNAMLEN;
DB (DB_EXTRA, ("."));
if (!((i = sys$search (dfd)) & 1))
{
DB (DB_EXTRA, ("sys$search failed with %d\n", i));
free (dentry);
if (debug_flag)
printf ("sys$search failed with %d\n", i);
return (NULL);
}
dentry->d_off = 0;
if (dfd->fab$l_nam->nam$w_fid == 0)
if (dnam->nam$w_fid == 0)
dentry->d_fileno = 1;
else
dentry->d_fileno = dfd->fab$l_nam->nam$w_fid[0]
+ dfd->fab$l_nam->nam$w_fid[1] << 16;
dentry->d_fileno = dnam->nam$w_fid[0] + (dnam->nam$w_fid[1] << 16);
dentry->d_reclen = sizeof (struct direct);
#if 0
if (!strcmp(dfd->fab$l_nam->nam$l_type, ".DIR"))
dentry->d_namlen = dfd->fab$l_nam->nam$b_name;
else
#endif
dentry->d_namlen = dfd->fab$l_nam->nam$b_name + dfd->fab$l_nam->nam$b_type;
strncpy (dentry->d_name, dfd->fab$l_nam->nam$l_name, dentry->d_namlen);
dentry->d_namlen = dnam->nam$b_name + dnam->nam$b_type;
strncpy (dentry->d_name, dnam->nam$l_name, dentry->d_namlen);
dentry->d_name[dentry->d_namlen] = '\0';
uppercasify (dentry->d_name);
#if 0
uvUnFixRCSSeparator(dentry->d_name);
#endif
return (dentry);
}
closedir (dfd)
DIR *dfd;
int
closedir (dir)
DIR *dir;
{
if (dfd)
if (dir != NULL)
{
if (dfd->fab$l_nam)
free (dfd->fab$l_nam->nam$l_esa);
free (dfd->fab$l_nam);
free (dfd);
struct FAB *dfab = &dir->fab;
struct NAM *dnam = (struct NAM *)(dfab->fab$l_nam);
if (dnam != NULL)
free (dnam->nam$l_esa);
free (dnam);
free (dir);
}
return 0;
}
#endif /* compiled for OpenVMS prior to V7.x */
@ -227,7 +199,7 @@ vms_stat (name, buf)
/* Initialize the FIB */
for (i = 0; i < 3; i++)
{
#if __DECC
#ifndef __VAXC
Fib.fib$w_fid[i] = Nam.nam$w_fid[i];
Fib.fib$w_did[i] = Nam.nam$w_did[i];
#else
@ -275,3 +247,33 @@ cvt_time (tval)
return (str);
}
int
strcmpi (s1, s2)
const char *s1;
const char *s2;
{
while (*s1 != '\0' && toupper(*s1) == toupper(*s2))
{
s1++;
s2++;
}
return toupper(*(unsigned char *) s1) - toupper(*(unsigned char *) s2);
}
int
strcmpi (s1, s2)
const char *s1;
const char *s2;
{
while (*s1 != '\0' && toupper(*s1) == toupper(*s2))
{
s1++;
s2++;
}
return toupper(*(unsigned char *) s1) - toupper(*(unsigned char *) s2);
}

221
vmsify.c
View file

@ -8,6 +8,7 @@
*/
#include <stdio.h>
#include <string.h>
#include <ctype.h>
@ -78,8 +79,8 @@ copyto (char **to, char **from, char upto, int as_dir)
}
else
{
if (islower ((unsigned char)**from))
**to = toupper ((unsigned char)**from);
if (isupper ((unsigned char)**from))
**to = tolower ((unsigned char)**from);
else
**to = **from;
}
@ -127,6 +128,27 @@ trnlog (char *name)
return s;
}
static char *
showall (char *s)
{
static char t[512];
char *pt;
pt = t;
if (strchr (s, '\\') == 0)
return s;
while (*s)
{
if (*s == '\\')
{
*pt++ = *s;
}
*pt++ = *s++;
}
return pt;
}
enum namestate { N_START, N_DEVICE, N_OPEN, N_DOT, N_CLOSED, N_DONE };
/*
@ -205,16 +227,39 @@ vmsify (name, type)
s = strpbrk (name, "$:");
if (s != 0)
{
char *s1;
char *s2;
if (type == 1)
{
s1 = strchr (s+1, '[');
s2 = strchr (s+1, ']');
}
if (*s == '$')
{
if (strchr (name, '/') == 0)
{
return name;
if ((type == 1) && (s1 != 0) && (s2 == 0))
{
strcpy (vmsname, name);
strcat (vmsname, "]");
return vmsname;
}
else
return name;
}
}
else
{
return name;
if ((type == 1) && (s1 != 0) && (s2 == 0))
{
strcpy (vmsname, name);
strcat (vmsname, "]");
return vmsname;
}
else
return name;
}
}
@ -227,7 +272,15 @@ vmsify (name, type)
s1 = strchr (s+1, '[');
if (s1 == 0)
{
return name; /* single [, keep unchanged */
if ((type == 1)
&& (strchr (s+1, ']') == 0))
{
strcpy (vmsname, name);
strcat (vmsname, "]");
return vmsname;
}
else
return name; /* single [, keep unchanged */
}
s1--;
if (*s1 != ']')
@ -403,7 +456,7 @@ vmsify (name, type)
{
if (*(s2-1) == '.') /* ends in '.]' */
{
if (!strneq (fptr, "000000", 6))
if (strncmp (fptr, "000000", 6) != 0)
rooted = 0;
}
else
@ -727,21 +780,48 @@ vmsify (name, type)
while (*fptr == '/');
}
{ /* got '..' or '../' */
nstate = N_OPEN;
*vptr++ = '[';
while (count--)
*vptr++ = '-';
char cwdbuf[MAXPATHLEN+1];
if (*fptr == 0) /* had '..' or '../' */
s1 = getcwd(cwdbuf, MAXPATHLEN);
if (s1 == 0)
{
*vptr++ = ']';
state = -1;
return ""; /* FIXME, err getcwd */
}
else /* had '../xxx' */
strcpy (vptr, s1);
s = strchr (vptr, ']');
if (s != 0)
{
state = 9;
nstate = N_OPEN;
while (s > vptr)
{
s--;
if (*s == '[')
{
s++;
strcpy (s, "000000]");
state = -1;
break;
}
else if (*s == '.')
{
if (--count == 0)
{
if (*fptr == 0) /* had '..' or '../' */
{
*s++ = ']';
state = -1;
}
else /* had '../xxx' */
{
state = 9;
}
*s = 0;
break;
}
}
}
}
*vptr = 0;
vptr += strlen (vptr);
}
break;
@ -752,89 +832,38 @@ vmsify (name, type)
{
return name;
}
fptr++;
while (*fptr == '/')
fptr++;
}
if (*fptr)
{
state = 9;
{
char cwdbuf[MAXPATHLEN+1];
switch (type)
{
case 0:
nstate = N_CLOSED;
*vptr++ = '[';
*vptr++ = ']';
break;
case 1:
nstate = N_OPEN;
*vptr++ = '[';
break;
case 2:
nstate = N_CLOSED;
break;
}
}
else
{
if (type == 1)
{
*vptr++ = '[';
*vptr++ = ']';
state = -1;
}
else
{
char cwdbuf[MAXPATHLEN+1];
s1 = getcwd(cwdbuf, MAXPATHLEN);
if (s1 == 0)
{
return "foo"; /*FIXME, err getcwd */
}
strcpy (vptr, s1);
vptr += strlen (vptr);
if (type == 2)
{
s = vptr;
while (s > vmsname)
{
if (*s == '.')
{
*s = ']';
vptr--;
break;
}
if (*s == '[')
{
int i;
char *t = vptr - 2;
while (t > s)
{
*(t+7) = *t;
t--;
}
s++;
for (i = 0; i < 6; i++)
*s++ = '0';
*s = ']';
vptr += 6;
break;
}
s--;
}
strcpy (vptr, ".dir");
vptr += 4;
}
state = -1;
}
}
s1 = getcwd(cwdbuf, MAXPATHLEN);
if (s1 == 0)
{
return ""; /*FIXME, err getcwd */
}
strcpy (vptr, s1);
if (*fptr == 0)
{
state = -1;
break;
}
else
{
s = strchr (vptr, ']');
if (s == 0)
{
state = -1;
break;
}
*s = 0;
nstate = N_OPEN;
vptr += strlen (vptr);
state = 9;
}
}
break;
}