diff --git a/ChangeLog b/ChangeLog index 175081c1..3e37cd0b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2000-01-21 Paul D. Smith + + Installed patches for the VMS port. + Patches provided by: Hartmut Becker + + * 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 Resolve PR/xxxx: don't automatically evaluate the $(call ...) diff --git a/NEWS b/NEWS index 0b96212a..1cd9ef64 100644 --- a/NEWS +++ b/NEWS @@ -1,8 +1,8 @@ GNU make NEWS -*-indented-text-*- History of user-visible changes. - 21 Nov 1999 + 21 Jan 2000 -Copyright (C) 1992,93,94,95,96,97,98,1999 Free Software Foundation, Inc. +Copyright (C) 1992,93,94,95,96,97,98,99,2000 Free Software Foundation, Inc. See the end for copying conditions. All changes mentioned here are more fully described in the GNU make @@ -43,6 +43,9 @@ Version 3.79 a minimal amount information is generated, displaying the names of "normal" targets (not makefiles) were deemed out of date and in need of being rebuilt. + +* Hartmut Becker provided many updates for the VMS port of GNU make. + See the readme.vms file for more details. Version 3.78 diff --git a/arscan.c b/arscan.c index 6ff27154..2b907058 100644 --- a/arscan.c +++ b/arscan.c @@ -78,7 +78,9 @@ VMS_get_member_info (module, rfa) mhd = (struct mhddef *) filename; +#ifdef __DECC val = decc$fix_time (&mhd->mhd$l_datim); +#endif for (i = 0; i < module->dsc$w_length; i++) filename[i] = _tolower ((unsigned char)module->dsc$a_pointer[i]); diff --git a/config.h-vms.template b/config.h-vms.template index 64882551..e2dd0264 100644 --- a/config.h-vms.template +++ b/config.h-vms.template @@ -1,4 +1,4 @@ -/* config.h-vms. Generated by hand by Klaus Kämpf */ +/* config.h-vms. Generated by hand by Klaus Kämpf */ /* 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 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 -#include -#include - /* 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 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 header file. */ -/* #undef HAVE_DIRENT_H */ +#define HAVE_DIRENT_H 1 /* Define if you have the header file. */ #ifdef __DECC @@ -302,36 +307,55 @@ /* #undef HAVE_SYS_PARAM_H */ /* Define if you have the header file. */ +#ifndef __GNUC__ #define HAVE_SYS_TIMEB_H 1 +#endif /* Define if you have the header file. */ /* #undef HAVE_SYS_WAIT_H */ -/* Define if you have the 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 +/* Don't use RTL functions of OpenVMS */ +#ifdef __DECC +#include +#include #define getopt gnu_getopt #define optarg gnu_optarg #define optopt gnu_optopt #define optind gnu_optind #define opterr gnu_opterr +#endif #if defined (__cplusplus) || (defined (__STDC__) && __STDC__) #undef PARAMS diff --git a/default.c b/default.c index 8ad37e1a..e50813df 100644 --- a/default.c +++ b/default.c @@ -38,8 +38,8 @@ Boston, MA 02111-1307, USA. */ static char default_suffixes[] #ifdef VMS - = ".exe .olb .ln .obj .c .cc .pas .p .for .f .r .y .l .mar \ -.mod .sym .def .h .info .dvi .tex .texinfo .texi .txinfo \ + = ".exe .olb .ln .obj .c .cxx .cc .pas .p .for .f .r .y .l .mar \ +.s .ss .i .ii .mod .sym .def .h .info .dvi .tex .texinfo .texi .txinfo \ .w .ch .cweb .web .com .sh .elc .el"; #else = ".out .a .ln .o .c .cc .C .cpp .p .f .F .r .y .l .s .S \ @@ -108,13 +108,21 @@ static char *default_suffix_rules[] = { #ifdef VMS ".obj.exe", - "$(LINK.obj) $^ $(LOADLIBES) $(LDLIBS) /exe=$@", + "$(LINK.obj) $^ $(LOADLIBES) $(LDLIBS) $(CRT0) /exe=$@", ".mar.exe", - "$(LINK.mar) $^ $(LOADLIBES) $(LDLIBS) /exe=$@", + "$(COMPILE.mar) $^ \n $(LINK.obj) $(subst .mar,.obj,$^) $(LOADLIBES) $(LDLIBS) $(CRT0) /exe=$@", + ".s.exe", + "$(COMPILE.s) $^ \n $(LINK.obj) $(subst .s,.obj,$^) $(LOADLIBES) $(LDLIBS) $(CRT0) /exe=$@", ".c.exe", - "$(COMPILE.c) $^ \n $(LINK.obj) $(subst .c,.obj,$^) $(LOADLIBES) $(LDLIBS) /exe=$@", + "$(COMPILE.c) $^ \n $(LINK.obj) $(subst .c,.obj,$^) $(LOADLIBES) $(LDLIBS) $(CRT0) /exe=$@", ".cc.exe", - "$(COMPILE.cc) $^ \n $(LINK.obj) $(subst .cc,.obj,$^) $(LOADLIBES) $(LDLIBS) /exe=$@", +#ifdef GCC_IS_NATIVE + "$(COMPILE.cc) $^ \n $(LINK.obj) $(CXXSTARTUP),sys$$disk:[]$(subst .cc,.obj,$^) $(LOADLIBES) $(LXLIBS) $(LDLIBS) $(CXXRT0) /exe=$@", +#else + "$(COMPILE.cc) $^ \n $(CXXLINK.obj) $(subst .cc,.obj,$^) $(LOADLIBES) $(LXLIBS) $(LDLIBS) $(CXXRT0) /exe=$@", + ".cxx.exe", + "$(COMPILE.cxx) $^ \n $(CXXLINK.obj) $(subst .cxx,.obj,$^) $(LOADLIBES) $(LXLIBS) $(LDLIBS) $(CXXRT0) /exe=$@", +#endif ".for.exe", "$(COMPILE.for) $^ \n $(LINK.obj) $(subst .for,.obj,$^) $(LOADLIBES) $(LDLIBS) /exe=$@", ".pas.exe", @@ -125,8 +133,24 @@ static char *default_suffix_rules[] = ".mar.obj", "$(COMPILE.mar) /obj=$@ $<", + ".s.obj", + "$(COMPILE.s) /obj=$@ $<", + ".ss.obj", + "$(COMPILE.s) /obj=$@ $<", + ".c.i", + "$(COMPILE.c)/prep /list=$@ $<", + ".c.s", + "$(COMPILE.c)/noobj/machine /list=$@ $<", + ".i.s", + "$(COMPILE.c)/noprep/noobj/machine /list=$@ $<", ".c.obj", "$(COMPILE.c) /obj=$@ $<", + ".cc.ii", + "$(COMPILE.cc)/prep /list=$@ $<", + ".cc.ss", + "$(COMPILE.cc)/noobj/machine /list=$@ $<", + ".ii.ss", + "$(COMPILE.cc)/noprep/noobj/machine /list=$@ $<", ".cc.obj", "$(COMPILE.cc) /obj=$@ $<", ".for.obj", @@ -276,12 +300,31 @@ static char *default_suffix_rules[] = static char *default_variables[] = { #ifdef VMS +#ifdef __ALPHA + "ARCH", "ALPHA", +#else + "ARCH", "VAX", +#endif "AR", "library/obj", "ARFLAGS", "/replace", "AS", "macro", + "MACRO", "macro", +#ifdef GCC_IS_NATIVE + "CC", "gcc", +#else "CC", "cc", +#endif + "CD", "builtin_cd", + "MAKE", "make", + "ECHO", "write sys$$output \"", +#ifdef GCC_IS_NATIVE "C++", "gcc/plus", "CXX", "gcc/plus", +#else + "C++", "cxx", + "CXX", "cxx", + "CXXLD", "cxxlink", +#endif "CO", "co", "CPP", "$(CC) /preprocess_only", "FC", "fortran", @@ -292,21 +335,43 @@ static char *default_variables[] = "LD", "link", "LEX", "lex", "PC", "pascal", - "YACC", "yacc", /* Or "bison -y" */ + "YACC", "bison/yacc", + "YFLAGS", "/Define/Verbose", + "BISON", "bison", "MAKEINFO", "makeinfo", "TEX", "tex", "TEXINDEX", "texindex", "RM", "delete/nolog", + "CSTARTUP", "", +#ifdef GCC_IS_NATIVE + "CRT0", ",sys$$library:vaxcrtl.olb/lib,gnu_cc_library:crt0.obj", + "CXXSTARTUP", "gnu_cc_library:crtbegin.obj", + "CXXRT0", ",sys$$library:vaxcrtl.olb/lib,gnu_cc_library:crtend.obj,gnu_cc_library:gxx_main.obj", + "LXLIBS", ",gnu_cc_library:libstdcxx.olb/lib,gnu_cc_library:libgccplus.olb/lib", + "LDLIBS", ",gnu_cc_library:libgcc.olb/lib", +#else + "CRT0", "", + "CXXSTARTUP", "", + "CXXRT0", "", + "LXLIBS", "", + "LDLIBS", "", +#endif + "LINK.obj", "$(LD) $(LDFLAGS)", +#ifndef GCC_IS_NATIVE + "CXXLINK.obj", "$(CXXLD) $(LDFLAGS)", + "COMPILE.cxx", "$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH)", +#endif "COMPILE.c", "$(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH)", - "COMPILE.cc", "$(C++) $(C++FLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c", + "COMPILE.cc", "$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH)", "YACC.y", "$(YACC) $(YFLAGS)", "LEX.l", "$(LEX) $(LFLAGS)", "COMPILE.for", "$(FC) $(FFLAGS) $(TARGET_ARCH)", "COMPILE.pas", "$(PC) $(PFLAGS) $(CPPFLAGS) $(TARGET_ARCH)", - "COMPILE.mar", "$(AS) $(ASFLAGS) $(TARGET_MACH)", + "COMPILE.mar", "$(MACRO) $(MACROFLAGS)", + "COMPILE.s", "$(AS) $(ASFLAGS) $(TARGET_MACH)", "LINT.c", "$(LINT) $(LINTFLAGS) $(CPPFLAGS) $(TARGET_ARCH)", "MV", "rename/new_version", diff --git a/dir.c b/dir.c index 5fa1d349..ccc5163a 100644 --- a/dir.c +++ b/dir.c @@ -22,6 +22,9 @@ Boston, MA 02111-1307, USA. */ #ifdef HAVE_DIRENT_H # include # 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, defines this macro for us. */ #ifdef _D_NAMLEN -#undef NAMLEN -#define NAMLEN(d) _D_NAMLEN(d) +# undef NAMLEN +# define NAMLEN(d) _D_NAMLEN(d) #endif -#if (defined (POSIX) || defined (WINDOWS32)) && !defined (__GNU_LIBRARY__) +#if (defined (POSIX) || defined (VMS) || defined (WINDOWS32)) && !defined (__GNU_LIBRARY__) /* Posix does not require that the d_ino field be present, and some systems do not provide it. */ -#define REAL_DIR_ENTRY(dp) 1 -#define FAKE_DIR_ENTRY(dp) +# define REAL_DIR_ENTRY(dp) 1 +# define FAKE_DIR_ENTRY(dp) #else -#define REAL_DIR_ENTRY(dp) (dp->d_ino != 0) -#define FAKE_DIR_ENTRY(dp) (dp->d_ino = 1) +# define REAL_DIR_ENTRY(dp) (dp->d_ino != 0) +# define FAKE_DIR_ENTRY(dp) (dp->d_ino = 1) #endif /* POSIX */ #ifdef __MSDOS__ @@ -156,7 +159,8 @@ vms_hash (name) while (*name) { - h = (h << 4) + *name++; + h = (h << 4) + (isupper (*name) ? tolower (*name) : *name); + name++; g = h & 0xf0000000; if (g) { @@ -333,12 +337,12 @@ find_directory (name) if (vmsstat_dir (name, &st) < 0) #else -#ifdef WINDOWS32 +# ifdef WINDOWS32 /* Remove any trailing '\'. Windows32 stat fails even on valid directories if they end in '\'. */ if (p[-1] == '\\') p[-1] = '\0'; -#endif +# endif if (stat (name, &st) < 0) #endif { @@ -356,14 +360,14 @@ find_directory (name) w32_path = w32ify(name, 1); hash = ((unsigned int) st.st_dev << 16) | (unsigned int) st.st_ctime; #else -#ifdef VMS - hash = ((unsigned int) st.st_dev << 16) - | ((unsigned int) st.st_ino[0] - + (unsigned int) st.st_ino[1] - + (unsigned int) st.st_ino[2]); -#else +# ifdef VMS + hash = (((unsigned int) st.st_dev << 16) + | ((unsigned int) st.st_ino[0] + + (unsigned int) st.st_ino[1] + + (unsigned int) st.st_ino[2])); +# else hash = ((unsigned int) st.st_dev << 16) | (unsigned int) st.st_ino; -#endif +# endif #endif hash %= DIRECTORY_BUCKETS; @@ -372,13 +376,14 @@ find_directory (name) if (strieq(dc->path_key, w32_path)) #else if (dc->dev == st.st_dev -#ifdef VMS +# ifdef VMS && dc->ino[0] == st.st_ino[0] && dc->ino[1] == st.st_ino[1] - && dc->ino[2] == st.st_ino[2]) -#else - && dc->ino == st.st_ino) -#endif + && dc->ino[2] == st.st_ino[2] +# else + && dc->ino == st.st_ino +# endif + ) #endif /* WINDOWS32 */ break; @@ -413,24 +418,22 @@ find_directory (name) else dc->fs_flags = FS_UNKNOWN; #else -#ifdef VMS +# ifdef VMS dc->ino[0] = st.st_ino[0]; dc->ino[1] = st.st_ino[1]; dc->ino[2] = st.st_ino[2]; -#else +# else dc->ino = st.st_ino; -#endif +# endif #endif /* WINDOWS32 */ dc->next = directories_contents[hash]; directories_contents[hash] = dc; dc->dirstream = opendir (name); if (dc->dirstream == 0) - { - /* Couldn't open the directory. Mark this by - setting the `files' member to a nil pointer. */ - dc->files = 0; - } + /* Couldn't open the directory. Mark this by + setting the `files' member to a nil pointer. */ + dc->files = 0; else { /* Allocate an array of buckets for files and zero it. */ @@ -553,6 +556,14 @@ dir_contents_file_exists_p (dir, filename) unsigned int len; register unsigned int i; +#if defined(VMS) && defined(HAVE_DIRENT_H) + /* In VMS we get file versions too, which have to be stripped off */ + { + char *p = strrchr (d->d_name, ';'); + if (p) + *p = '\0'; + } +#endif if (!REAL_DIR_ENTRY (d)) continue; @@ -636,6 +647,8 @@ file_exists_p (name) #ifdef VMS dirend = strrchr (name, ']'); + if (dirend == 0) + dirend = strrchr (name, ':'); dirend++; if (dirend == (char *)1) return dir_file_exists_p ("[]", name); @@ -694,6 +707,8 @@ file_impossible (filename) #ifdef VMS dirend = strrchr (p, ']'); + if (dirend == 0) + dirend = strrchr (name, ':'); dirend++; if (dirend == (char *)1) dir = find_directory ("[]"); diff --git a/file.c b/file.c index 1ce4b89d..f790eb15 100644 --- a/file.c +++ b/file.c @@ -54,7 +54,7 @@ lookup_file (name) register struct file *f; register char *n; register unsigned int hashval; -#ifdef VMS +#if defined(VMS) && !defined(WANT_CASE_SENSITIVE_TARGETS) register char *lname, *ln; #endif @@ -65,11 +65,13 @@ lookup_file (name) for names read from makefiles. It is here for names passed on the command line. */ #ifdef VMS +# ifndef WANT_CASE_SENSITIVE_TARGETS lname = (char *)malloc(strlen(name) + 1); for (n=name, ln=lname; *n != '\0'; ++n, ++ln) *ln = isupper((unsigned char)*n) ? tolower((unsigned char)*n) : *n; *ln = '\0'; name = lname; +# endif while (name[0] == '[' && name[1] == ']' && name[2] != '\0') name += 2; @@ -103,13 +105,13 @@ lookup_file (name) { if (strieq (f->hname, name)) { -#ifdef VMS +#if defined(VMS) && !defined(WANT_CASE_SENSITIVE_TARGETS) free (lname); #endif return f; } } -#ifdef VMS +#if defined(VMS) && !defined(WANT_CASE_SENSITIVE_TARGETS) free (lname); #endif return 0; @@ -122,14 +124,14 @@ enter_file (name) register struct file *f, *new; register char *n; register unsigned int hashval; -#ifdef VMS +#if defined(VMS) && !defined(WANT_CASE_SENSITIVE_TARGETS) char *lname, *ln; #endif if (*name == '\0') abort (); -#ifdef VMS +#if defined(VMS) && !defined(WANT_CASE_SENSITIVE_TARGETS) lname = (char *)malloc (strlen (name) + 1); for (n = name, ln = lname; *n != '\0'; ++n, ++ln) { @@ -139,6 +141,8 @@ enter_file (name) *ln = *n; } *ln = 0; + /* Creates a possible leak, old value of name is unreachable, but I + currently don't know how to fix it. */ name = lname; #endif @@ -153,7 +157,7 @@ enter_file (name) if (f != 0 && !f->double_colon) { -#ifdef VMS +#if defined(VMS) && !defined(WANT_CASE_SENSITIVE_TARGETS) free(lname); #endif return f; diff --git a/glob/glob.c b/glob/glob.c index 65055fb7..4bbf7bb0 100644 --- a/glob/glob.c +++ b/glob/glob.c @@ -299,6 +299,12 @@ static int glob_in_dir __P ((const char *pattern, const char *directory, static int prefix_array __P ((const char *prefix, char **array, size_t n)); static int collated_compare __P ((const __ptr_t, const __ptr_t)); +#ifdef VMS +/* these compilers like prototypes */ +#if !defined _LIBC || !defined NO_GLOB_PATTERN_P +int __glob_pattern_p (const char *pattern, int quote); +#endif +#endif /* Find the end of the sub-pattern in a brace expression. We define this as an inline function if the compiler permits. */ @@ -609,7 +615,12 @@ glob (pattern, flags, errfunc, pglob) if (dirname[1] == '\0' || dirname[1] == '/') { /* Look up home directory. */ - const char *home_dir = getenv ("HOME"); +#ifdef VMS +/* This isn't obvious, RTLs of DECC and VAXC know about "HOME" */ + const char *home_dir = getenv ("SYS$LOGIN"); +#else + const char *home_dir = getenv ("HOME"); +#endif # ifdef _AMIGA if (home_dir == NULL || home_dir[0] == '\0') home_dir = "SYS:"; @@ -618,6 +629,11 @@ glob (pattern, flags, errfunc, pglob) if (home_dir == NULL || home_dir[0] == '\0') home_dir = "c:/users/default"; /* poor default */ # else +# ifdef VMS +/* Again, this isn't obvious, if "HOME" isn't known "SYS$LOGIN" should be set */ + if (home_dir == NULL || home_dir[0] == '\0') + home_dir = "SYS$DISK:[]"; +# else if (home_dir == NULL || home_dir[0] == '\0') { int success; @@ -676,6 +692,7 @@ glob (pattern, flags, errfunc, pglob) else home_dir = "~"; /* No luck. */ } +# endif /* VMS */ # endif /* WINDOWS32 */ # endif /* Now construct the full directory. */ @@ -696,7 +713,7 @@ glob (pattern, flags, errfunc, pglob) dirname = newp; } } -# if !defined _AMIGA && !defined WINDOWS32 +# if !defined _AMIGA && !defined WINDOWS32 && !defined VMS else { char *end_name = strchr (dirname, '/'); @@ -776,7 +793,7 @@ glob (pattern, flags, errfunc, pglob) home directory. */ return GLOB_NOMATCH; } -# endif /* Not Amiga && not WINDOWS32. */ +# endif /* Not Amiga && not WINDOWS32 && not VMS. */ } #endif /* Not VMS. */ @@ -1213,6 +1230,10 @@ glob_in_dir (pattern, directory, flags, errfunc, pglob) int meta; int save; +#ifdef VMS + if (*directory == 0) + directory = "[]"; +#endif meta = __glob_pattern_p (pattern, !(flags & GLOB_NOESCAPE)); if (meta == 0) { diff --git a/glob/glob.h b/glob/glob.h index 7c2a67a1..9f735fe8 100644 --- a/glob/glob.h +++ b/glob/glob.h @@ -51,7 +51,15 @@ extern "C" { typedef __SIZE_TYPE__ __size_t; # else /* This is a guess. */ +/*hb + * Conflicts with DECCs aready defined type __size_t. + * Defining an own type with a name beginning with '__' is no good. + * Anyway if DECC is used and __SIZE_T is defined then __size_t is + * already defined (and I hope it's exactly the one we need here). + */ +#if !(defined __DECC && defined __SIZE_T) typedef unsigned long int __size_t; +#endif # endif #else /* The GNU CC stddef.h version defines __size_t as empty. We need a real @@ -118,7 +126,11 @@ typedef struct struct dirent *(*gl_readdir) __PMT ((void *)); __ptr_t (*gl_opendir) __PMT ((__const char *)); int (*gl_lstat) __PMT ((__const char *, struct stat *)); +#if defined(VMS) && defined(__DECC) && !defined(_POSIX_C_SOURCE) + int (*gl_stat) __PMT ((__const char *, struct stat *, ...)); +#else int (*gl_stat) __PMT ((__const char *, struct stat *)); +#endif } glob_t; #ifdef _LARGEFILE64_SOURCE diff --git a/implicit.c b/implicit.c index 4156402a..c0ca4ed7 100644 --- a/implicit.c +++ b/implicit.c @@ -163,6 +163,8 @@ pattern_search (file, archive, depth, recursions) bar/ in directory foo/, not empty in directory foo/bar/.) */ #ifdef VMS lastslash = strrchr (filename, ']'); + if (lastslash == 0) + lastslash = strrchr (filename, ':'); #else lastslash = strrchr (filename, '/'); #if defined(__MSDOS__) || defined(WINDOWS32) @@ -225,7 +227,9 @@ pattern_search (file, archive, depth, recursions) prefix and the target pattern does not contain a slash. */ #ifdef VMS - check_lastslash = lastslash != 0 && strchr (target, ']') == 0; + check_lastslash = lastslash != 0 + && ((strchr (target, ']') == 0) + && (strchr (target, ':') == 0)); #else check_lastslash = lastslash != 0 && strchr (target, '/') == 0; #endif diff --git a/job.c b/job.c index c920b9f0..c4e30c9b 100644 --- a/job.c +++ b/job.c @@ -46,7 +46,12 @@ extern int MyExecute (char **); directories we could trust). */ char *default_shell = "command.com"; # else /* __MSDOS__ */ +# ifdef VMS +# include +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 -# include +# ifndef __GNUC__ +# include +# endif # include # include #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 +#include +#include + +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 diff --git a/make.h b/make.h index 8f1b0577..18eb1c9d 100644 --- a/make.h +++ b/make.h @@ -312,6 +312,9 @@ extern char *alloca (); # define strieq(a, b) (strcmp ((a), (b)) == 0) #endif #define strneq(a, b, l) (strncmp ((a), (b), (l)) == 0) +#ifdef VMS +extern int strcmpi (const char *,const char *); +#endif /* Add to VAR the hashing value of C, one character in a name. */ #define HASH(var, c) \ @@ -449,10 +452,9 @@ extern long int lseek (); #endif /* Not GNU C library or POSIX. */ #ifdef HAVE_GETCWD +# if !defined(VMS) && !defined(__DECC) extern char *getcwd (); -# ifdef VMS -extern char *getwd PARAMS ((char *)); -# endif +#endif #else extern char *getwd (); # define getcwd(buf, len) getwd (buf) diff --git a/makefile.com b/makefile.com index f180df20..5a0f884c 100644 --- a/makefile.com +++ b/makefile.com @@ -7,6 +7,13 @@ $! P2 = DEBUG will build an image with debug information $! $! In case of problems with the install you might contact me at $! zinser@decus.decus.de (preferred) or martin_zinser@exchange.de +$ +$! hb +$! But don't ask Martin Zinser about the lines, I added/changed. +$! In case of an error do some cleanup +$ on error then $ goto cleanup +$! in case somebody set up her/his own symbol for cc +$ set symbol/scope=(nolocal,noglobal) $! $! Look for the compiler used $! @@ -57,9 +64,16 @@ $ linkit: $ close optf $ if p1 .nes. "" then goto link_using_library $ link/exe=make make.opt/opt'lopt -$ exit +$ goto cleanup +$ $ link_using_library: $ link/exe=make make.opt/opt,sys$library:vaxcrtl/lib'lopt +$ +$ cleanup: +$ if f$trnlnm("SYS").nes."" then $ deassign sys +$ if f$trnlnm("OPTF").nes."" then $ close optf +$ if f$search("make.opt").nes."" then $ del make.opt;* +$ exit $! $ compileit : subroutine $ ploc = f$locate("]",p1) diff --git a/makefile.vms b/makefile.vms index 9b8208a2..9a780d86 100644 --- a/makefile.vms +++ b/makefile.vms @@ -2,7 +2,8 @@ # This file is part of GNU Make. # # VMS extensions from GNU Make 3.60 imported by -# Klaus Kämpf (kkaempf@progis.de) of proGIS Software, Aachen, Germany +# Klaus Kämpf (kkaempf@rmi.de) +# Modified for version 3.78.1 by Hartmut.Becker@compaq.com. # # GNU Make is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -19,7 +20,7 @@ # the Free Software Foundation, Inc., 59 Temple Place - Suite 330, # Boston, MA 02111-1307, USA. -CC = cc/warn +CC = cc CP = copy %.obj: %.c @@ -28,11 +29,23 @@ CP = copy # Makefile for GNU Make # -CFLAGS = $(defines) /debug/noopt/include=([],[.glob]) +ifeq ($(CC),cc) +CFLAGS = $(defines) /include=([],[.glob])/prefix=all/standard=relaxed +else +CFLAGS = $(defines) /include=([],[.glob]) +endif #LDFLAGS = /deb LDFLAGS = +ifeq ($(CC),cc) defines = /define=("unlink=remove","HAVE_CONFIG_H","VMS","allocated_variable_expand_for_file=alloc_var_expand_for_file") +else +ifeq ($(ARCH),VAX) +defines = /define=("HAVE_CONFIG_H","GCC_IS_NATIVE","VAX") +else +defines = /define=("HAVE_CONFIG_H","GCC_IS_NATIVE") +endif +endif LOAD_AVG = /define="NO_LDAV" @@ -44,12 +57,17 @@ ARCHIVES_SRC = ar.c arscan.c # System V probably need -lPW for alloca. # if on vax, uncomment the following line #LOADLIBES = ,c.opt/opt -LOADLIBES =,sys$$library:vaxcrtl.olb/lib +ifeq ($(CC),cc) +#LOADLIBES =,sys$$library:vaxcrtl.olb/lib +CRT0 = +else +LOADLIBES =,gnu_cc_library:libgcc.olb/lib +endif # If your system doesn't have alloca, or the one provided is bad, # get it from the Emacs distribution and define these. -ALLOCA = ,alloca.obj -ALLOCASRC = alloca.c +#ALLOCA = ,alloca.obj +#ALLOCASRC = alloca.c # If there are remote execution facilities defined, # enable them with switches here (see remote-*.c). @@ -86,11 +104,14 @@ doc: make.info make.dvi make.exe: $(objs) - $(LD)$(LDFLAGS)/exe=$@ $^$(LOADLIBES) + $(LD)$(LDFLAGS)/exe=$@ $^$(LOADLIBES)$(CRT0) .PHONY: clean realclean clean: - -$(RM) make.exe;,*.obj;* + $$ purge [...] + -$(RM) make.exe;,*.obj; + -$(RM) *.opt; + -$(RM) [.glob]*.obj; # Automatically generated dependencies. commands.obj: commands.c make.h dep.h commands.h filedef.h variable.h job.h @@ -108,7 +129,7 @@ variable.obj: variable.c make.h commands.h variable.h dep.h filedef.h expand.obj: expand.c make.h commands.h filedef.h variable.h function.obj: function.c make.h variable.h dep.h commands.h job.h vpath.obj: vpath.c make.h filedef.h variable.h -version.obj: version.c +version.obj: version.c config.h arscan.obj: arscan.c ar.obj: ar.c make.h filedef.h signame.obj: signame.c @@ -117,6 +138,8 @@ remote-stub.obj: remote-stub.c [.glob]fnmatch.obj: [.glob]fnmatch.c getopt.obj: getopt.c getopt1.obj: getopt1.c +vmsfunctions.obj: vmsfunctions.c make.h vmsdir.h +vmsify.obj: vmsify.c make.h config.h: config.h-vms $(CP) $< $@ diff --git a/readme.vms b/readme.vms index 43b4dd07..dacc3940 100644 --- a/readme.vms +++ b/readme.vms @@ -1,9 +1,111 @@ +This is the VMS port of GNU Make done by Hartmut.Becker@compaq.com. + +It is based on the specific version 3.77k and on 3.78.1. 3.77k was done +by Klaus Kämpf , 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 of -proGIS Software, Aachen, Germany. +This port was done by Klaus Kämpf + +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 +$(). Variables defined in the Makefile +override VMS symbols/logicals ! + +Functions for file names are working now. See the GNU Make manual for +$(dir ...) and $(wildcard ...). Unix-style and VMS-style names are +supported as arguments. + +The default rules are set up for GNU C. Building an executable from a +single source file is as easy as 'make file.exe'. + +The variable $(ARCH) is predefined as ALPHA or VAX resp. Makefiles for +different VMS systems can now be written by checking $(ARCH) as in + ifeq ($(ARCH),ALPHA) + $(ECHO) "On the Alpha" + else + $(ECHO) "On the VAX" + endif + +Command lines of excessive length are correctly broken and written to a +batch file in sys$scratch for later execution. There's no limit to the +lengths of commands (and no need for .opt files :-) any more. + +Empty commands are handled correctly and don't end in a new DCL process. + + +New for 3.76: + +John W. Eaton has updated the VMS port to support libraries and VPATH. + To build Make, simply type @makefile. This should compile all the necessary files and link Make. There is also a file called @@ -12,6 +114,16 @@ Make with this makefile to rebuild. Here are some notes about GNU Make for VMS: +The cd command is supported if it's called as $(CD). This invokes +the 'builtin_cd' command which changes the directory. +Calling 'set def' doesn't do the trick, since a sub-shell is +spawned for this command, the directory is changed *in this sub-shell* +and the sub-shell ends. + +Libraries are not supported. They were in GNU Make 3.60 but somehow I +didn't care porting the code. If there is enough interest, I'll do it at +some later time. + The variable $^ separates files with commas instead of spaces (It's the natural thing to do for VMS). @@ -26,8 +138,8 @@ The default include directory for including other makefiles is SYS$SYSROOT:[SYSLIB] (I don't remember why I didn't just use SYS$LIBRARY: instead; maybe it wouldn't work that way). -The default makefiles make looks for are: makefile.vms, gnumakefile, makefile., -and gnumakefile. . +The default makefiles make looks for are: makefile.vms, gnumakefile, +makefile., and gnumakefile. . The stat() function and handling of time stamps in VMS is broken, so I replaced it with a hack in vmsfunctions.c. I will provide a full rewrite @@ -37,9 +149,9 @@ less than what vms provides. This might be a problem on the faster Alphas. You can use a : in a filename only if you preceed it with a backslash ('\'). E.g.- hobbes\:[bogas.files] -Make ignores success, informational, or warning errors (-S-, -I-, or -W-). -But it will stop on -E- and -F- errors. (unless you do something to override -this in your makefile, or whatever). +Make ignores success, informational, or warning errors (-S-, -I-, or +-W-). But it will stop on -E- and -F- errors. (unless you do something +to override this in your makefile, or whatever). Remote stuff isn't implemented yet. @@ -47,18 +159,10 @@ Multiple line DCL commands, such as "if" statements, must be put inside command files. You can run a command file by using \@. -Change history: +VMS changes made for 3.74.3 -3.76.x -====== -Added VMS help version (make.hlp) of the Unix man page. To integrate -that with an existing Help library use a command like the following - $lib/ins/help sys$help:helplib.hlb make.hlp -3.74.3 -====== Lots of default settings are adapted for VMS. See default.c. Long command lines are now converted to command files. Comma (',') as a separator is now allowed. See makefile.vms for an example. - diff --git a/rule.c b/rule.c index 90e04e3c..5933777a 100644 --- a/rule.c +++ b/rule.c @@ -109,10 +109,14 @@ count_implicit_rule_limits () #ifdef VMS char *p = strrchr (dep->name, ']'); + char *p2; + if (p == 0) + p = strrchr (dep->name, ':'); + p2 = p != 0 ? strchr (dep->name, '%') : 0; #else char *p = strrchr (dep->name, '/'); -#endif char *p2 = p != 0 ? strchr (dep->name, '%') : 0; +#endif ndeps++; if (len > max_pattern_dep_length) @@ -140,7 +144,7 @@ count_implicit_rule_limits () dep->changed = !dir_file_exists_p (name, ""); #ifdef VMS - if (dep->changed && *name == ']') + if (dep->changed && strchr (name, ':') != 0) #else if (dep->changed && *name == '/') #endif diff --git a/variable.c b/variable.c index 8058a748..6d105b29 100644 --- a/variable.c +++ b/variable.c @@ -182,6 +182,63 @@ lookup_variable (name, length) return v; } +#ifdef VMS + /* since we don't read envp[] on startup, try to get the + variable via getenv() here. */ + + { + char *vname = alloca (length + 1); + char *value; + strncpy (vname, name, length); + vname[length] = 0; + value = getenv (vname); + if (value != 0) + { + char *sptr; + int scnt; + + sptr = value; + scnt = 0; + + while ((sptr = strchr (sptr, '$'))) + { + scnt++; + sptr++; + } + + if (scnt > 0) + { + char *nvalue; + char *nptr; + + nvalue = alloca (length + scnt + 1); + sptr = value; + nptr = nvalue; + + while (*sptr) + { + if (*sptr == '$') + { + *nptr++ = '$'; + *nptr++ = '$'; + } + else + { + *nptr++ = *sptr; + } + sptr++; + } + + return define_variable (vname, length, nvalue, o_env, 1); + + } + + return define_variable (vname, length, value, o_env, 1); + } + } + +#endif /* VMS */ + return 0; } @@ -457,6 +514,15 @@ define_automatic_variables () /* Define the magic D and F variables in terms of the automatic variables they are variations of. */ +#ifdef VMS + define_variable ("@D", 2, "$(dir $@)", o_automatic, 1); + define_variable ("%D", 2, "$(dir $%)", o_automatic, 1); + define_variable ("*D", 2, "$(dir $*)", o_automatic, 1); + define_variable (" #define MAXNAMLEN 255 #ifndef __DECC +#if !defined (__GNUC__) && !defined (__ALPHA) typedef unsigned long u_long; typedef unsigned short u_short; #endif +#endif -struct direct { +struct direct +{ off_t d_off; u_long d_fileno; u_short d_reclen; @@ -18,8 +24,11 @@ struct direct { }; #undef DIRSIZ -#define DIRSIZ(dp) \ - (((sizeof (struct direct) - (MAXNAMLEN+1) + ((dp)->d_namlen+1)) + 3) & ~3) +#define DIRSIZ(dp) \ + (((sizeof (struct direct) \ + - (MAXNAMLEN+1) \ + + ((dp)->d_namlen+1)) \ + + 3) & ~3) #define d_ino d_fileno /* compatability */ @@ -28,15 +37,25 @@ struct direct { * Definitions for library routines operating on directories. */ -typedef struct FAB DIR; +typedef struct DIR +{ + struct direct dir; + char d_result[MAXNAMLEN + 1]; +#if defined (__ALPHA) || defined (__DECC) + struct FAB fab; +#else + struct fabdef fab; +#endif +} DIR; #ifndef NULL #define NULL 0 #endif + extern DIR *opendir PARAMS (()); extern struct direct *readdir PARAMS ((DIR *dfd)); #define rewinddir(dirp) seekdir((dirp), (long)0) extern int closedir PARAMS ((DIR *dfd)); extern char *vmsify PARAMS ((char *name, int type)); -/* EOF */ +#endif /* VMSDIR_H */ diff --git a/vmsfunctions.c b/vmsfunctions.c index 4e0cb34c..a36630e7 100644 --- a/vmsfunctions.c +++ b/vmsfunctions.c @@ -1,7 +1,5 @@ /* vmsfunctions.c */ -#define KDEBUG 0 - #include "make.h" #include "debug.h" @@ -21,37 +19,17 @@ DIR * opendir (dspec) char *dspec; { - static struct FAB *dfab; - struct NAM *dnam; - char *searchspec; + 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); +} diff --git a/vmsify.c b/vmsify.c index 350ce156..f7871bb2 100644 --- a/vmsify.c +++ b/vmsify.c @@ -8,6 +8,7 @@ */ +#include #include #include @@ -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; }