Tue Mar 19 20:21:34 1996 Roland McGrath <roland@charlie-brown.gnu.ai.mit.edu>

Merged VMS port from Klaus Kaempf <kkaempf@didymus.rmi.de>.
	* make.h (PARAMS): New macro.
	* config.h-vms: New file.
	* makefile.com: New file.
	* makefile.vms: New file.
	* readme.vms: New file.
	* vmsdir.h: New file.
	* vmsfunctions.c: New file.
	* vmsify.c: New file.
	* file.h: Renamed to filedef.h to avoid conflict with VMS system hdr.
	* ar.c: Added prototypes and changes for VMS.
	* commands.c: Likewise.
	* commands.h: Likewise.
	* default.c: Likewise.
	* dep.h: Likewise.
	* dir.c: Likewise.
	* expand.c: Likewise.
	* file.c: Likewise.
	* function.c: Likewise.
	* implicit.c: Likewise.
	* job.c: Likewise.
	* job.h: Likewise.
	* main.c: Likewise.
	* make.h: Likewise.
	* misc.c: Likewise.
	* read.c: Likewise.
	* remake.c: Likewise.
	* remote-stub.c: Likewise.
	* rule.c: Likewise.
	* rule.h: Likewise.
	* variable.c: Likewise.
	* variable.h: Likewise.
	* vpath.c: Likewise.
	* compatMakefile (srcs): Rename file.h to filedef.h.
This commit is contained in:
Roland McGrath 1996-03-20 14:57:41 +00:00
parent dfefc77263
commit 9e443adaf6
32 changed files with 3063 additions and 223 deletions

126
ar.c
View file

@ -20,14 +20,14 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifndef NO_ARCHIVES
#include "file.h"
#include "filedef.h"
#include "dep.h"
#include <fnmatch.h>
/* Defined in arscan.c. */
extern long int ar_scan ();
extern int ar_member_touch ();
extern int ar_name_equal ();
extern long int ar_scan PARAMS ((char *archive, long int (*function) (), long int arg));
extern int ar_member_touch PARAMS ((char *arname, char *memname));
extern int ar_name_equal PARAMS ((char *name, char *mem, int truncated));
/* Return nonzero if NAME is an archive-member reference, zero if not.
@ -67,8 +67,113 @@ ar_parse_name (name, arname_p, memname_p)
if (memname_p != 0)
*memname_p = savestring (p + 1, end - (p + 1));
}
#ifdef VMS
#include <lbrdef.h>
#include <mhddef.h>
#include <credef.h>
#include <descrip.h>
#include <ctype.h>
#if __DECC
#include <lbr$routines.h>
#endif
#define uppercasify(str) {char *str1; for (str1 = str; *str1; str1++) *str1 = _toupper(*str1);}
#define LBR$_KEYNOTFND 2527330 /* This isn't in any .h file anywhere so I got it from a MACRO library */
time_t
ar_member_date (name)
char *name;
{
static char *arname;
static char *memname;
char *p,*q;
long int val;
static struct {
struct mhddef mhd;
struct credef cre;
char garbage[256];
} buf;
int func=LBR$C_READ,
type=LBR$C_TYP_OBJ,
rfa[2],
lidx,
status;
$DESCRIPTOR(bufdesc,(char *)&buf);
$DESCRIPTOR(libdesc,arname);
$DESCRIPTOR(moddesc,memname);
/* This "file" is an archive member. */
p = index (name, '(');
arname = savestring (name, p - name);
val = strlen (p) - 2;
/*
if (val > 15)
val = 15;
*/
memname = savestring (p + 1, val);
#ifdef OLDWAY
p = rindex (memname, ')');
if (p != 0) {
q = rindex(p,'.');
if (q)
*q = '\0'; /* to get rid of extension */
}
#endif
q = rindex(memname,'.');
if (q)
*q = '\0'; /* to get rid of extension */
uppercasify(memname);
/* Make sure we know the modtime of the archive itself because
we are likely to be called just before commands to remake a
member are run, and they will change the archive itself. */
(void) f_mtime (enter_file (arname));
libdesc.dsc$a_pointer = arname;
libdesc.dsc$w_length = strlen(arname);
moddesc.dsc$a_pointer = memname;
moddesc.dsc$w_length = strlen(memname);
if (!((status = lbr$ini_control(&lidx,&func,&type,0)) & 1)) {
printf("Error in lbr$ini_control, %d\n",status);
return(-1);
}
if (!((status = lbr$open(&lidx,&libdesc,0,0,0,0,0)) & 1)) {
printf("Error opening library %s to lookup member %s, %d\n",arname, memname ,status);
return(-1);
}
if (!((status = lbr$lookup_key(&lidx,&moddesc,rfa)) & 1)) {
if (status != LBR$_KEYNOTFND)
printf("Error looking up module %s in library %s, %d\n",memname, arname ,status);
lbr$close(&lidx);
return(-1);
}
if (!((status = lbr$set_module(&lidx,rfa,&bufdesc,&bufdesc,0)) & 1)) {
printf("Error getting module info, %d\n",status);
lbr$close(&lidx);
return(-1);
}
lbr$close(&lidx);
val = SHELL$FIX_TIME(&buf.mhd.mhd$l_datim);
free (arname);
free (memname);
return (val <= 0 ? (time_t) -1 : (time_t) val);
}
#else
static long int ar_member_date_1 ();
static long int ar_member_date_1 PARAMS ((int desc, char *mem, int truncated, long int hdrpos,
long int datapos, long int size, long int date, int uid, int gid, int mode, char *name));
/* Return the modtime of NAME. */
@ -127,9 +232,19 @@ ar_member_date_1 (desc, mem, truncated,
{
return ar_name_equal (name, mem, truncated) ? date : 0;
}
#endif /* !VMS */
/* Set the archive-member NAME's modtime to now. */
#ifdef VMS
int
ar_touch (name)
char *name;
{
error ("touch archive member is not available on VMS");
return -1;
}
#else
int
ar_touch (name)
char *name;
@ -182,6 +297,7 @@ ar_touch (name)
return val;
}
#endif /* !VMS */
/* State of an `ar_glob' run, passed to `ar_glob_match'. */

View file

@ -18,12 +18,12 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "make.h"
#include "dep.h"
#include "commands.h"
#include "file.h"
#include "filedef.h"
#include "variable.h"
#include "job.h"
#include "commands.h"
extern int remote_kill ();
extern int remote_kill PARAMS ((int id, int sig));
#ifndef HAVE_UNISTD_H
extern int getpid ();
@ -154,8 +154,11 @@ set_file_variables (file)
bcopy (c, cp, len);
cp += len;
#if VMS
*cp++ = ',';
#else
*cp++ = ' ';
#endif
if (! d->changed)
qmark_len -= len + 1; /* Don't space in $? for this one. */
}
@ -193,13 +196,20 @@ set_file_variables (file)
bcopy (c, cp, len);
cp += len;
#if VMS
*cp++ = ',';
#else
*cp++ = ' ';
#endif
if (d->changed)
{
bcopy (c, qp, len);
qp += len;
#if VMS
*qp++ = ',';
#else
*qp++ = ' ';
#endif
}
}
@ -413,7 +423,7 @@ fatal_error_signal (sig)
if (sig == SIGQUIT)
/* We don't want to send ourselves SIGQUIT, because it will
cause a core dump. Just exit instead. */
exit (1);
exit (EXIT_FAILURE);
/* Signal the same code; this time it will really be fatal. The signal
will be unblocked when we return and arrive then to kill us. */

View file

@ -36,7 +36,7 @@ struct commands
#define COMMANDS_SILENT 2 /* Silent: @. */
#define COMMANDS_NOERROR 4 /* No errors: -. */
extern void execute_file_commands ();
extern void print_commands ();
extern void delete_child_targets ();
extern void chop_commands ();
extern void execute_file_commands PARAMS ((struct file *file));
extern void print_commands PARAMS ((struct commands *cmds));
extern void delete_child_targets PARAMS ((struct child *child));
extern void chop_commands PARAMS ((struct commands *cmds));

View file

@ -122,7 +122,7 @@ srcs = $(srcdir)/commands.c $(srcdir)/job.c $(srcdir)/dir.c \
$(srcdir)/ar.c $(srcdir)/arscan.c \
$(srcdir)/signame.c $(srcdir)/signame.h \
$(srcdir)/getopt.c $(srcdir)/getopt1.c $(srcdir)/getopt.h \
$(srcdir)/commands.h $(srcdir)/dep.h $(srcdir)/file.h \
$(srcdir)/commands.h $(srcdir)/dep.h $(srcdir)/filedef.h \
$(srcdir)/job.h $(srcdir)/make.h $(srcdir)/rule.h \
$(srcdir)/variable.h $(ALLOCA_SRC) $(srcdir)/config.h.in

292
config.h-vms.template Normal file
View file

@ -0,0 +1,292 @@
/* config.h-vms. Generated by hand by Klaus Kämpf <kkaempf@didymus.rmi.de> */
/* config.h. Generated automatically by configure. */
/* config.h.in. Generated automatically from configure.in by autoheader. */
/* Define if on AIX 3.
System headers sometimes define this.
We just want to avoid a redefinition error message. */
#ifndef _ALL_SOURCE
/* #undef _ALL_SOURCE */
#endif
/* Define if using alloca.c. */
/* #undef C_ALLOCA */
/* Define to empty if the keyword does not work. */
/* #undef const */
/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems.
This function is required for alloca.c support on those systems. */
/* #undef CRAY_STACKSEG_END */
/* Define for DGUX with <sys/dg_sys_info.h>. */
/* #undef DGUX */
/* Define if the `getloadavg' function needs to be run setuid or setgid. */
/* #undef GETLOADAVG_PRIVILEGED 1 */
/* Define to `int' if <sys/types.h> doesn't define. */
/* #undef gid_t */
/* Define if you have alloca, as a function or macro. */
#define HAVE_ALLOCA 1
/* Define if you have <alloca.h> and it should be used (not on Ultrix). */
/* #undef HAVE_ALLOCA_H 1 */
/* Define if you don't have vprintf but do have _doprnt. */
/* #undef HAVE_DOPRNT */
/* Define if your system has its own `getloadavg' function. */
/* #undef HAVE_GETLOADAVG */
/* Define if you have the getmntent function. */
/* #undef HAVE_GETMNTENT */
/* Define if the `long double' type works. */
/* #undef HAVE_LONG_DOUBLE */
/* Define if you support file names longer than 14 characters. */
#define HAVE_LONG_FILE_NAMES 1
/* Define if you have a working `mmap' system call. */
/* #undef HAVE_MMAP */
/* Define if system calls automatically restart after interruption
by a signal. */
/* #undef HAVE_RESTARTABLE_SYSCALLS */
/* Define if your struct stat has st_blksize. */
/* #undef HAVE_ST_BLKSIZE */
/* Define if your struct stat has st_blocks. */
/* #undef HAVE_ST_BLOCKS */
/* Define if you have the strcoll function and it is properly defined. */
/* #undef HAVE_STRCOLL 1 */
/* Define if your struct stat has st_rdev. */
/* #undef HAVE_ST_RDEV */
/* Define if you have the strftime function. */
/* #undef HAVE_STRFTIME */
/* Define if you have <sys/wait.h> that is POSIX.1 compatible. */
/* #undef HAVE_SYS_WAIT_H 1 */
/* Define if your struct tm has tm_zone. */
/* #undef HAVE_TM_ZONE */
/* Define if you don't have tm_zone but do have the external array
tzname. */
/* #undef HAVE_TZNAME */
/* Define if you have <unistd.h>. */
#ifdef __DECC
#define HAVE_UNISTD_H 1
#endif
/* Define if utime(file, NULL) sets file's timestamp to the present. */
/* #undef HAVE_UTIME_NULL */
/* Define if you have <vfork.h>. */
/* #undef HAVE_VFORK_H 1 */
/* Define if you have the vprintf function. */
#define HAVE_VPRINTF 1
/* Define if you have the wait3 system call. */
/* #undef HAVE_WAIT3 1 */
/* Define if on MINIX. */
/* #undef _MINIX */
/* Define if your struct nlist has an n_un member. */
/* #undef NLIST_NAME_UNION */
/* Define if you have <nlist.h>. */
/* #undef NLIST_STRUCT 1 */
/* Define if your C compiler doesn't accept -c and -o together. */
/* #undef NO_MINUS_C_MINUS_O */
/* Define to `int' if <sys/types.h> doesn't define. */
#define pid_t int
/* Define if the system does not provide POSIX.1 features except
with this defined. */
/* #undef _POSIX_1_SOURCE */
/* Define if you need to in order for stat and other things to work. */
/* #undef _POSIX_SOURCE */
/* Define as the return type of signal handlers (int or void). */
#define RETSIGTYPE void
/* Define if the setvbuf function takes the buffering type as its second
argument and the buffer pointer as the third, as on System V
before release 3. */
/* #undef SETVBUF_REVERSED 1 */
/* If using the C implementation of alloca, define if you know the
direction of stack growth for your system; otherwise it will be
automatically deduced at run-time.
STACK_DIRECTION > 0 => grows toward higher addresses
STACK_DIRECTION < 0 => grows toward lower addresses
STACK_DIRECTION = 0 => direction of growth unknown
*/
/* #undef STACK_DIRECTION */
/* Define if the `S_IS*' macros in <sys/stat.h> do not work properly. */
/* #undef STAT_MACROS_BROKEN */
/* Define if you have the ANSI C header files. */
/* #undef STDC_HEADERS */
/* Define on System V Release 4. */
/* #undef SVR4 */
/* Define if `sys_siglist' is declared by <signal.h>. */
/* #undef SYS_SIGLIST_DECLARED */
/* Define to `int' if <sys/types.h> doesn't define. */
#define uid_t int
/* Define for Encore UMAX. */
/* #undef UMAX */
/* Define for Encore UMAX 4.3 that has <inq_status/cpustats.h>
instead of <sys/cpustats.h>. */
/* #undef UMAX4_3 */
/* Define vfork as fork if vfork does not work. */
/* #undef vfork */
/* Define to the name of the SCCS `get' command. */
/* #undef SCCS_GET "/usr/sccs/get" */
/* Define this if the SCCS `get' command understands the `-G<file>' option. */
/* #undef SCCS_GET_MINUS_G 1 */
/* Define this if the C library defines the variable `sys_siglist'. */
/* #undefine HAVE_SYS_SIGLIST 1 */
/* Define this if the C library defines the variable `_sys_siglist'. */
/* #undef HAVE__SYS_SIGLIST */
/* Define this if you have the `union wait' type in <sys/wait.h>. */
/* #undef HAVE_UNION_WAIT */
/* Define this if the POSIX.1 call `sysconf (_SC_OPEN_MAX)' works properly. */
/* #undef HAVE_SYSCONF_OPEN_MAX */
/* Define if you have the dup2 function. */
#define HAVE_DUP2 1
/* Define if you have the getcwd function. */
#define HAVE_GETCWD 1
/* Define if you have the getdtablesize function. */
/* #undef HAVE_GETDTABLESIZE 1 */
/* Define if you have the getgroups function. */
/* #undef HAVE_GETGROUPS 1 */
/* Define if you have the mktemp function. */
#define HAVE_MKTEMP 1
/* Define if you have the psignal function. */
/* #undef HAVE_PSIGNAL 1 */
/* Define if you have the setegid function. */
/* #undef HAVE_SETEGID 1 */
/* Define if you have the seteuid function. */
/* #undef HAVE_SETEUID 1 */
/* Define if you have the setlinebuf function. */
/* #undef HAVE_SETLINEBUF 1 */
/* Define if you have the setregid function. */
/* #undefine HAVE_SETREGID 1 */
/* Define if you have the setreuid function. */
/* #define HAVE_SETREUID 1 */
/* Define if you have the sigsetmask function. */
#define HAVE_SIGSETMASK 1
/* Define if you have the strerror function. */
#define HAVE_STRERROR 1
/* Define if you have the strsignal function. */
/* #undef HAVE_STRSIGNAL */
/* Define if you have the wait3 function. */
/* #define HAVE_WAIT3 1 */
/* Define if you have the waitpid function. */
/* #undef HAVE_WAITPID 1 */
/* Define if you have the <dirent.h> header file. */
/* #unddef HAVE_DIRENT_H 1 */
/* Define if you have the <fcntl.h> header file. */
#ifdef __DECC
#define HAVE_FCNTL_H 1
#endif
/* Define if you have the <limits.h> header file. */
#define HAVE_LIMITS_H 1
/* Define if you have the <mach/mach.h> header file. */
/* #undef HAVE_MACH_MACH_H */
/* Define if you have the <memory.h> header file. */
/* #undef HAVE_MEMORY_H 1 */
/* Define if you have the <ndir.h> header file. */
/* #undef HAVE_NDIR_H */
/* Define if you have the <string.h> header file. */
#define HAVE_STRING_H 1
/* Define if you have the <pwd.h> header file. */
/* #undef HAVE_PWD_H */
/* Define if you have the <sys/dir.h> header file. */
/* #undef HAVE_SYS_DIR_H */
/* Define if you have the <sys/ndir.h> header file. */
/* #undef HAVE_SYS_NDIR_H */
/* Define if you have the <sys/param.h> header file. */
/* #undef HAVE_SYS_PARAM_H 1 */
/* Define if you have the <sys/timeb.h> header file. */
#define HAVE_SYS_TIMEB_H 1
/* Define if you have the <sys/wait.h> header file. */
/* #undef HAVE_SYS_WAIT_H 1 */
/* Define if you have the dgc library (-ldgc). */
/* #undef HAVE_LIBDGC */
/* Define if you have the sun library (-lsun). */
/* #undef HAVE_LIBSUN */
/* VMS specific */
#define HAVE_VMSDIR_H 1
#define HAVE_STDLIB_H 1
#define INCLUDEDIR "sys$sysroot:[syslib]"
#define LIBDIR "sys$sysroot:[syslib]"
#if defined (__cplusplus) || (defined (__STDC__) && __STDC__)
#undef PARAMS
#define PARAMS(protos) protos
#else /* Not C++ or ANSI C. */
#undef PARAMS
#define PARAMS(protos) ()
#endif /* C++ or ANSI C. */

114
default.c
View file

@ -19,7 +19,8 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "make.h"
#include "rule.h"
#include "dep.h"
#include "file.h"
#include "filedef.h"
#include "job.h"
#include "commands.h"
#include "variable.h"
@ -35,9 +36,15 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
a `.c' or `.p' or ... file rather than from a .s file. */
static char default_suffixes[]
#ifdef VMS
= ".exe .olb .ln .obj .c .cc .pas .p .for .f .r .y .l .mar \
.mod .sym .def .h .info .dvi .tex .texinfo .texi .txinfo \
.w .ch .cweb .web .com .sh .elc .el";
#else
= ".out .a .ln .o .c .cc .C .p .f .F .r .y .l .s .S \
.mod .sym .def .h .info .dvi .tex .texinfo .texi .txinfo \
.w .ch .web .sh .elc .el";
#endif
static struct pspec default_pattern_rules[] =
{
@ -47,9 +54,13 @@ static struct pspec default_pattern_rules[] =
/* The X.out rules are only in BSD's default set because
BSD Make has no null-suffix rules, so `foo.out' and
`foo' are the same thing. */
#ifdef VMS
{ "%.exe", "%",
"copy $< $@" },
#else
{ "%.out", "%",
"@rm -f $@ \n cp $< $@" },
#endif
/* Syntax is "ctangle foo.w foo.ch foo.c". */
{ "%.c", "%.w %.ch",
"$(CTANGLE) $^ $@" },
@ -61,6 +72,20 @@ static struct pspec default_pattern_rules[] =
static struct pspec default_terminal_rules[] =
{
#ifdef VMS
/* RCS. */
{ "%", "%$$5lv", /* Multinet style */
"if f$$search($@) .nes. \"\" then +$(CHECKOUT,v)" },
{ "%", "[.$$rcs]%$$5lv", /* Multinet style */
"if f$$search($@) .nes. \"\" then +$(CHECKOUT,v)" },
{ "%", "%_v", /* Normal style */
"if f$$search($@) .nes. \"\" then +$(CHECKOUT,v)" },
{ "%", "[.rcs]%_v", /* Normal style */
"if f$$search($@) .nes. \"\" then +$(CHECKOUT,v)" },
/* SCCS. */
/* ain't no SCCS on vms */
#else
/* RCS. */
{ "%", "%,v",
"$(CHECKOUT,v)" },
@ -72,12 +97,53 @@ static struct pspec default_terminal_rules[] =
"$(GET) $(GFLAGS) $(SCCS_OUTPUT_OPTION) $<" },
{ "%", "SCCS/s.%",
"$(GET) $(GFLAGS) $(SCCS_OUTPUT_OPTION) $<" },
#endif /* !VMS */
{ 0, 0, 0 }
};
static char *default_suffix_rules[] =
{
#ifdef VMS
".obj.exe",
"$(LINK.obj) $^ $(LOADLIBES) $(LDLIBS) /exe=$@",
".mar.exe",
"$(LINK.mar) $^ $(LOADLIBES) $(LDLIBS) /exe=$@",
".c.exe",
"$(COMPILE.c) $^ \n $(LINK.obj) $(subst .c,.obj,$^) $(LOADLIBES) $(LDLIBS) /exe=$@",
".cc.exe",
"$(COMPILE.cc) $^ \n $(LINK.obj) $(subst .cc,.obj,$^) $(LOADLIBES) $(LDLIBS) /exe=$@",
".for.exe",
"$(COMPILE.for) $^ \n $(LINK.obj) $(subst .for,.obj,$^) $(LOADLIBES) $(LDLIBS) /exe=$@",
".pas.exe",
"$(COMPILE.pas) $^ \n $(LINK.obj) $(subst .pas,.obj,$^) $(LOADLIBES) $(LDLIBS) /exe=$@",
".com",
"copy $< >$@",
".mar.obj",
"$(COMPILE.mar) /obj=$@ $<",
".c.obj",
"$(COMPILE.c) /obj=$@ $<",
".cc.obj",
"$(COMPILE.cc) /obj=$@ $<",
".for.obj",
"$(COMPILE.for) /obj=$@ $<",
".pas.obj",
"$(COMPILE.pas) /obj=$@ $<",
".y.c",
"$(YACC.y) $< \n rename y_tab.c $@",
".l.c",
"$(LEX.l) $< \n rename lexyy.c $@",
".texinfo.info",
"$(MAKEINFO) $<",
".tex.dvi",
"$(TEX) $<",
#else /* ! VMS */
".o",
"$(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o $@",
".s",
@ -195,11 +261,52 @@ static char *default_suffix_rules[] =
".web.tex",
"$(WEAVE) $<",
#endif /* !VMS */
0, 0,
};
static char *default_variables[] =
{
#ifdef VMS
"AR", "library/obj",
"ARFLAGS", "/replace",
"AS", "macro",
"CC", "cc",
"C++", "gcc/plus",
"CXX", "gcc/plus",
"CO", "co",
"CPP", "$(CC) /preprocess_only",
"FC", "fortran",
/* System V uses these, so explicit rules using them should work.
However, there is no way to make implicit rules use them and FC. */
"F77", "$(FC)",
"F77FLAGS", "$(FFLAGS)",
"LD", "link",
"LEX", "lex",
"PC", "pascal",
"YACC", "yacc", /* Or "bison -y" */
"MAKEINFO", "makeinfo",
"TEX", "tex",
"TEXINDEX", "texindex",
"RM", "delete/nolog",
"LINK.obj", "$(LD) $(LDFLAGS)",
"COMPILE.c", "$(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH)",
"COMPILE.cc", "$(C++) $(C++FLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c",
"YACC.y", "$(YACC) $(YFLAGS)",
"LEX.l", "$(LEX) $(LFLAGS)",
"COMPILE.for", "$(FC) $(FFLAGS) $(TARGET_ARCH)",
"COMPILE.pas", "$(PC) $(PFLAGS) $(CPPFLAGS) $(TARGET_ARCH)",
"COMPILE.mar", "$(AS) $(ASFLAGS) $(TARGET_MACH)",
"LINT.c", "$(LINT) $(LINTFLAGS) $(CPPFLAGS) $(TARGET_ARCH)",
"MV", "rename/new_version",
"CP", "copy",
#else /* !VMS */
"AR", "ar",
"ARFLAGS", "rv",
"AS", "as",
@ -310,6 +417,7 @@ static char *default_variables[] =
"SCCS_OUTPUT_OPTION", "-G$@",
#endif
#endif /* !VMS */
0, 0
};

13
dep.h
View file

@ -40,11 +40,16 @@ struct nameseq
};
extern struct nameseq *multi_glob (), *parse_file_seq ();
extern char *tilde_expand ();
extern struct nameseq *multi_glob PARAMS ((struct nameseq *chain, unsigned int size));
#ifdef VMS
extern struct nameseq *parse_file_seq ();
#else
extern struct nameseq *parse_file_seq PARAMS ((char **stringp, char stopchar, unsigned int size, int strip));
#endif
extern char *tilde_expand PARAMS ((char *name));
#ifndef NO_ARCHIVES
extern struct nameseq *ar_glob ();
extern struct nameseq *ar_glob PARAMS ((char *arname, char *member_pattern, unsigned int size));
#endif
#ifndef iAPX286
@ -54,7 +59,7 @@ extern struct nameseq *ar_glob ();
extern char *dep_name ();
#endif
extern struct dep *read_all_makefiles ();
extern struct dep *read_all_makefiles PARAMS ((char **makefiles));
/* Flag bits for the second argument to `read_makefile'.
These flags are saved in the `changed' field of each

192
dir.c
View file

@ -33,6 +33,9 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
# ifdef HAVE_NDIR_H
# include <ndir.h>
# endif
# ifdef HAVE_VMSDIR_H
# include "vmsdir.h"
# endif /* HAVE_VMSDIR_H */
#endif
/* In GNU systems, <dirent.h> defines this macro for us. */
@ -92,7 +95,63 @@ dosify (filename)
*df = 0;
return dos_filename;
}
#endif
#endif /* __MSDOS__ */
#ifdef VMS
static int
vms_hash (name)
char *name;
{
int h = 0;
int g;
while (*name)
{
h = (h << 4) + *name++;
g = h & 0xf0000000;
if (g)
{
h = h ^ (g >> 24);
h = h ^ g;
}
}
return h;
}
/* fake stat entry for a directory */
static int
vmsstat_dir (name, st)
char *name;
struct stat *st;
{
char *s;
int h;
DIR *dir;
dir = opendir (name);
if (dir == 0)
return -1;
closedir (dir);
s = strchr (name, ':'); /* find device */
if (s)
{
*s++ = 0;
st->st_dev = (char *)vms_hash (name);
}
else
{
st->st_dev = 0;
s = name;
}
h = vms_hash (s);
st->st_ino[0] = h & 0xff;
st->st_ino[1] = h & 0xff00;
st->st_ino[2] = h >> 16;
return 0;
}
#endif /* VMS */
/* Hash table of directories. */
@ -104,8 +163,12 @@ struct directory_contents
{
struct directory_contents *next;
int dev, ino; /* Device and inode numbers of this dir. */
dev_t dev; /* Device and inode numbers of this dir. */
#ifdef VMS
ino_t ino[3];
#else
ino_t ino;
#endif
struct dirfile **files; /* Files in this directory. */
DIR *dirstream; /* Stream reading this directory. */
};
@ -149,7 +212,8 @@ struct dirfile
#define DIRFILE_BUCKETS 107
#endif
static int dir_contents_file_exists_p ();
static int dir_contents_file_exists_p PARAMS ((struct directory_contents *dir, char *filename));
static struct directory *find_directory PARAMS ((char *name));
/* Find the directory named NAME and return its `struct directory'. */
@ -160,6 +224,12 @@ find_directory (name)
register unsigned int hash = 0;
register char *p;
register struct directory *dir;
#ifdef VMS
if ((*name == '.') && (*(name+1) == 0))
name = "[]";
else
name = vmsify (name,1);
#endif
for (p = name; *p != '\0'; ++p)
HASH (hash, *p);
@ -183,21 +253,41 @@ find_directory (name)
/* The directory is not in the name hash table.
Find its device and inode numbers, and look it up by them. */
#ifdef VMS
if (vmsstat_dir (name, &st) < 0)
#else
if (stat (name, &st) < 0)
#endif
{
/* Couldn't stat the directory. Mark this by
setting the `contents' member to a nil pointer. */
dir->contents = 0;
dir->contents = 0;
}
else
{
/* Search the contents hash table; device and inode are the key. */
struct directory_contents *dc;
#ifdef VMS
hash = ((unsigned int) st.st_dev << 16)
| ((unsigned int) st.st_ino[0]
+ (unsigned int) st.st_ino[1]
+ (unsigned int) st.st_ino[2]);
#else
hash = ((unsigned int) st.st_dev << 16) | (unsigned int) st.st_ino;
#endif
hash %= DIRECTORY_BUCKETS;
for (dc = directories_contents[hash]; dc != 0; dc = dc->next)
if (dc->dev == st.st_dev && dc->ino == st.st_ino)
if (dc->dev == st.st_dev
#ifdef VMS
&& dc->ino[0] == st.st_ino[0]
&& dc->ino[1] == st.st_ino[1]
&& dc->ino[2] == st.st_ino[2])
#else
&& dc->ino == st.st_ino)
#endif
break;
if (dc == 0)
@ -209,15 +299,23 @@ find_directory (name)
/* Enter it in the contents hash table. */
dc->dev = st.st_dev;
#ifdef VMS
dc->ino[0] = st.st_ino[0];
dc->ino[1] = st.st_ino[1];
dc->ino[2] = st.st_ino[2];
#else
dc->ino = st.st_ino;
#endif
dc->next = directories_contents[hash];
directories_contents[hash] = dc;
dc->dirstream = opendir (name);
if (dc->dirstream == 0)
{
/* Couldn't open the directory. Mark this by
setting the `files' member to a nil pointer. */
dc->files = 0;
dc->files = 0;
}
else
{
/* Allocate an array of buckets for files and zero it. */
@ -257,19 +355,26 @@ dir_contents_file_exists_p (dir, filename)
register struct dirent *d;
if (dir == 0 || dir->files == 0)
{
/* The directory could not be stat'd or opened. */
return 0;
return 0;
}
#ifdef __MSDOS__
filename = dosify (filename);
#endif
#ifdef VMS
filename = vmsify (filename,0);
#endif
hash = 0;
if (filename != 0)
{
if (*filename == '\0')
{
/* Checking if the directory exists. */
return 1;
return 1;
}
for (p = filename; *p != '\0'; ++p)
HASH (hash, *p);
@ -278,16 +383,22 @@ dir_contents_file_exists_p (dir, filename)
/* Search the list of hashed files. */
for (df = dir->files[hash]; df != 0; df = df->next)
if (streq (df->name, filename))
return !df->impossible;
{
if (streq (df->name, filename))
{
return !df->impossible;
}
}
}
/* The file was not found in the hashed list.
Try to read the directory further. */
if (dir->dirstream == 0)
{
/* The directory has been all read in. */
return 0;
return 0;
}
while ((d = readdir (dir->dirstream)) != 0)
{
@ -309,11 +420,12 @@ dir_contents_file_exists_p (dir, filename)
dir->files[newhash] = df;
df->name = savestring (d->d_name, len);
df->impossible = 0;
/* Check if the name matches the one we're searching for. */
if (filename != 0
&& newhash == hash && streq (d->d_name, filename))
return 1;
{
return 1;
}
}
/* If the directory has been completely read in,
@ -324,7 +436,6 @@ dir_contents_file_exists_p (dir, filename)
closedir (dir->dirstream);
dir->dirstream = 0;
}
return 0;
}
@ -355,9 +466,16 @@ file_exists_p (name)
return ar_member_date (name) != (time_t) -1;
#endif
#ifdef VMS
dirend = rindex (name, ']');
dirend++;
if (dirend == (char *)1)
return dir_file_exists_p ("[]", name);
#else
dirend = rindex (name, '/');
if (dirend == 0)
return dir_file_exists_p (".", name);
#endif
dirname = (char *) alloca (dirend - name + 1);
bcopy (name, dirname, dirend - name);
@ -379,9 +497,16 @@ file_impossible (filename)
register struct directory *dir;
register struct dirfile *new;
#ifdef VMS
dirend = rindex (p, ']');
dirend++;
if (dirend == (char *)1)
dir = find_directory ("[]");
#else
dirend = rindex (p, '/');
if (dirend == 0)
dir = find_directory (".");
#endif
else
{
char *dirname = (char *) alloca (dirend - p + 1);
@ -401,7 +526,13 @@ file_impossible (filename)
structure for it, but leave it out of the contents hash table. */
dir->contents = (struct directory_contents *)
xmalloc (sizeof (struct directory_contents));
#ifdef VMS
dir->contents->dev = 0;
dir->contents->ino[0] = dir->contents->ino[1] =
dir->contents->ino[2] = 0;
#else
dir->contents->dev = dir->contents->ino = 0;
#endif
dir->contents->files = 0;
dir->contents->dirstream = 0;
}
@ -436,9 +567,15 @@ file_impossible_p (filename)
register struct directory_contents *dir;
register struct dirfile *next;
#ifdef VMS
dirend = rindex (filename, ']');
if (dirend == 0)
dir = find_directory ("[]")->contents;
#else
dirend = rindex (filename, '/');
if (dirend == 0)
dir = find_directory (".")->contents;
#endif
else
{
char *dirname = (char *) alloca (dirend - filename + 1);
@ -455,6 +592,9 @@ file_impossible_p (filename)
#ifdef __MSDOS__
p = filename = dosify (p);
#endif
#ifdef VMS
p = filename = vmsify (p, 1);
#endif
for (hash = 0; *p != '\0'; ++p)
HASH (hash, *p);
@ -495,8 +635,15 @@ print_dir_data_base ()
if (dir->contents == 0)
printf ("# %s: could not be stat'd.\n", dir->name);
else if (dir->contents->files == 0)
#ifdef VMS
printf ("# %s (device %d, inode [%d,%d,%d]): could not be opened.\n",
dir->name, dir->contents->dev,
dir->contents->ino[0], dir->contents->ino[1],
dir->contents->ino[2]);
#else
printf ("# %s (device %d, inode %d): could not be opened.\n",
dir->name, dir->contents->dev, dir->contents->ino);
#endif
else
{
register unsigned int f = 0, im = 0;
@ -508,8 +655,15 @@ print_dir_data_base ()
++im;
else
++f;
#ifdef VMS
printf ("# %s (device %d, inode [%d,%d,%d]): ",
dir->name, dir->contents->dev,
dir->contents->ino[0], dir->contents->ino[1],
dir->contents->ino[2]);
#else
printf ("# %s (device %d, inode %d): ",
dir->name, dir->contents->dev, dir->contents->ino);
#endif
if (f == 0)
fputs ("No", stdout);
else
@ -557,15 +711,15 @@ struct dirstream
};
/* Forward declarations. */
static __ptr_t open_dirstream __P ((const char *));
static struct dirent *read_dirstream __P ((__ptr_t));
static __ptr_t open_dirstream PARAMS ((const char *));
static struct dirent *read_dirstream PARAMS ((__ptr_t));
static __ptr_t
open_dirstream (directory)
const char *directory;
{
struct dirstream *new;
struct directory *dir = find_directory (directory);
struct directory *dir = find_directory ((char *)directory);
if (dir->contents == 0 || dir->contents->files == 0)
/* DIR->contents is nil if the directory could not be stat'd.

View file

@ -17,8 +17,9 @@ along with GNU Make; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "make.h"
#include "filedef.h"
#include "job.h"
#include "commands.h"
#include "file.h"
#include "variable.h"
/* The next two describe the variable output buffer.

55
file.c
View file

@ -17,9 +17,10 @@ along with GNU Make; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "make.h"
#include "commands.h"
#include "dep.h"
#include "file.h"
#include "filedef.h"
#include "job.h"
#include "commands.h"
#include "variable.h"
#include <assert.h>
@ -55,6 +56,10 @@ lookup_file (name)
/* This is also done in parse_file_seq, so this is redundant
for names read from makefiles. It is here for names passed
on the command line. */
#ifdef VMS
while (name[0] == '[' && name[1] == ']' && name[2] != '\0')
name += 2;
#endif
while (name[0] == '.' && name[1] == '/' && name[2] != '\0')
{
name += 2;
@ -65,7 +70,11 @@ lookup_file (name)
if (*name == '\0')
/* It was all slashes after a dot. */
#ifdef VMS
name = "[]";
#else
name = "./";
#endif
hashval = 0;
for (n = name; *n != '\0'; ++n)
@ -73,8 +82,12 @@ lookup_file (name)
hashval %= FILE_BUCKETS;
for (f = files[hashval]; f != 0; f = f->next)
if (streq (f->name, name))
return f;
{
if (streq (f->name, name))
{
return f;
}
}
return 0;
}
@ -85,10 +98,26 @@ enter_file (name)
register struct file *f, *new;
register char *n;
register unsigned int hashval;
#ifdef VMS
char *lname, *ln;
#endif
if (*name == '\0')
abort ();
#ifdef VMS
lname = (char *)malloc (strlen (name) + 1);
for (n = name, ln = lname; *n != '\0'; ++n, ++ln)
{
if (isupper(*n))
*ln = tolower(*n);
else
*ln = *n;
}
*ln = 0;
name = lname;
#endif
hashval = 0;
for (n = name; *n != '\0'; ++n)
HASH (hashval, *n);
@ -99,7 +128,12 @@ enter_file (name)
break;
if (f != 0 && !f->double_colon)
return f;
{
#ifdef VMS
free(lname);
#endif
return f;
}
new = (struct file *) xmalloc (sizeof (struct file));
bzero ((char *) new, sizeof (struct file));
@ -477,7 +511,9 @@ print_file (f)
struct file *f;
{
register struct dep *d;
#ifdef VMS
extern char *cvt_time PARAMS ((unsigned long));
#endif
putchar ('\n');
if (!f->is_target)
puts ("# Not a target:");
@ -513,8 +549,13 @@ print_file (f)
else if (f->last_mtime == (time_t) -1)
puts ("# File does not exist.");
else
#ifdef VMS
printf ("# Last modified %.24s (%0lx)\n",
cvt_time(f->last_mtime), (unsigned long) f->last_mtime);
#else
printf ("# Last modified %.24s (%ld)\n",
ctime (&f->last_mtime), (long int) f->last_mtime);
#endif
printf ("# File has%s been updated.\n",
f->updated ? "" : " not");
switch (f->command_state)
@ -601,3 +642,5 @@ print_file_data_base ()
#endif
}
}
/* EOF */

120
filedef.h Normal file
View file

@ -0,0 +1,120 @@
/* Definition of target file data structures for GNU Make.
Copyright (C) 1988, 89, 90, 91, 92, 93, 94 Free Software Foundation, Inc.
This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Make is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Make; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* Structure that represents the info on one file
that the makefile says how to make.
All of these are chained together through `next'. */
struct file
{
struct file *next;
char *name;
struct dep *deps;
struct commands *cmds; /* Commands to execute for this target. */
int command_flags; /* Flags OR'd in for cmds; see commands.h. */
char *stem; /* Implicit stem, if an implicit
rule has been used */
struct dep *also_make; /* Targets that are made by making this. */
time_t last_mtime; /* File's modtime, if already known. */
struct file *prev; /* Previous entry for same file name;
used when there are multiple double-colon
entries for the same file. */
/* File that this file was renamed to. After any time that a
file could be renamed, call `check_renamed' (below). */
struct file *renamed;
/* List of variable sets used for this file. */
struct variable_set_list *variables;
/* Immediate dependent that caused this target to be remade,
or nil if there isn't one. */
struct file *parent;
/* For a double-colon entry, this is the first double-colon entry for
the same file. Otherwise this is null. */
struct file *double_colon;
short int update_status; /* Status of the last attempt to update,
or -1 if none has been made. */
enum /* State of the commands. */
{ /* Note: It is important that cs_not_started be zero. */
cs_not_started, /* Not yet started. */
cs_deps_running, /* Dep commands running. */
cs_running, /* Commands running. */
cs_finished /* Commands finished. */
} command_state ENUM_BITFIELD (2);
unsigned int precious:1; /* Non-0 means don't delete file on quit */
unsigned int tried_implicit:1; /* Nonzero if have searched
for implicit rule for making
this file; don't search again. */
unsigned int updating:1; /* Nonzero while updating deps of this file */
unsigned int updated:1; /* Nonzero if this file has been remade. */
unsigned int is_target:1; /* Nonzero if file is described as target. */
unsigned int cmd_target:1; /* Nonzero if file was given on cmd line. */
unsigned int phony:1; /* Nonzero if this is a phony file
i.e., a dependency of .PHONY. */
unsigned int intermediate:1;/* Nonzero if this is an intermediate file. */
/* Nonzero, for an intermediate file,
means remove_intermediates should not delete it. */
unsigned int secondary:1;
unsigned int dontcare:1; /* Nonzero if no complaint is to be made if
this target cannot be remade. */
};
/* Number of intermediate files entered. */
extern unsigned int num_intermediates;
extern struct file *default_goal_file, *suffix_file, *default_file;
extern struct file *lookup_file (), *enter_file ();
extern void remove_intermediates (), snap_deps ();
extern void rename_file (), file_hash_enter ();
extern void set_command_state ();
/* Return the mtime of file F (a struct file *), caching it.
The value is -1 if the file does not exist. */
#define file_mtime(f) file_mtime_1 ((f), 1)
/* Return the mtime of file F (a struct file *), caching it.
Don't search using vpath for the file--if it doesn't actually exist,
we don't find it.
The value is -1 if the file does not exist. */
#define file_mtime_no_search(f) file_mtime_1 ((f), 0)
extern time_t f_mtime ();
#define file_mtime_1(f, v) \
((f)->last_mtime != (time_t) 0 ? (f)->last_mtime : f_mtime ((f), v))
/* Modtime value to use for `infinitely new'. We used to get the current time
from the system and use that whenever we wanted `new'. But that causes
trouble when the machine running make and the machine holding a file have
different ideas about what time it is; and can also lose for `force'
targets, which need to be considered newer than anything that depends on
them, even if said dependents' modtimes are in the future.
NOTE: This assumes 32-bit `time_t's, but I cannot think of a portable way
to produce the largest representable integer of a given signed type. */
#define NEW_MTIME ((time_t) 0x7fffffff)
#define check_renamed(file) \
while ((file)->renamed != 0) (file) = (file)->renamed /* No ; here. */

View file

@ -17,17 +17,18 @@ along with GNU Make; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "make.h"
#include "filedef.h"
#include "variable.h"
#include "dep.h"
#include "commands.h"
#include "job.h"
#include "commands.h"
#ifdef __MSDOS__
#include <process.h>
#include <fcntl.h>
#endif
static char *string_glob ();
static char *string_glob PARAMS ((char *line));
/* Store into VARIABLE_BUFFER at O the result of scanning TEXT and replacing
each occurrence of SUBST with REPLACE. TEXT is null-terminated. SLEN is
@ -35,7 +36,7 @@ static char *string_glob ();
nonzero, substitutions are done only on matches which are complete
whitespace-delimited words. If SUFFIX_ONLY is nonzero, substitutions are
done only at the ends of whitespace-delimited words. */
char *
subst_expand (o, text, subst, replace, slen, rlen, by_word, suffix_only)
char *o;
@ -337,7 +338,8 @@ expand_function (o, function, text, end)
default:
abort ();
break;
#ifndef VMS /* not supported for vms yet */
case function_shell:
{
char **argv, **envp;
@ -349,12 +351,13 @@ expand_function (o, function, text, end)
text = expand_argument (text, end);
/* Construct the argument list. */
argv = construct_command_argv (text, (char *) NULL, (struct file *) 0);
argv = construct_command_argv (text,
(char **) NULL, (struct file *) 0);
if (argv == 0)
break;
/* Using a target environment for `shell' loses in cases like:
export var = $(shell echo foobie)
export var = $(shell echo foobie)
because target_environment hits a loop trying to expand $(var)
to put it in the environment. This is even more confusing when
var was not explicitly exported, but just appeared in the
@ -498,7 +501,7 @@ expand_function (o, function, text, end)
unsigned int maxlen = 200;
int cc;
char *buffer;
strcpy (tmp_output, "shXXXXXX");
mktemp (tmp_output);
child_stdout = open (tmp_output,
@ -509,9 +512,9 @@ expand_function (o, function, text, end)
dup2 (save_stdout, 1);
close (child_stdout);
close (save_stdout);
child_stdout = open (tmp_output, O_RDONLY|O_TEXT, 0644);
buffer = xmalloc (maxlen);
i = 0;
do
@ -521,15 +524,15 @@ expand_function (o, function, text, end)
maxlen += 512;
buffer = (char *) xrealloc (buffer, maxlen + 1);
}
cc = read (child_stdout, &buffer[i], maxlen - i);
if (cc > 0)
i += cc;
} while (cc > 0);
close (child_stdout);
unlink (tmp_output);
if (i > 0)
{
if (buffer[i - 1] == '\n')
@ -548,6 +551,7 @@ expand_function (o, function, text, end)
free (text);
break;
}
#endif /* !VMS */
case function_origin:
/* Expand the argument. */
@ -590,7 +594,7 @@ expand_function (o, function, text, end)
free (text);
break;
case function_sort:
/* Expand the argument. */
text = expand_argument (text, end);
@ -610,7 +614,7 @@ expand_function (o, function, text, end)
nwords *= 2;
words = (char **) xrealloc ((char *) words,
nwords * sizeof (char *));
}
}
words[wordi++] = savestring (p, len);
}
@ -640,7 +644,7 @@ expand_function (o, function, text, end)
free (text);
break;
case function_foreach:
{
/* Get three comma-separated arguments but
@ -733,7 +737,7 @@ expand_function (o, function, text, end)
if (p == end)
BADARGS (function == function_filter ? "filter" : "filter-out");
p2 = expand_argument (text, p);
text = expand_argument (p + 1, end);
/* Chop TEXT up into words and then run each pattern through. */
@ -792,7 +796,7 @@ expand_function (o, function, text, end)
free (text);
}
break;
case function_patsubst:
/* Get three comma-separated arguments and expand each one. */
count = 0;
@ -825,9 +829,9 @@ expand_function (o, function, text, end)
text = expand_argument (text, p2);
p3 = expand_argument (p2 + 1, p);
p2 = expand_argument (p + 1, end);
o = patsubst_expand (o, p2, text, p3, (char *) 0, (char *) 0);
free (text);
free (p3);
free (p2);
@ -850,7 +854,7 @@ expand_function (o, function, text, end)
text = expand_argument (text, p);
p = expand_argument (p + 1, end);
{
/* Write each word of the first argument directly followed
by the corresponding word of the second argument.
@ -866,11 +870,11 @@ expand_function (o, function, text, end)
tp = find_next_token (&p2, &tlen);
if (tp != 0)
o = variable_buffer_output (o, tp, tlen);
pp = find_next_token (&p3, &plen);
if (pp != 0)
o = variable_buffer_output (o, pp, plen);
if (tp != 0 || pp != 0)
{
o = variable_buffer_output (o, " ", 1);
@ -882,11 +886,11 @@ expand_function (o, function, text, end)
/* Kill the last blank. */
--o;
}
free (text);
free (p);
break;
case function_strip:
/* Expand the argument. */
text = expand_argument (text, end);
@ -901,19 +905,19 @@ expand_function (o, function, text, end)
if (doneany)
/* Kill the last space. */
--o;
free (text);
break;
case function_wildcard:
text = expand_argument (text, end);
p = string_glob (text);
o = variable_buffer_output (o, p, strlen (p));
free (text);
break;
case function_subst:
/* Get three comma-separated arguments and expand each one. */
count = 0;
@ -946,14 +950,14 @@ expand_function (o, function, text, end)
text = expand_argument (text, p2);
p3 = expand_argument (p2 + 1, p);
p2 = expand_argument (p + 1, end);
o = subst_expand (o, p2, text, p3, strlen (text), strlen (p3), 0, 0);
free (text);
free (p3);
free (p2);
break;
case function_firstword:
/* Expand the argument. */
text = expand_argument (text, end);
@ -963,10 +967,10 @@ expand_function (o, function, text, end)
p = find_next_token (&p2, &i);
if (p != 0)
o = variable_buffer_output (o, p, i);
free (text);
break;
case function_word:
/* Get two comma-separated arguments and expand each one. */
count = 0;
@ -1058,11 +1062,11 @@ index argument");
i = strlen (text);
if (sindex (p, 0, text, i) != 0)
o = variable_buffer_output (o, text, i);
free (p);
free (text);
break;
case function_addsuffix:
case function_addprefix:
/* Get two comma-separated arguments and expand each one. */
@ -1082,7 +1086,7 @@ index argument");
i = strlen (text);
p2 = expand_argument (p + 1, end);
p3 = p2;
while ((p = find_next_token (&p3, &len)) != 0)
{
@ -1097,11 +1101,11 @@ index argument");
if (doneany)
/* Kill last space. */
--o;
free (p2);
free (text);
break;
case function_dir:
case function_basename:
/* Expand the argument. */
@ -1111,7 +1115,11 @@ index argument");
while ((p2 = find_next_token (&p3, &len)) != 0)
{
p = p2 + len;
#ifdef VMS
while (p >= p2 && *p != (function == function_dir ? ']' : '.'))
#else
while (p >= p2 && *p != (function == function_dir ? '/' : '.'))
#endif
--p;
if (p >= p2)
{
@ -1120,7 +1128,11 @@ index argument");
o = variable_buffer_output (o, p2, p - p2);
}
else if (function == function_dir)
#ifdef VMS
o = variable_buffer_output (o, "[]", 2);
#else
o = variable_buffer_output (o, "./", 2);
#endif
else
/* The entire name is the basename. */
o = variable_buffer_output (o, p2, len);
@ -1131,10 +1143,10 @@ index argument");
if (doneany)
/* Kill last space. */
--o;
free (text);
break;
case function_notdir:
case function_suffix:
/* Expand the argument. */
@ -1144,7 +1156,11 @@ index argument");
while ((p2 = find_next_token (&p3, &len)) != 0)
{
p = p2 + len;
#ifdef VMS
while (p >= p2 && *p != (function == function_notdir ? ']' : '.'))
#else
while (p >= p2 && *p != (function == function_notdir ? '/' : '.'))
#endif
--p;
if (p >= p2)
{

View file

@ -19,9 +19,10 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "make.h"
#include "rule.h"
#include "dep.h"
#include "file.h"
#include "filedef.h"
static int pattern_search ();
static int pattern_search PARAMS ((struct file *file, int archive, unsigned int depth,
unsigned int recursions));
/* For a FILE which has no commands specified, try to figure out some
from the implicit pattern rules.
@ -162,7 +163,11 @@ pattern_search (file, archive, depth, recursions)
/* Set LASTSLASH to point at the last slash in FILENAME
but not counting any slash at the end. (foo/bar/ counts as
bar/ in directory foo/, not empty in directory foo/bar/.) */
#ifdef VMS
lastslash = rindex (filename, ']');
#else
lastslash = rindex (filename, '/');
#endif
if (lastslash != 0 && lastslash[1] == '\0')
lastslash = 0;
}
@ -210,7 +215,11 @@ pattern_search (file, archive, depth, recursions)
/* Set CHECK_LASTSLASH if FILENAME contains a directory
prefix and the target pattern does not contain a slash. */
#ifdef VMS
check_lastslash = lastslash != 0 && index (target, ']') == 0;
#else
check_lastslash = lastslash != 0 && index (target, '/') == 0;
#endif
if (check_lastslash)
{
/* In that case, don't include the

366
job.c
View file

@ -18,9 +18,9 @@ along with GNU Make; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "make.h"
#include "commands.h"
#include "job.h"
#include "file.h"
#include "filedef.h"
#include "commands.h"
#include "variable.h"
#include <assert.h>
@ -36,6 +36,13 @@ static char *dos_bename;
static int dos_batch_file;
#endif /* MSDOS. */
#ifdef VMS
#include <time.h>
#include <processes.h>
#include <starlet.h>
#include <lib$routines.h>
#endif
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#else
@ -102,22 +109,40 @@ extern int wait ();
#endif /* Don't have `union wait'. */
#ifdef VMS
static int vms_jobsefnmask=0;
#endif /* !VMS */
#ifndef HAVE_UNISTD_H
extern int dup2 ();
extern int execve ();
extern void _exit ();
extern int geteuid (), getegid ();
extern int setgid (), getgid ();
#ifndef VMS
extern int geteuid ();
extern int getegid ();
extern int setgid ();
extern int getgid ();
#endif
#endif
extern int getloadavg ();
extern int start_remote_job_p ();
extern int start_remote_job (), remote_status ();
extern char *allocated_variable_expand_for_file PARAMS ((char *line, struct file *file));
RETSIGTYPE child_handler ();
static void free_child (), start_job_command ();
static int load_too_high (), job_next_command ();
extern int getloadavg PARAMS ((double loadavg[], int nelem));
extern int start_remote_job PARAMS ((char **argv, char **envp, int stdin_fd,
int *is_remote, int *id_ptr, int *used_stdin));
extern int start_remote_job_p PARAMS ((void));
extern int remote_status PARAMS ((int *exit_code_ptr, int *signal_ptr,
int *coredump_ptr, int block));
RETSIGTYPE child_handler PARAMS ((int));
static void free_child PARAMS ((struct child *));
static void start_job_command PARAMS ((struct child *child));
static int load_too_high PARAMS ((void));
static int job_next_command PARAMS ((struct child *));
static int start_waiting_job PARAMS ((struct child *));
#ifdef VMS
static void vmsWaitForChildren PARAMS ((int *));
#endif
/* Chain of all live (or recently deceased) children. */
@ -148,6 +173,10 @@ child_error (target_name, exit_code, exit_sig, coredump, ignored)
if (ignored && silent_flag)
return;
#ifdef VMS
if (!(exit_code & 1))
error("*** [%s] Error 0x%x%s", target_name, exit_code, ((ignored)? " (ignored)" : ""));
#else
if (exit_sig == 0)
error (ignored ? "[%s] Error %d (ignored)" :
"*** [%s] Error %d",
@ -156,10 +185,31 @@ child_error (target_name, exit_code, exit_sig, coredump, ignored)
error ("*** [%s] %s%s",
target_name, strsignal (exit_sig),
coredump ? " (core dumped)" : "");
#endif
}
static unsigned int dead_children = 0;
#ifdef VMS
/* Wait for nchildren children to terminate */
static void
vmsWaitForChildren(int *status)
{
while (1)
{
if (!vms_jobsefnmask)
{
*status = 0;
return;
}
*status = sys$wflor (32, vms_jobsefnmask);
}
return;
}
#endif
/* Notice that a child died.
reap_children should be called when convenient. */
RETSIGTYPE
@ -215,7 +265,7 @@ reap_children (block, err)
and we might print the "Waiting for unfinished jobs" message above
when not necessary. */
if (dead_children != 0)
if (dead_children > 0)
--dead_children;
any_remote = 0;
@ -228,6 +278,9 @@ reap_children (block, err)
printf ("Live child 0x%08lx PID %d%s\n",
(unsigned long int) c,
c->pid, c->remote ? " (remote)" : "");
#ifdef VMS
break;
#endif
}
/* First, check for remote children. */
@ -235,6 +288,7 @@ reap_children (block, err)
pid = remote_status (&exit_code, &exit_sig, &coredump, 0);
else
pid = 0;
if (pid < 0)
{
remote_status_lose:
@ -251,19 +305,24 @@ reap_children (block, err)
if (any_local)
{
#ifdef WAIT_NOHANG
#ifdef VMS
vmsWaitForChildren (&status);
pid = c->pid;
#else
#ifdef WAIT_NOHANG
if (!block)
pid = WAIT_NOHANG (&status);
else
#endif
pid = wait (&status);
#endif /* !VMS */
}
else
pid = 0;
if (pid < 0)
{
#ifdef EINTR
#ifdef EINTR
if (errno == EINTR)
continue;
#endif
@ -442,7 +501,8 @@ reap_children (block, err)
free_child (c);
/* There is now another slot open. */
--job_slots_used;
if (job_slots_used > 0)
--job_slots_used;
/* If the job failed, and the -k flag was not given, die,
unless we are already in the process of dying. */
@ -453,6 +513,7 @@ reap_children (block, err)
/* Only block for one child. */
block = 0;
}
return;
}
/* Free the storage allocated for CHILD. */
@ -514,7 +575,11 @@ start_job_command (child)
static int bad_stdin = -1;
register char *p;
int flags;
#ifdef VMS
char *argv;
#else
char **argv;
#endif
/* Combine the flags parsed for the line itself with
the flags specified globally for this target. */
@ -523,6 +588,7 @@ start_job_command (child)
p = child->command_ptr;
child->noerror = flags & COMMANDS_NOERROR;
while (*p != '\0')
{
if (*p == '@')
@ -553,8 +619,12 @@ start_job_command (child)
/* Figure out an argument list from this command line. */
{
char *end;
char *end = 0;
#ifdef VMS
argv = p;
#else
argv = construct_command_argv (p, &end, child->file);
#endif
if (end == NULL)
child->command_ptr = NULL;
else
@ -568,8 +638,10 @@ start_job_command (child)
{
/* Go on to the next command. It might be the recursive one.
We construct ARGV only to find the end of the command line. */
#ifndef VMS
free (argv[0]);
free ((char *) argv);
#endif
argv = 0;
}
@ -608,8 +680,10 @@ start_job_command (child)
if (just_print_flag && !(flags & COMMANDS_RECURSE))
{
#ifndef VMS
free (argv[0]);
free ((char *) argv);
#endif
goto next_command;
}
@ -618,6 +692,8 @@ start_job_command (child)
fflush (stdout);
fflush (stderr);
#ifndef VMS
/* Set up a bad standard input that reads from a broken pipe. */
if (bad_stdin == -1)
@ -652,6 +728,8 @@ start_job_command (child)
if (child->good_stdin)
good_stdin_used = 1;
#endif /* !VMS */
child->deleted = 0;
/* Set up the environment for the child. */
@ -660,6 +738,7 @@ start_job_command (child)
#ifndef __MSDOS__
#ifndef VMS
/* start_waiting_job has set CHILD->remote if we can start a remote job. */
if (child->remote)
{
@ -680,6 +759,7 @@ start_job_command (child)
}
}
else
#endif /* !VMS */
{
/* Fork the child process. */
@ -694,6 +774,17 @@ start_job_command (child)
#endif
child->remote = 0;
#ifdef VMS
if (!child_execute_job (argv, child)) {
/* Fork failed! */
perror_with_name ("vfork", "");
goto error;
}
#else
parent_environ = environ;
child->pid = vfork ();
environ = parent_environ; /* Restore value child may have clobbered. */
@ -711,9 +802,11 @@ start_job_command (child)
perror_with_name ("vfork", "");
goto error;
}
#endif /* !VMS */
}
#else /* MSDOS. */
dos_status = spawnvpe (P_WAIT, argv[0], argv, child->environment);
++dead_children;
child->pid = dos_pid++;
@ -735,15 +828,17 @@ start_job_command (child)
set_command_state (child->file, cs_running);
/* Free the storage used by the child's argument list. */
#ifndef VMS
free (argv[0]);
free ((char *) argv);
#endif
return;
error:
child->file->update_status = 2;
notice_finished_file (child->file);
return;
}
/* Try to start a child running.
@ -949,13 +1044,15 @@ new_job (file)
/* The job is now primed. Start it running.
(This will notice if there are in fact no commands.) */
start_waiting_job (c);
(void)start_waiting_job (c);
if (job_slots == 1)
/* Since there is only one job slot, make things run linearly.
Wait for the child to die, setting the state to `cs_finished'. */
while (file->command_state == cs_running)
reap_children (1, 0);
return;
}
/* Move CHILD's pointers to the next command for it to execute.
@ -984,10 +1081,9 @@ job_next_command (child)
static int
load_too_high ()
{
#ifdef __MSDOS__
#if defined(__MSDOS__) || defined(VMS)
return 1;
#else
extern int getloadavg ();
double load;
if (max_load_average < 0)
@ -1036,10 +1132,226 @@ start_waiting_jobs ()
/* Try to start that job. We break out of the loop as soon
as start_waiting_job puts one back on the waiting list. */
} while (start_waiting_job (job) && waiting_jobs != 0);
}
while (start_waiting_job (job) && waiting_jobs != 0);
return;
}
/* Replace the current process with one executing the command in ARGV.
#ifdef VMS
#include <descrip.h>
#include <clidef.h>
/* This is called as an AST when a child process dies (it won't get
interrupted by anything except a higher level AST).
*/
int vmsHandleChildTerm(struct child *child)
{
int status;
register struct child *lastc, *c;
int child_failed;
vms_jobsefnmask &= ~(1 << (child->efn - 32));
lib$free_ef(&child->efn);
(void) sigblock (fatal_signal_mask);
child_failed = !(child->cstatus & 1 || ((child->cstatus & 7) == 0));
/* Search for a child matching the deceased one. */
lastc = 0;
#if defined(RECURSIVEJOBS) /* I've had problems with recursive stuff and process handling */
for (c = children; c != 0 && c != child; lastc = c, c = c->next);
#else
c = child;
#endif
if (child_failed && !c->noerror && !ignore_errors_flag)
{
/* The commands failed. Write an error message,
delete non-precious targets, and abort. */
child_error (c->file->name, c->cstatus, 0, 0, 0);
c->file->update_status = 1;
delete_child_targets (c);
}
else
{
if (child_failed)
{
/* The commands failed, but we don't care. */
child_error (c->file->name, c->cstatus, 0, 0, 1);
child_failed = 0;
}
#if defined(RECURSIVEJOBS) /* I've had problems with recursive stuff and process handling */
/* If there are more commands to run, try to start them. */
start_job (c);
switch (c->file->command_state)
{
case cs_running:
/* Successfully started. */
break;
case cs_finished:
if (c->file->update_status != 0) {
/* We failed to start the commands. */
delete_child_targets (c);
}
break;
default:
error ("internal error: `%s' command_state \
%d in child_handler", c->file->name);
abort ();
break;
}
#endif /* RECURSIVEJOBS */
}
/* Set the state flag to say the commands have finished. */
c->file->command_state = cs_finished;
notice_finished_file (c->file);
#if defined(RECURSIVEJOBS) /* I've had problems with recursive stuff and process handling */
/* Remove the child from the chain and free it. */
if (lastc == 0)
children = c->next;
else
lastc->next = c->next;
free_child (c);
#endif /* RECURSIVEJOBS */
/* There is now another slot open. */
if (job_slots_used > 0)
--job_slots_used;
/* If the job failed, and the -k flag was not given, die. */
if (child_failed && !keep_going_flag)
die (EXIT_FAILURE);
(void) sigsetmask (sigblock (0) & ~(fatal_signal_mask));
return 1;
}
/* VMS:
Spawn a process executing the command in ARGV and return its pid. */
#define MAXCMDLEN 200
int
child_execute_job (argv, child)
char *argv;
struct child *child;
{
int i;
static struct dsc$descriptor_s cmddsc;
#ifndef DONTWAITFORCHILD
int spflags = 0;
#else
int spflags = CLI$M_NOWAIT;
#endif
int status;
char cmd[4096],*p,*c;
char comname[50];
/* Remove backslashes */
for (p = argv, c = cmd; *p; p++,c++)
{
if (*p == '\\') p++;
*c = *p;
}
*c = *p;
/* check for maximum dcl length and create *.com file if neccesary */
comname[0] = '\0';
if (strlen (cmd) > MAXCMDLEN)
{
FILE *outfile;
char tmp;
strcpy (comname, "sys$scratch:CMDXXXXXX.COM");
(void) mktemp (comname);
outfile = fopen (comname, "w");
if (outfile == 0)
pfatal_with_name (comname);
fprintf (outfile, "$ ");
c = cmd;
while (c)
{
p = strchr (c, ',');
if ((p == NULL) || (p-c > MAXCMDLEN))
p = strchr (c, ' ');
if (p != NULL)
{
p++;
tmp = *p;
*p = '\0';
}
else
tmp = '\0';
fprintf (outfile, "%s%s\n", c, (tmp == '\0')?"":" -");
if (p != NULL)
*p = tmp;
c = p;
}
fclose (outfile);
sprintf (cmd, "$ @%s", comname);
if (debug_flag)
printf ("Executing %s instead\n", cmd);
}
cmddsc.dsc$w_length = strlen(cmd);
cmddsc.dsc$a_pointer = cmd;
cmddsc.dsc$b_dtype = DSC$K_DTYPE_T;
cmddsc.dsc$b_class = DSC$K_CLASS_S;
child->efn = 0;
while (child->efn < 32 || child->efn > 63)
{
status = lib$get_ef(&child->efn);
if (!(status & 1))
return 0;
}
sys$clref(child->efn);
vms_jobsefnmask |= (1 << (child->efn - 32));
#ifndef DONTWAITFORCHILD
status = lib$spawn(&cmddsc,0,0,&spflags,0,&child->pid,&child->cstatus,
&child->efn,0,0);
vmsHandleChildTerm(child);
#else
status = lib$spawn(&cmddsc,0,0,&spflags,0,&child->pid,&child->cstatus,
&child->efn,vmsHandleChildTerm,child);
#endif
if (!(status & 1))
{
printf("Error spawning, %d\n",status);
fflush(stdout);
}
unlink (comname);
return (status & 1);
}
#else /* !VMS */
/* UNIX:
Replace the current process with one executing the command in ARGV.
STDIN_FD and STDOUT_FD are used as the process's stdin and stdout; ENVP is
the environment of the new program. This function does not return. */
@ -1060,6 +1372,7 @@ child_execute_job (stdin_fd, stdout_fd, argv, envp)
/* Run the command. */
exec_command (argv, envp);
}
#endif /* !VMS */
/* Replace the current process with one running the command in ARGV,
with environment ENVP. This function does not return. */
@ -1068,6 +1381,12 @@ void
exec_command (argv, envp)
char **argv, **envp;
{
#ifdef VMS
/* Run the program. */
execve (argv[0], argv, envp);
perror_with_name ("execve: ", argv[0]);
_exit (EXIT_FAILURE);
#else
/* Be the user, permanently. */
child_access ();
@ -1119,8 +1438,10 @@ exec_command (argv, envp)
}
_exit (127);
#endif /* !VMS */
}
#ifndef VMS
/* Figure out the argument list necessary to run LINE as a command. Try to
avoid using a shell. This routine handles only ' quoting, and " quoting
when no backslash, $ or ` characters are seen in the quotes. Starting
@ -1364,7 +1685,7 @@ construct_command_argv_internal (line, restp, shell, ifs)
{
/* Free the old argument list we were working on. */
free (new_argv[0]);
free (new_argv);
free ((void *)new_argv);
}
#ifdef __MSDOS__
@ -1496,6 +1817,7 @@ construct_command_argv (line, restp, file)
return argv;
}
#endif /* !VMS */
#ifndef HAVE_DUP2
int

27
job.h
View file

@ -16,6 +16,9 @@ You should have received a copy of the GNU General Public License
along with GNU Make; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifndef SEEN_JOB_H
#define SEEN_JOB_H
/* Structure describing a running or dead child process. */
struct child
@ -31,6 +34,10 @@ struct child
char *command_ptr; /* Ptr into command_lines[command_line]. */
pid_t pid; /* Child process's ID number. */
#ifdef VMS
int efn; /* Completion event flag number */
int cstatus; /* Completion status */
#endif
unsigned int remote:1; /* Nonzero if executing remotely. */
unsigned int noerror:1; /* Nonzero if commands contained a `-'. */
@ -41,18 +48,22 @@ struct child
extern struct child *children;
extern void new_job ();
extern void reap_children ();
extern void start_waiting_jobs ();
extern void new_job PARAMS ((struct file *file));
extern void reap_children PARAMS ((int block, int err));
extern void start_waiting_jobs PARAMS ((void));
extern char **construct_command_argv ();
extern void child_execute_job ();
extern void exec_command ();
extern char **construct_command_argv PARAMS ((char *line, char **restp, struct file *file));
#ifdef VMS
extern int child_execute_job PARAMS ((char *argv, struct child *child));
#else
extern void child_execute_job PARAMS ((int stdin_fd, int stdout_fd, char **argv, char **envp));
#endif
extern void exec_command PARAMS ((char **argv, char **envp));
extern unsigned int job_slots_used;
#ifdef POSIX
extern void unblock_sigs ();
extern void unblock_sigs PARAMS ((void));
#else
#ifdef HAVE_SIGSETMASK
extern int fatal_signal_mask;
@ -61,3 +72,5 @@ extern int fatal_signal_mask;
#define unblock_sigs()
#endif
#endif
#endif /* SEEN_JOB_H */

49
main.c
View file

@ -17,20 +17,23 @@ along with GNU Make; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "make.h"
#include "commands.h"
#include "dep.h"
#include "file.h"
#include "filedef.h"
#include "variable.h"
#include "job.h"
#include "commands.h"
#include "getopt.h"
#include <assert.h>
extern void init_dir PARAMS ((void));
extern RETSIGTYPE fatal_error_signal PARAMS ((int sig));
extern RETSIGTYPE child_handler PARAMS ((int sig));
extern void print_variable_data_base ();
extern void print_dir_data_base ();
extern void print_rule_data_base ();
extern void print_file_data_base ();
extern void print_vpath_data_base ();
extern void print_variable_data_base PARAMS ((void));
extern void print_dir_data_base PARAMS ((void));
extern void print_rule_data_base PARAMS ((void));
extern void print_file_data_base PARAMS ((void));
extern void print_vpath_data_base PARAMS ((void));
#ifndef HAVE_UNISTD_H
extern int chdir ();
@ -43,10 +46,12 @@ extern double atof ();
#endif
extern char *mktemp ();
static void print_data_base (), print_version ();
static void decode_switches (), decode_env_switches ();
static void define_makeflags ();
static char *quote_as_word ();
static void print_data_base PARAMS((void));
static void print_version PARAMS ((void));
static void decode_switches PARAMS ((int argc, char **argv, int env));
static void decode_env_switches PARAMS ((char *envar, unsigned int len));
static void define_makeflags PARAMS ((int all, int makefile));
static char *quote_as_word PARAMS ((char *out, char *in, int double_dollars));
/* The structure that describes an accepted command switch. */
@ -415,7 +420,6 @@ main (argc, argv, envp)
char **argv;
char **envp;
{
extern RETSIGTYPE fatal_error_signal (), child_handler ();
register struct file *f;
register unsigned int i;
char **p;
@ -486,7 +490,11 @@ main (argc, argv, envp)
program = "make";
else
{
#ifdef VMS
program = rindex (argv[0], ']');
#else
program = rindex (argv[0], '/');
#endif
#ifdef __MSDOS__
if (program == 0)
program = rindex (argv[0], '\\');
@ -560,7 +568,7 @@ main (argc, argv, envp)
if (print_version_flag)
die (0);
#ifndef __MSDOS__
#if !defined(__MSDOS__) && !defined(VMS)
/* Set the "MAKE_COMMAND" variable to the name we were invoked with.
(If it is a relative pathname with a slash, prepend our directory name
so the result will run the same program regardless of the current dir.
@ -699,7 +707,12 @@ main (argc, argv, envp)
/* Make a unique filename. */
#ifdef HAVE_MKTEMP
#ifdef VMS
static char name[] = "sys$scratch:GmXXXXXX";
#else
static char name[] = "/tmp/GmXXXXXX";
#endif
(void) mktemp (name);
#else
static char name[L_tmpnam];
@ -1101,15 +1114,15 @@ main (argc, argv, envp)
/* Nothing happened. */
case 0:
/* Updated successfully. */
status = 0;
status = EXIT_SUCCESS;
break;
case 2:
/* Updating failed. */
status = 2;
status = EXIT_FAILURE;
break;
case 1:
/* We are under -q and would run some commands. */
status = 1;
status = EXIT_FAILURE;
break;
default:
abort ();
@ -1589,7 +1602,11 @@ quote_as_word (out, in, double_dollars)
{
while (*in != '\0')
{
#ifdef VMS
if (index ("^;'\"*?$<>(){}|&~`\\ \t\r\n\f\v", *in) != 0)
#else
if (index ("^;'\"*?[]$<>(){}|&~`\\ \t\r\n\f\v", *in) != 0)
#endif
*out++ = '\\';
if (double_dollars && *in == '$')
*out++ = '$';

119
make.h
View file

@ -1,5 +1,5 @@
/* Miscellaneous global declarations and portability cruft for GNU Make.
Copyright (C) 1988, 89, 90, 91, 92, 93, 94, 95 Free Software Foundation, Inc.
Copyright (C) 1988,89,90,91,92,93,94,95,96 Free Software Foundation, Inc.
This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify
@ -28,6 +28,17 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#undef HAVE_CONFIG_H
#define HAVE_CONFIG_H
/* Use prototypes if available. */
#if defined (__cplusplus) || (defined (__STDC__) && __STDC__)
#undef PARAMS
#define PARAMS(protos) protos
#else /* Not C++ or ANSI C. */
#undef PARAMS
#define PARAMS(protos) ()
#endif /* C++ or ANSI C. */
#ifdef CRAY
/* This must happen before #include <signal.h> so
that the declaration therein is changed. */
@ -67,9 +78,7 @@ extern int errno;
#endif
/* Some systems define _POSIX_VERSION but are not really POSIX.1. */
#if (defined (butterfly) || defined (__arm) || \
(defined (__mips) && defined (_SYSTYPE_SVR3)) || \
(defined (sequent) && defined (i386)))
#if (defined (butterfly) || defined (__arm) || (defined (__mips) && defined (_SYSTYPE_SVR3)) || (defined (sequent) && defined (i386)))
#undef POSIX
#endif
@ -132,7 +141,7 @@ extern char *sys_siglist[];
#define PATH_VAR(var) char var[PATH_MAX]
#else
#define NEED_GET_PATH_MAX
extern unsigned int get_path_max ();
extern unsigned int get_path_max PARAMS ((void));
#define GET_PATH_MAX (get_path_max ())
#define PATH_VAR(var) char *var = (char *) alloca (GET_PATH_MAX)
#endif
@ -153,8 +162,16 @@ extern unsigned int get_path_max ();
#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
#endif
#ifdef VMS
#include <stdio.h>
#include <types.h>
#include <unixlib.h>
#include <unixio.h>
#include <errno.h>
#include <perror.h>
#endif
#if (defined (STDC_HEADERS) || defined (__GNU_LIBRARY__))
#if (defined (STDC_HEADERS) || defined (__GNU_LIBRARY__) || defined(VMS))
#include <stdlib.h>
#include <string.h>
#define ANSI_STRING
@ -170,10 +187,12 @@ extern unsigned int get_path_max ();
#include <memory.h>
#endif
extern char *malloc (), *realloc ();
extern void free ();
extern char *malloc PARAMS ((int));
extern char *realloc PARAMS ((char *, int));
extern void free PARAMS ((char *));
extern void abort (), exit ();
extern void abort PARAMS ((void));
extern void exit PARAMS ((int));
#endif /* Standard headers. */
@ -214,8 +233,8 @@ extern void bcopy ();
/* SCO Xenix has a buggy macro definition in <string.h>. */
#undef strerror
#ifndef ANSI_STRING
extern char *strerror ();
#if !defined(ANSI_STRING) && !defined(__DECC)
extern char *strerror PARAMS ((int errnum));
#endif
@ -258,19 +277,30 @@ extern char *alloca ();
#endif
extern void die ();
extern void message (), fatal (), error ();
extern void message ();
extern void fatal ();
extern void error ();
extern void log_working_directory ();
extern void makefile_error (), makefile_fatal ();
extern void pfatal_with_name (), perror_with_name ();
extern char *savestring (), *concat ();
extern char *xmalloc (), *xrealloc ();
extern char *find_next_token (), *next_token (), *end_of_token ();
extern void collapse_continuations (), remove_comments ();
extern char *sindex (), *lindex ();
extern void makefile_error ();
extern void makefile_fatal ();
extern void pfatal_with_name ();
extern void perror_with_name ();
extern char *savestring ();
extern char *concat ();
extern char *xmalloc ();
extern char *xrealloc ();
extern char *find_next_token ();
extern char *next_token ();
extern char *end_of_token ();
extern void collapse_continuations ();
extern void remove_comments ();
extern char *sindex ();
extern char *lindex ();
extern int alpha_compare ();
extern void print_spaces ();
extern struct dep *copy_dep_chain ();
extern char *find_char_unquote (), *find_percent ();
extern char *find_char_unquote ();
extern char *find_percent ();
#ifndef NO_ARCHIVES
extern int ar_name ();
@ -280,16 +310,22 @@ extern time_t ar_member_date ();
#endif
extern void dir_load ();
extern int dir_file_exists_p (), file_exists_p (), file_impossible_p ();
extern int dir_file_exists_p ();
extern int file_exists_p ();
extern int file_impossible_p ();
extern void file_impossible ();
extern char *dir_name ();
extern void define_default_variables ();
extern void set_default_suffixes (), install_default_suffix_rules ();
extern void install_default_implicit_rules (), count_implicit_rule_limits ();
extern void convert_to_pattern (), create_pattern_rule ();
extern void set_default_suffixes ();
extern void install_default_suffix_rules ();
extern void install_default_implicit_rules ();
extern void count_implicit_rule_limits ();
extern void convert_to_pattern ();
extern void create_pattern_rule ();
extern void build_vpath_lists (), construct_vpath_list ();
extern void build_vpath_lists ();
extern void construct_vpath_list ();
extern int vpath_search ();
extern void construct_include_path ();
@ -298,8 +334,9 @@ extern void uniquize_deps ();
extern int update_goal_chain ();
extern void notice_finished_file ();
extern void user_access (), make_access (), child_access ();
extern void user_access ();
extern void make_access ();
extern void child_access ();
#ifdef HAVE_VFORK_H
#include <vfork.h>
@ -311,12 +348,17 @@ extern void user_access (), make_access (), child_access ();
#if !defined (__GNU_LIBRARY__) && !defined (POSIX) && !defined (_POSIX_VERSION)
extern long int atol ();
#ifndef VMS
extern long int lseek ();
#endif
#endif /* Not GNU C library or POSIX. */
#ifdef HAVE_GETCWD
extern char *getcwd ();
#ifdef VMS
extern char *getwd PARAMS ((char *));
#endif
#else
extern char *getwd ();
#define getcwd(buf, len) getwd (buf)
@ -349,3 +391,26 @@ extern int handling_fatal_signal;
#define DEBUGPR(msg) \
do if (debug_flag) { print_spaces (depth); printf (msg, file->name); \
fflush (stdout); } while (0)
#ifdef VMS
# ifndef EXIT_FAILURE
# define EXIT_FAILURE 3
# endif
# ifndef EXIT_SUCCESS
# define EXIT_SUCCESS 1
# endif
# ifndef EXIT_TROUBLE
# define EXIT_TROUBLE 2
# endif
#else
# ifndef EXIT_FAILURE
# define EXIT_FAILURE 2
# endif
# ifndef EXIT_SUCCESS
# define EXIT_SUCCESS 0
# endif
# ifndef EXIT_TROUBLE
# define EXIT_TROUBLE 1
# endif
#endif

34
makefile.com Normal file
View file

@ -0,0 +1,34 @@
$!
$! Makefile.com - builds GNU Make for VMS
$!
$! P1 is non-empty if you want to link with the VAXCRTL library instead
$! of the shareable executable
$!
$ def/nolog sys sys$library:
$ filelist = "alloca commands default dir expand file function implicit job main misc read remake remote-stub rule signame variable version vmsfunctions vmsify vpath [.glob]glob [.glob]fnmatch getopt getopt1"
$ copy config.h-vms config.h
$ n=0
$ loop:
$ cfile = f$elem(n," ",filelist)
$ if cfile .eqs. " " then goto linkit
$ write sys$output "Compiling ''cfile'..."
$ call compileit 'cfile' 'p1'
$ n = n + 1
$ goto loop
$ linkit:
$ if p1 .nes. "" then goto link_using_library
$ link/exe=make alloca,commands,default,dir,expand,file,function,-
implicit,job,main,misc,read,remake,remote-stub,rule,-
signame,variable,version,vmsfunctions,vmsify,vpath,-
glob,fnmatch,getopt,getopt1
$ exit
$ link_using_library:
$ link/exe=make alloca,commands,default,dir,expand,file,function,-
implicit,job,main,misc,read,remake,remote-stub,rule,-
signame,variable,version,vmsfunctions,vmsfiy,vpath,-
glob,fnmatch,getopt,getopt1,sys$library:vaxcrtl/lib
$!
$ compileit : subroutine
$ cc/include=([],[.glob])/define=("allocated_variable_expand_for_file=alloc_var_expand_for_file","unlink=remove","HAVE_CONFIG_H","VMS","NO_ARCHIVES") 'p1'
$ exit
$ endsubroutine : compileit

121
makefile.vms Normal file
View file

@ -0,0 +1,121 @@
# Copyright (C) 1988, 1989 Free Software Foundation, Inc.
# This file is part of GNU Make.
#
# VMS extensions from GNU Make 3.60 imported by
# Klaus Kämpf (kkaempf@didymus.rmi.de)
#
# GNU Make is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 1, or (at your option)
# any later version.
#
# GNU Make is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with GNU Make; see the file COPYING. If not, write to
# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
CC = cc/warn
CP = copy
%.obj: %.c
$(CC) $(CFLAGS)/obj=$@ $<
#
# Makefile for GNU Make
#
CFLAGS = $(defines) /debug/noopt/include=([],[.glob])
#LDFLAGS = /deb
LDFLAGS =
defines = /define=("unlink=remove","HAVE_CONFIG_H","VMS","NO_ARCHIVES","allocated_variable_expand_for_file=alloc_var_expand_for_file")
LOAD_AVG = /define="NO_LDAV"
# If you don't want archive support, comment these out.
#ARCHIVES = ,ar.obj,arscan.obj
#ARCHIVES_SRC = ar.c arscan.c
# If your system needs extra libraries loaded in, define them here.
# System V probably need -lPW for alloca.
# if on vax, uncomment the following line
#LOADLIBES = ,c.opt/opt
LOADLIBES =
# If your system doesn't have alloca, or the one provided is bad,
# get it from the Emacs distribution and define these.
ALLOCA = ,alloca.obj
ALLOCASRC = alloca.c
# If there are remote execution facilities defined,
# enable them with switches here (see remote-*.c).
REMOTE =
# Any extra object files your system needs.
extras = ,signame.obj,remote-stub.obj,vmsfunctions.obj,vmsify.obj
#,directory.obj
# as an alternative:
glob = ,[.glob]glob.obj,[.glob]fnmatch.obj
getopt = ,getopt.obj,getopt1.obj
# Directory to install `make' in.
bindir = []
# Directory to install the man page in.
mandir = []
# Number to put on the man page filename.
manext = 1
objs = commands.obj,job.obj,dir.obj,file.obj,misc.obj,\
main.obj,read.obj,remake.obj,rule.obj,implicit.obj,\
default.obj,variable.obj,expand.obj,function.obj,\
vpath.obj,version.obj$(ARCHIVES)$(ALLOCA)$(extras)$(getopt)$(glob)
srcs = commands.c job.c dir.c file.c misc.c \
main.c read.c remake.c rule.c implicit.c \
default.c variable.c expand.c function.c \
vpath.c version.c vmsfunctions.c vmsify.c $(ARCHIVES_SRC) $(ALLOCASRC) \
commands.h dep.h filedef.h job.h make.h rule.h variable.h
.PHONY: all doc
all: config.h make.exe
doc: make.info make.dvi
make.exe: $(objs)
$(LD)$(LDFLAGS)/exe=$@ $^$(LOADLIBES)
.PHONY: clean realclean
clean:
-$(RM) make.exe;,*.obj;*
# Automatically generated dependencies.
commands.obj: commands.c make.h dep.h commands.h filedef.h variable.h job.h
job.obj: job.c make.h commands.h job.h filedef.h variable.h
dir.obj: dir.c make.h
file.obj: file.c make.h commands.h dep.h filedef.h variable.h
misc.obj: misc.c make.h dep.h
main.obj: main.c make.h commands.h dep.h filedef.h variable.h job.h
read.obj: read.c make.h commands.h dep.h filedef.h variable.h
remake.obj: remake.c make.h commands.h job.h dep.h filedef.h
rule.obj: rule.c make.h commands.h dep.h filedef.h variable.h rule.h
implicit.obj: implicit.c make.h rule.h dep.h filedef.h
default.obj: default.c make.h rule.h dep.h filedef.h commands.h variable.h
variable.obj: variable.c make.h commands.h variable.h dep.h filedef.h
expand.obj: expand.c make.h commands.h filedef.h variable.h
function.obj: function.c make.h variable.h dep.h commands.h job.h
vpath.obj: vpath.c make.h filedef.h variable.h
version.obj: version.c
arscan.obj: arscan.c
ar.obj: ar.c make.h filedef.h
signame.obj: signame.c
remote-stub.obj: remote-stub.c
[.glob]glob.obj: [.glob]glob.c
[.glob]fnmatch.obj: [.glob]fnmatch.c
getopt.obj: getopt.c
getopt1.obj: getopt1.c
config.h: config.h-vms
$(CP) $< $@

4
misc.c
View file

@ -271,7 +271,9 @@ strerror (errnum)
int errnum;
{
extern int errno, sys_nerr;
#ifndef __DECC
extern char *sys_errlist[];
#endif
static char buf[] = "Unknown error 12345678901234567890";
if (errno < sys_nerr)
@ -540,6 +542,7 @@ log_access (flavor)
static void
init_access ()
{
#ifndef VMS
user_uid = getuid ();
user_gid = getgid ();
@ -553,6 +556,7 @@ init_access ()
log_access ("Initialized");
current_access = make;
#endif
}
#endif /* GETLOADAVG_PRIVILEGED */

103
read.c
View file

@ -17,9 +17,10 @@ along with GNU Make; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "make.h"
#include "commands.h"
#include "dep.h"
#include "file.h"
#include "filedef.h"
#include "job.h"
#include "commands.h"
#include "variable.h"
/* This is POSIX.2, but most systems using -DPOSIX probably don't have it. */
@ -29,15 +30,11 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "glob/glob.h"
#endif
#ifndef VMS
#include <pwd.h>
struct passwd *getpwnam ();
static int read_makefile ();
static unsigned int readline (), do_define ();
static int conditional_line ();
static void record_files ();
#else
struct passwd *getpwnam PARAMS ((char *name));
#endif
/* A `struct linebuffer' is a structure which holds a line of text.
`readline' reads a line from a stream into a linebuffer
@ -104,6 +101,18 @@ unsigned int *reading_lineno_ptr;
/* The chain of makefiles read by read_makefile. */
static struct dep *read_makefiles = 0;
static int read_makefile PARAMS ((char *filename, int flags));
static unsigned int readline PARAMS ((struct linebuffer *linebuffer, FILE *stream,
char *filename, unsigned int lineno));
static unsigned int do_define PARAMS ((char *name, unsigned int namelen, enum variable_origin origin,
unsigned int lineno, FILE *infile, char *filename));
static int conditional_line PARAMS ((char *line, char *filename, unsigned int lineno));
static void record_files PARAMS ((struct nameseq *filenames, char *pattern, char *pattern_percent,
struct dep *deps, unsigned int commands_started, char *commands,
unsigned int commands_idx, int two_colon, char *filename,
unsigned int lineno, int set_default));
static char *find_semicolon PARAMS ((char *s));
/* Read in all the makefiles and return the chain of their names. */
@ -138,6 +147,7 @@ read_all_makefiles (makefiles)
/* Set NAME to the start of next token and LENGTH to its length.
MAKEFILES is updated for finding remaining tokens. */
p = value;
while ((name = find_next_token (&p, &length)) != 0)
{
if (*p != '\0')
@ -176,7 +186,12 @@ read_all_makefiles (makefiles)
if (num_makefiles == 0)
{
static char *default_makefiles[] =
#if VMS
/* all lower case since readdir() (the vms version) 'lowercasifies' */
{ "makefile.vms", "gnumakefile", "makefile", 0 };
#else
{ "GNUmakefile", "makefile", "Makefile", 0 };
#endif
register char **p = default_makefiles;
while (*p != 0 && !file_exists_p (*p))
++p;
@ -302,7 +317,6 @@ read_makefile (filename, flags)
/* If the makefile wasn't found and it's either a makefile from
the `MAKEFILES' variable or an included makefile,
search the included makefile search path for this makefile. */
if (infile == 0 && (flags & RM_INCLUDED) && *filename != '/')
{
register unsigned int i;
@ -586,7 +600,7 @@ read_makefile (filename, flags)
{
struct nameseq *next = files->next;
char *name = files->name;
free (files);
free ((char *)files);
files = next;
if (! read_makefile (name, (RM_INCLUDED | RM_NO_TILDE
@ -1303,7 +1317,7 @@ record_files (filenames, pattern, pattern_percent, deps, commands_started,
{
struct dep *nextd = d->next;
free (d->name);
free (d);
free ((char *)d);
d = nextd;
}
f->deps = 0;
@ -1520,9 +1534,16 @@ parse_file_seq (stringp, stopchar, size, strip)
register char *p = *stringp;
char *q;
char *name;
char stopchars[2];
char stopchars[3];
#ifdef VMS
stopchars[0] = ',';
stopchars[1] = stopchar;
stopchars[2] = '\0';
#else
stopchars[0] = stopchar;
stopchars[1] = '\0';
#endif
while (1)
{
@ -1532,9 +1553,16 @@ parse_file_seq (stringp, stopchar, size, strip)
break;
if (*p == stopchar)
break;
/* Yes, find end of next name. */
q = p;
p = find_char_unquote (q, stopchars, 1);
#ifdef VMS
/* convert comma separated list to space separated */
if (p && *p == ',')
*p =' ';
#endif
#ifdef __MSDOS__
/* For MS-DOS, skip a "C:\...". */
if (stopchar == ':' && p != 0 && p[1] == '\\' && isalpha (p[-1]))
@ -1544,8 +1572,13 @@ parse_file_seq (stringp, stopchar, size, strip)
p = q + strlen (q);
if (strip)
#ifdef VMS
/* Skip leading `[]'s. */
while (p - q > 2 && q[0] == '[' && q[1] == ']')
#else
/* Skip leading `./'s. */
while (p - q > 2 && q[0] == '.' && q[1] == '/')
#endif
{
q += 2; /* Skip "./". */
while (q < p && *q == '/')
@ -1556,10 +1589,40 @@ parse_file_seq (stringp, stopchar, size, strip)
/* Extract the filename just found, and skip it. */
if (q == p)
/* ".///" was stripped to "". */
/* ".///" was stripped to "". */
#ifdef VMS
continue;
#else
name = savestring ("./", 2);
#endif
else
#ifdef VMS
/* VMS filenames can have a ':' in them but they have to be '\'ed but we need
* to remove this '\' before we can use the filename.
* Savestring called because q may be read-only string constant.
*/
{
char *qbase = savestring(q, strlen(q));
char *pbase = qbase + (p-q);
char *q1 = qbase;
char *q2 = q1;
char *p1 = pbase;
while (q1 != pbase)
{
if (*q1 == '\\' && *(q1+1) == ':')
{
q1++;
p1--;
}
*q2++ = *q1++;
}
name = savestring (qbase, p1 - qbase);
free (qbase);
}
#else
name = savestring (q, p - q);
#endif
/* Add it to the front of the chain. */
new1 = (struct nameseq *) xmalloc (size);
@ -1787,8 +1850,11 @@ construct_include_path (arg_dirs)
char **arg_dirs;
{
register unsigned int i;
#ifdef VAXC /* just don't ask ... */
stat_t stbuf;
#else
struct stat stbuf;
#endif
/* Table to hold the dirs. */
register unsigned int defsize = (sizeof (default_include_directories)
@ -1860,6 +1926,7 @@ char *
tilde_expand (name)
char *name;
{
#ifndef VMS
if (name[1] == '/' || name[1] == '\0')
{
extern char *getenv ();
@ -1919,7 +1986,7 @@ tilde_expand (name)
else if (userend != 0)
*userend = '/';
}
#endif /* !VMS */
return 0;
}
@ -2037,7 +2104,7 @@ multi_glob (chain, size)
}
globfree (&gl);
free (old->name);
free (old);
free ((char *)old);
break;
}

62
readme.vms Normal file
View file

@ -0,0 +1,62 @@
This is the VMS port of GNU Make version 3.74.
It is based on the VMS port of GNU Make 3.60 by Mike Moretti.
This port was done by Klaus Kämpf (kkaempf@didymus.rmi.de)
To build Make, simply type @makefile. This should compile all the
necessary files and link Make.
There is also a file called makefile.vms. If you already have GNU
Make 3.74 built you can just use Make with this makefile to rebuild.
Here are some notes about GNU Make for VMS:
Libraries are not supported. They were in GNU Make 3.60 but somehow I didn't
care porting the code. If there is enough interest, I'll do it at some
later time.
The variable $^ separates files with commas instead of spaces (It's the
natural thing to do for VMS).
See defaults.c for VMS default suffixes and my definitions for default
rules and variables.
The shell function is not implemented yet.
Load average routines haven't been implemented for VMS yet.
The default include directory for including other makefiles is
SYS$SYSROOT:[SYSLIB] (I don't remember why I didn't just use
SYS$LIBRARY: instead; maybe it wouldn't work that way).
The default makefiles make looks for are: makefile.vms, gnumakefile, makefile.,
and gnumakefile. .
The stat() function and handling of time stamps in VMS is broken, so I
replaced it with a hack in vmsfunctions.c. I will provide a full rewrite
somewhere in the future. Be warned, the time resolution inside make is
less than what vms provides. This might be a problem on the faster Alphas.
You can use a : in a filename only if you preceed it with a backslash ('\').
E.g.- hobbes\:[bogas.files]
None of the stuff in vpath.c has been implemented yet.
Make ignores success, informational, or warning errors (-S-, -I-, or -W-).
But it will stop on -E- and -F- errors. (unless you do something to override
this in your makefile, or whatever).
Remote stuff isn't implemented yet.
Multiple line DCL commands, such as "if" statements, must be put inside
command files. You can run a command file by using \@.
VMS changes made for 3.74.3
Lots of default settings are adapted for VMS. See default.c.
Long command lines are now converted to command files.
Comma (',') as a separator is now allowed. See makefile.vms for an example.

View file

@ -17,10 +17,10 @@ along with GNU Make; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "make.h"
#include "commands.h"
#include "filedef.h"
#include "job.h"
#include "commands.h"
#include "dep.h"
#include "file.h"
#include <assert.h>
#ifdef HAVE_FCNTL_H
@ -29,17 +29,30 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <sys/file.h>
#endif
extern int try_implicit_rule ();
#ifdef VMS
#include <starlet.h>
#endif
extern int try_implicit_rule PARAMS ((struct file *file, unsigned int depth));
/* Incremented when a command is started (under -n, when one would be). */
unsigned int commands_started = 0;
static int update_file (), update_file_1 (), check_dep (), touch_file ();
static void remake_file ();
static time_t name_mtime ();
static int library_search ();
extern time_t f_mtime ();
static int update_file PARAMS ((struct file *file, unsigned int depth));
static int update_file_1 PARAMS ((struct file *file, unsigned int depth));
static int check_dep PARAMS ((struct file *file, unsigned int depth, time_t this_mtime, int *must_make_ptr));
static int touch_file PARAMS ((struct file *file));
static void remake_file PARAMS ((struct file *file));
static time_t name_mtime PARAMS ((char *name));
static int library_search PARAMS ((char **lib, time_t *mtime_ptr));
extern time_t f_mtime PARAMS ((struct file *file, int search));
#ifdef VMS
extern int vms_stat PARAMS ((char *name, struct stat *buf));
#endif
/* Remake all the goals in the `struct dep' chain GOALS. Return -1 if nothing
was done, 0 if all goals were updated successfully, or 1 if a goal failed.
@ -100,6 +113,7 @@ update_goal_chain (goals, makefiles)
/* Iterate over all double-colon entries for this file. */
struct file *file = g->file;
int stop, any_not_updated = 0;
for (file = g->file->double_colon ? g->file->double_colon : g->file;
file != NULL;
file = file->prev)
@ -108,7 +122,6 @@ update_goal_chain (goals, makefiles)
int x;
time_t mtime = MTIME (file);
check_renamed (file);
if (makefiles)
{
if (file->cmd_target)
@ -229,7 +242,6 @@ update_goal_chain (goals, makefiles)
just_print_flag = n;
job_slots = j;
}
return status;
}
@ -1015,12 +1027,28 @@ f_mtime (file, search)
unrecoverably absent. */
static time_t now;
#ifdef VMS
/* Handle vms 64bit to 32bit time hack introduced in vms_stat() ... */
static unsigned long vms_now[2]; /* assumes 32 bit long ! */
static int vms_now_set = 0;
if (!vms_now_set)
{
sys$gettim(vms_now);
now = ((vms_now[0]>>24) & 0xff) + ((vms_now[1]<<8) & 0xffffff00);
vms_now_set = 1;
}
#endif
if (mtime > now && ! file->updated)
{
/* This file's time appears to be in the future.
Update our concept of the present, and compare again. */
#ifndef VMS
extern time_t time ();
if (mtime > time (&now))
#else
if ((mtime != -1) && (mtime > now))
#endif
{
error ("*** File `%s' has modification time in the future",
file->name);
@ -1050,7 +1078,11 @@ name_mtime (name)
{
struct stat st;
#ifdef VMS
if (vms_stat (name, &st) < 0)
#else
if (stat (name, &st) < 0)
#endif
return (time_t) -1;
return (time_t) st.st_mtime;

View file

@ -17,6 +17,8 @@ along with GNU Make; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "make.h"
#include "filedef.h"
#include "job.h"
#include "commands.h"

23
rule.c
View file

@ -17,13 +17,14 @@ along with GNU Make; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "make.h"
#include "commands.h"
#include "dep.h"
#include "file.h"
#include "filedef.h"
#include "job.h"
#include "commands.h"
#include "variable.h"
#include "rule.h"
static void freerule ();
static void freerule PARAMS ((struct rule *rule, struct rule *lastrule));
/* Chain of all pattern rules. */
@ -96,9 +97,13 @@ count_implicit_rule_limits ()
for (dep = rule->deps; dep != 0; dep = dep->next)
{
unsigned int len = strlen (dep->name);
char *p = rindex (dep->name, '/');
char *p2 = p != 0 ? index (dep->name, '%') : 0;
#ifdef VMS
char *p = rindex (dep->name, ']');
#else
char *p = rindex (dep->name, '/');
#endif
char *p2 = p != 0 ? index (dep->name, '%') : 0;
ndeps++;
if (len > max_pattern_dep_length)
@ -125,7 +130,11 @@ count_implicit_rule_limits ()
nonexistent subdirectory. */
dep->changed = !dir_file_exists_p (name, "");
#ifdef VMS
if (dep->changed && *name == ']')
#else
if (dep->changed && *name == '/')
#endif
{
/* The name is absolute and the directory does not exist.
This rule can never possibly match, since this dependency
@ -173,7 +182,11 @@ convert_suffix_rule (target, source, cmds)
/* Special case: TARGET being nil means we are defining a
`.X.a' suffix rule; the target pattern is always `(%.o)'. */
{
#ifdef VMS
targname = savestring ("(%.obj)", 7);
#else
targname = savestring ("(%.o)", 5);
#endif
targpercent = targname + 1;
}
else

4
rule.h
View file

@ -49,5 +49,5 @@ extern struct file *suffix_file;
extern unsigned int maxsuffix;
extern void install_pattern_rule ();
int new_pattern_rule ();
extern void install_pattern_rule PARAMS ((struct pspec *p, int terminal));
extern int new_pattern_rule PARAMS ((struct rule *rule, int override));

View file

@ -17,10 +17,11 @@ along with GNU Make; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "make.h"
#include "dep.h"
#include "filedef.h"
#include "job.h"
#include "commands.h"
#include "variable.h"
#include "dep.h"
#include "file.h"
/* Hash table of all global variable definitions. */
@ -39,6 +40,11 @@ static struct variable_set global_variable_set
static struct variable_set_list global_setlist
= { 0, &global_variable_set };
struct variable_set_list *current_variable_set_list = &global_setlist;
static struct variable *define_variable_in_set PARAMS ((char *name, unsigned int length,
char *value, enum variable_origin origin,
int recursive, struct variable_set *set));
/* Implement variables. */

View file

@ -70,31 +70,40 @@ struct variable_set_list
extern struct variable_set_list *current_variable_set_list;
extern void push_new_variable_scope (), pop_variable_scope ();
extern int handle_function ();
extern char *variable_buffer_output ();
extern char *variable_expand (), *variable_expand_for_file ();
extern char *allocated_variable_expand_for_file ();
/* expand.c */
extern char *variable_buffer_output PARAMS ((char *ptr, char *string, unsigned int length));
extern char *variable_expand PARAMS ((char *line));
extern char *variable_expand_for_file PARAMS ((char *line, struct file *file));
extern char *allocated_variable_expand_for_file PARAMS ((char *line, struct file *file));
#define allocated_variable_expand(line) \
allocated_variable_expand_for_file (line, (struct file *) 0)
extern char *expand_argument ();
extern char *expand_argument PARAMS ((char *str, char *end));
extern void define_automatic_variables ();
extern void initialize_file_variables ();
extern void print_file_variables ();
/* function.c */
extern int handle_function PARAMS ((char **op, char **stringp));
extern int pattern_matches PARAMS ((char *pattern, char *percent, char *word));
extern char *subst_expand PARAMS ((char *o, char *text, char *subst, char *replace,
unsigned int slen, unsigned int rlen, int by_word, int suffix_only));
extern char *patsubst_expand PARAMS ((char *o, char *text, char *pattern, char *replace,
char *pattern_percent, char *replace_percent));
extern void merge_variable_set_lists ();
/* expand.c */
extern char *recursively_expand PARAMS ((struct variable *v));
extern struct variable *try_variable_definition ();
/* variable.c */
extern void push_new_variable_scope PARAMS ((void));
extern void pop_variable_scope PARAMS ((void));
extern void define_automatic_variables PARAMS ((void));
extern void initialize_file_variables PARAMS ((struct file *file));
extern void print_file_variables PARAMS ((struct file *file));
extern void merge_variable_set_lists PARAMS ((struct variable_set_list **setlist0, struct variable_set_list *setlist1));
extern struct variable *try_variable_definition PARAMS ((char *filename, unsigned int lineno, char *line, enum variable_origin origin));
extern struct variable *lookup_variable (), *define_variable ();
extern struct variable *define_variable_for_file ();
extern struct variable *lookup_variable PARAMS ((char *name, unsigned int length));
extern struct variable *define_variable PARAMS ((char *name, unsigned int length, char *value,
enum variable_origin origin, int recursive));
extern struct variable *define_variable_for_file PARAMS ((char *name, unsigned int length,
char *value, enum variable_origin origin, int recursive, struct file *file));
extern char **target_environment PARAMS ((struct file *file));
extern int pattern_matches ();
extern char *subst_expand (), *patsubst_expand (), *recursively_expand ();
extern char **target_environment ();
extern int export_all_variables;

40
vmsdir.h Normal file
View file

@ -0,0 +1,40 @@
/* dirent.h for vms */
#include <rms.h>
#define MAXNAMLEN 255
typedef unsigned long u_long;
typedef unsigned short u_short;
struct direct {
off_t d_off;
u_long d_fileno;
u_short d_reclen;
u_short d_namlen;
char d_name[MAXNAMLEN + 1];
};
#undef DIRSIZ
#define DIRSIZ(dp) \
(((sizeof (struct direct) - (MAXNAMLEN+1) + ((dp)->d_namlen+1)) + 3) & ~3)
#define d_ino d_fileno /* compatability */
/*
* Definitions for library routines operating on directories.
*/
typedef struct FAB DIR;
#ifndef NULL
#define NULL 0
#endif
extern DIR *opendir PARAMS (());
extern struct direct *readdir PARAMS ((DIR *dfd));
#define rewinddir(dirp) seekdir((dirp), (long)0)
extern int closedir PARAMS ((DIR *dfd));
extern char *vmsify PARAMS ((char *name, int type));
/* EOF */

234
vmsfunctions.c Normal file
View file

@ -0,0 +1,234 @@
#define KDEBUG 0
/* vmsfunctions.c */
#include <stdio.h>
#include "make.h"
#ifdef __DECC
#include <starlet.h>
#endif
#include <descrip.h>
#include <rms.h>
#include <iodef.h>
#include <atrdef.h>
#include <fibdef.h>
#include "vmsdir.h"
DIR *opendir(char *dspec)
{
static struct FAB *dfab;
struct NAM *dnam;
char *searchspec;
if ((dfab = (struct FAB *)xmalloc(sizeof (struct FAB))) == NULL) {
printf("Error mallocing for FAB\n");
return(NULL);
}
if ((dnam = (struct NAM *)xmalloc(sizeof (struct NAM))) == NULL) {
printf("Error mallocing for NAM\n");
free(dfab);
return(NULL);
}
if ((searchspec = (char *)xmalloc(MAXNAMLEN+1)) == NULL) {
printf("Error mallocing for searchspec\n");
free(dfab);
free(dnam);
return(NULL);
}
sprintf(searchspec,"%s*.*;",dspec);
*dfab = cc$rms_fab;
dfab->fab$l_fna = searchspec;
dfab->fab$b_fns = strlen(searchspec);
dfab->fab$l_nam = dnam;
*dnam = cc$rms_nam;
dnam->nam$l_esa = searchspec;
dnam->nam$b_ess = MAXNAMLEN;
if (!(sys$parse(dfab) & 1)) {
free(dfab);
free(dnam);
free(searchspec);
return(NULL);
}
return(dfab);
}
#include <ctype.h>
#define uppercasify(str) { char *tmp; for(tmp = (str); *tmp != '\0'; tmp++) if(islower(*tmp)) *tmp = toupper(*tmp); }
struct direct *readdir(DIR *dfd)
{
static struct direct *dentry;
static char resultspec[MAXNAMLEN+1];
int i;
if ((dentry = (struct direct *)xmalloc(sizeof (struct direct))) == NULL) {
printf("Error mallocing for direct\n");
return(NULL);
}
dfd->fab$l_nam->nam$l_rsa = resultspec;
dfd->fab$l_nam->nam$b_rss = MAXNAMLEN;
if (debug_flag)
printf(".");
if (!((i = sys$search(dfd)) & 1)) {
if (debug_flag)
printf("sys$search failed with %d\n", i);
free(dentry);
return(NULL);
}
dentry->d_off = 0;
if (dfd->fab$l_nam->nam$w_fid == 0)
dentry->d_fileno = 1;
else dentry->d_fileno = dfd->fab$l_nam->nam$w_fid[0]
+dfd->fab$l_nam->nam$w_fid[1]<<16;
dentry->d_reclen = sizeof (struct direct);
/*
if (!strcmp(dfd->fab$l_nam->nam$l_type,".DIR"))
dentry->d_namlen = dfd->fab$l_nam->nam$b_name;
else
*/
dentry->d_namlen = dfd->fab$l_nam->nam$b_name+dfd->fab$l_nam->nam$b_type;
strncpy(dentry->d_name,dfd->fab$l_nam->nam$l_name,dentry->d_namlen);
dentry->d_name[dentry->d_namlen] = '\0';
uppercasify(dentry->d_name);
/* uvUnFixRCSSeparator(dentry->d_name);*/
return(dentry);
}
closedir(DIR *dfd)
{
if (dfd != NULL) {
if (dfd->fab$l_nam != NULL)
free(dfd->fab$l_nam->nam$l_esa);
free(dfd->fab$l_nam);
free(dfd);
}
}
char *getwd(char *cwd)
{
static char buf[512];
if (cwd)
return(getcwd(cwd,512));
else
return(getcwd(buf,512));
}
int
vms_stat (name, buf)
char *name;
struct stat *buf;
{
int status;
int i;
static struct FAB Fab;
static struct NAM Nam;
static struct fibdef Fib; /* short fib */
static struct dsc$descriptor FibDesc =
{sizeof(Fib), DSC$K_DTYPE_Z, DSC$K_CLASS_S, (char *)&Fib};
static struct dsc$descriptor_s DevDesc =
{0, DSC$K_DTYPE_T, DSC$K_CLASS_S, &Nam.nam$t_dvi[1]};
static char EName[NAM$C_MAXRSS];
static char RName[NAM$C_MAXRSS];
static struct dsc$descriptor_s FileName =
{0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0};
static struct dsc$descriptor_s string =
{0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0};
static unsigned long Rdate[2];
static unsigned long Cdate[2];
static struct atrdef Atr[] = {
{sizeof(Rdate),ATR$C_REVDATE,&Rdate[0]}, /* Revision date */
{sizeof(Cdate),ATR$C_CREDATE,&Cdate[0]}, /* Creation date */
{0,0,0}
};
static short int DevChan;
static short int iosb[4];
name = vmsify (name, 0);
/* initialize RMS structures, we need a NAM to retrieve the FID */
Fab = cc$rms_fab;
Fab.fab$l_fna = name ; /* name of file */
Fab.fab$b_fns = strlen(name);
Fab.fab$l_nam = &Nam; /* FAB has an associated NAM */
Nam = cc$rms_nam;
Nam.nam$l_esa = EName; /* expanded filename */
Nam.nam$b_ess = sizeof(EName);
Nam.nam$l_rsa = RName; /* resultant filename */
Nam.nam$b_rss = sizeof(RName);
/* do $PARSE and $SEARCH here */
status = sys$parse(&Fab);
if (!(status & 1))
return -1;
DevDesc.dsc$w_length = Nam.nam$t_dvi[0];
status = sys$assign(&DevDesc,&DevChan,0,0);
if (!(status & 1))
return -1;
FileName.dsc$a_pointer = Nam.nam$l_name;
FileName.dsc$w_length = Nam.nam$b_name+Nam.nam$b_type+Nam.nam$b_ver;
/* Initialize the FIB */
for (i=0;i<3;i++)
{
#if __DECC
Fib.fib$w_fid[i]=Nam.nam$w_fid[i];
Fib.fib$w_did[i]=Nam.nam$w_did[i];
#else
Fib.fib$r_fid_overlay.fib$w_fid[i]=Nam.nam$w_fid[i];
Fib.fib$r_did_overlay.fib$w_did[i]=Nam.nam$w_did[i];
#endif
}
status = sys$qiow(0,DevChan,IO$_ACCESS,&iosb,0,0,
&FibDesc,&FileName,0,0,&Atr,0);
if (!(status & 1))
return -1;
status = iosb[0];
if (!(status & 1))
return -1;
status = stat (name, buf);
if (status)
return -1;
buf->st_mtime = ((Rdate[0]>>24) & 0xff) + ((Rdate[1]<<8) & 0xffffff00);
buf->st_ctime = ((Cdate[0]>>24) & 0xff) + ((Cdate[1]<<8) & 0xffffff00);
return 0;
}
char *
cvt_time(tval)
unsigned long tval;
{
static long int date[2];
static char str[27];
static struct dsc$descriptor date_str =
{26, DSC$K_DTYPE_T, DSC$K_CLASS_S, str};
date[0] = (tval & 0xff) << 24;
date[1] = ((tval>>8) & 0xffffff);
if ((date[0]==0) && (date[1]==0))
return("never");
sys$asctim(0,&date_str,date,0);
str[26]='\0';
return(str);
}
/* EOF */

925
vmsify.c Normal file
View file

@ -0,0 +1,925 @@
/*
vmsify.c
Module for vms <-> unix file name conversion
Written by Klaus Kämpf (kkaempf@didymus.rmi.de)
*/
#include <string.h>
#include <ctype.h>
#if VMS
#include <unixlib.h>
#include <stdlib.h>
#include <jpidef.h>
#include <descrip.h>
#include <uaidef.h>
#include <ssdef.h>
#include <starlet.h>
#include <lib$routines.h>
/* Initialize a string descriptor (struct dsc$descriptor_s) for an
arbitrary string. ADDR is a pointer to the first character
of the string, and LEN is the length of the string. */
#define INIT_DSC_S(dsc, addr, len) do { \
(dsc).dsc$b_dtype = DSC$K_DTYPE_T; \
(dsc).dsc$b_class = DSC$K_CLASS_S; \
(dsc).dsc$w_length = (len); \
(dsc).dsc$a_pointer = (addr); \
} while (0)
/* Initialize a string descriptor (struct dsc$descriptor_s) for a
NUL-terminated string. S is a pointer to the string; the length
is determined by calling strlen(). */
#define INIT_DSC_CSTRING(dsc, s) INIT_DSC_S(dsc, s, strlen(s))
#endif
/*
copy 'from' to 'to' up to but not including 'upto'
return 0 if eos on from
return 1 if upto found
return 'to' at last char + 1
return 'from' at match + 1 or eos if no match
if as_dir == 1, change all '.' to '_'
else change all '.' but the last to '_'
*/
static int
copyto (char **to, char **from, char upto, int as_dir)
{
char *s;
s = strrchr (*from, '.');
while (**from)
{
if (**from == upto)
{
do
{
(*from)++;
}
while (**from == upto);
return 1;
}
if (**from == '.')
{
if ((as_dir == 1)
|| (*from != s))
**to = '_';
else
**to = '.';
}
else
{
if (islower (**from))
**to = toupper (**from);
else
**to = **from;
}
(*to)++;
(*from)++;
}
return 0;
}
/*
get translation of logical name
*/
static char *
trnlog (char *name)
{
int stat;
static char reslt[1024];
$DESCRIPTOR (reslt_dsc, reslt);
short resltlen;
struct dsc$descriptor_s name_dsc;
char *s;
INIT_DSC_CSTRING (name_dsc, name);
stat = lib$sys_trnlog (&name_dsc, &resltlen, &reslt_dsc);
if ((stat&1) == 0)
{
return "";
}
if (stat == SS$_NOTRAN)
{
return "";
}
reslt[resltlen] = '\0';
s = (char *)malloc (resltlen+1);
if (s == 0)
return "";
strcpy (s, reslt);
return s;
}
enum namestate { N_START, N_DEVICE, N_OPEN, N_DOT, N_CLOSED, N_DONE };
/*
convert unix style name to vms style
type = 0 -> name is a full name (directory and filename part)
type = 1 -> name is a directory
type = 2 -> name is a filename without directory
The following conversions are applied
(0) (1) (2)
input full name dir name file name
1 ./ <cwd> [] <current directory>.dir
2 ../ <home of cwd> <home of cwd> <home of cwd>.dir
3 // <dev of cwd>: <dev of cwd>:[000000] <dev of cwd>:000000.dir
4 //a a: a: a:
5 //a/ a: a: a:000000.dir
9 / [000000] [000000] 000000.dir
10 /a [000000]a [a] [000000]a
11 /a/ [a] [a] [000000]a.dir
12 /a/b [a]b [a.b] [a]b
13 /a/b/ [a.b] [a.b] [a]b.dir
14 /a/b/c [a.b]c [a.b.c] [a.b]c
15 /a/b/c/ [a.b.c] [a.b.c] [a.b]c.dir
16 a a [.a] a
17 a/ [.a] [.a] a.dir
18 a/b [.a]b [.a.b] [.a]b
19 a/b/ [.a.b] [.a.b] [.a]b.dir
20 a/b/c [.a.b]c [.a.b.c] [.a.b]c
21 a/b/c/ [.a.b.c] [.a.b.c] [.a.b]c.dir
22 a.b.c a_b.c [.a_b_c] a_b_c.dir
23 [x][y]z [x.y]z [x.y]z [x.y]z
24 [x][.y]z [x.y]z [x.y]z [x.y]z
25 filenames with '$' are left unchanged if they contain no '/'
25 filenames with ':' are left unchanged
26 filenames with a single pair of '[' ']' are left unchanged
the input string is not written to
*/
char *
vmsify (name, type)
char *name;
int type;
{
/* max 255 device
max 39 directory
max 39 filename
max 39 filetype
max 5 version
*/
#define MAXPATHLEN 512
enum namestate nstate;
static char vmsname[MAXPATHLEN+1];
char *fptr;
char *vptr;
char *s,*s1;
int as_dir;
int count;
if (name == 0)
return 0;
fptr = name;
vptr = vmsname;
nstate = N_START;
/* case 25a */
s = strpbrk (name, "$:");
if (s != 0)
{
if (*s == '$')
{
if (strchr (name, '/') == 0)
{
return name;
}
}
else
{
return name;
}
}
/* case 26 */
s = strchr (name, '[');
if (s != 0)
{
s1 = strchr (s+1, '[');
if (s1 == 0)
{
return name; /* single [, keep unchanged */
}
s1--;
if (*s1 != ']')
{
return name; /* not ][, keep unchanged */
}
/* we have ][ */
s = name;
/* s -> starting char
s1 -> ending ']' */
do
{
strncpy (vptr, s, s1-s); /* copy up to but not including ']' */
vptr += s1-s;
if (*s1 == 0)
break;
s = s1 + 1; /* s -> char behind ']' */
if (*s != '[') /* was '][' ? */
break; /* no, last ] found, exit */
s++;
if (*s != '.')
*vptr++ = '.';
s1 = strchr (s, ']');
if (s1 == 0) /* no closing ] */
s1 = s + strlen (s);
}
while (1);
*vptr++ = ']';
fptr = s;
}
else /* no [ in name */
{
int state;
int rooted = 1; /* flag if logical is rooted, else insert [000000] */
state = 0;
do
{
switch (state)
{
case 0: /* start of loop */
if (*fptr == '/')
{
fptr++;
state = 1;
}
else if (*fptr == '.')
{
fptr++;
state = 10;
}
else
state = 2;
break;
case 1: /* '/' at start */
if (*fptr == '/')
{
fptr++;
state = 3;
}
else
state = 4;
break;
case 2: /* no '/' at start */
s = strchr (fptr, '/');
if (s == 0) /* no '/' (16) */
{
if (type == 1)
{
strcpy (vptr, "[.");
vptr += 2;
}
copyto (&vptr, &fptr, 0, (type==1));
if (type == 1)
*vptr++ = ']';
state = -1;
}
else /* found '/' (17..21) */
{
if ((type == 2)
&& (*(s+1) == 0)) /* 17(2) */
{
copyto (&vptr, &fptr, '/', 1);
state = 7;
}
else
{
strcpy (vptr, "[.");
nstate = N_DOT;
vptr += 2;
copyto (&vptr, &fptr, '/', 1);
state = 9;
}
}
break;
case 3: /* '//' at start */
while (*fptr == '/') /* collapse all '/' */
fptr++;
if (*fptr == 0) /* just // */
{
char cwdbuf[MAXPATHLEN+1];
s1 = getcwd(cwdbuf, MAXPATHLEN);
if (s1 == 0)
{
return ""; /* FIXME, err getcwd */
}
s = strchr (s1, ':');
if (s == 0)
{
return ""; /* FIXME, err no device */
}
strncpy (vptr, s1, s-s1+1);
vptr += s-s1+1;
state = -1;
break;
}
s = vptr;
if (copyto (&vptr, &fptr, '/', 1) == 0) /* copy device part */
{
*vptr++ = ':';
state = -1;
break;
}
*vptr = ':';
nstate = N_DEVICE;
if (*fptr == 0) /* just '//a/' */
{
strcpy (vptr+1, "[000000]");
vptr += 9;
state = -1;
break;
}
*vptr = 0;
/* check logical for [000000] insertion */
s1 = trnlog (s);
if (*s1 != 0)
{ /* found translation */
char *s2;
for (;;) /* loop over all nested logicals */
{
s2 = s1 + strlen (s1) - 1;
if (*s2 == ':') /* translation ends in ':' */
{
s2 = trnlog (s1);
free (s1);
if (*s2 == 0)
{
rooted = 0;
break;
}
s1 = s2;
continue; /* next iteration */
}
if (*s2 == ']') /* translation ends in ']' */
{
if (*(s2-1) == '.') /* ends in '.]' */
{
if (strncmp (fptr, "000000", 6) != 0)
rooted = 0;
}
else
{
strcpy (vmsname, s1);
s = strchr (vmsname, ']');
*s = '.';
nstate = N_DOT;
vptr = s;
}
}
break;
}
free (s1);
}
else
rooted = 0;
if (*vptr == 0)
{
nstate = N_DEVICE;
*vptr++ = ':';
}
else
vptr++;
if (rooted == 0)
{
strcpy (vptr, "[000000.");
vptr += 8;
s1 = vptr-1;
nstate = N_DOT;
}
else
s1 = 0;
/* s1-> '.' after 000000 or NULL */
s = strchr (fptr, '/');
if (s == 0)
{ /* no next '/' */
if (*(vptr-1) == '.')
*(vptr-1) = ']';
else if (rooted == 0)
*vptr++ = ']';
copyto (&vptr, &fptr, 0, (type == 1));
state = -1;
break;
}
else
{
while (*(s+1) == '/') /* skip multiple '/' */
s++;
}
if ((rooted != 0)
&& (*(vptr-1) != '.'))
{
*vptr++ = '[';
nstate = N_DOT;
}
else
if ((nstate == N_DOT)
&& (s1 != 0)
&& (*(s+1) == 0))
{
if (type == 2)
{
*s1 = ']';
nstate = N_CLOSED;
}
}
state = 9;
break;
case 4: /* single '/' at start (9..15) */
if (*fptr == 0)
state = 5;
else
state = 6;
break;
case 5: /* just '/' at start (9) */
if (type != 2)
{
*vptr++ = '[';
nstate = N_OPEN;
}
strcpy (vptr, "000000");
vptr += 6;
if (type == 2)
state = 7;
else
state = 8;
break;
case 6: /* chars following '/' at start 10..15 */
*vptr++ = '[';
nstate = N_OPEN;
s = strchr (fptr, '/');
if (s == 0) /* 10 */
{
if (type != 1)
{
strcpy (vptr, "000000]");
vptr += 7;
}
copyto (&vptr, &fptr, 0, (type == 1));
if (type == 1)
{
*vptr++ = ']';
}
state = -1;
}
else /* 11..15 */
{
if ( (type == 2)
&& (*(s+1) == 0)) /* 11(2) */
{
strcpy (vptr, "000000]");
nstate = N_CLOSED;
vptr += 7;
}
copyto (&vptr, &fptr, '/', (*(vptr-1) != ']'));
state = 9;
}
break;
case 7: /* add '.dir' and exit */
if ((nstate == N_OPEN)
|| (nstate == N_DOT))
{
s = vptr-1;
while (s > vmsname)
{
if (*s == ']')
{
break;
}
if (*s == '.')
{
*s = ']';
break;
}
s--;
}
}
strcpy (vptr, ".dir");
vptr += 4;
state = -1;
break;
case 8: /* add ']' and exit */
*vptr++ = ']';
state = -1;
break;
case 9: /* 17..21, fptr -> 1st '/' + 1 */
if (*fptr == 0)
{
if (type == 2)
{
state = 7;
}
else
state = 8;
break;
}
s = strchr (fptr, '/');
if (s == 0)
{
if (type != 1)
{
if (nstate == N_OPEN)
{
*vptr++ = ']';
nstate = N_CLOSED;
}
as_dir = 0;
}
else
{
if (nstate == N_OPEN)
{
*vptr++ = '.';
nstate = N_DOT;
}
as_dir = 1;
}
}
else
{
while (*(s+1) == '/')
s++;
if ( (type == 2)
&& (*(s+1) == 0)) /* 19(2), 21(2)*/
{
if (nstate != N_CLOSED)
{
*vptr++ = ']';
nstate = N_CLOSED;
}
as_dir = 1;
}
else
{
if (nstate == N_OPEN)
{
*vptr++ = '.';
nstate = N_DOT;
}
as_dir = 1;
}
}
if ( (*fptr == '.') /* check for '..' or '../' */
&& (*(fptr+1) == '.')
&& ((*(fptr+2) == '/')
|| (*(fptr+2) == 0)) )
{
fptr += 2;
if (*fptr == '/')
{
do
{
fptr++;
}
while (*fptr == '/');
}
else if (*fptr == 0)
type = 1;
vptr--; /* vptr -> '.' or ']' */
s1 = vptr;
for (;;)
{
s1--;
if (*s1 == '.') /* one back */
{
vptr = s1;
nstate = N_OPEN;
break;
}
if (*s1 == '[') /* top level reached */
{
if (*fptr == 0)
{
strcpy (s1, "[000000]");
vptr = s1 + 8;
nstate = N_CLOSED;
s = 0;
break;
}
else
{
vptr = s1+1;
nstate = N_OPEN;
break;
}
}
}
}
else
{
copyto (&vptr, &fptr, '/', as_dir);
if (nstate == N_DOT)
nstate = N_OPEN;
}
if (s == 0)
{ /* 18,20 */
if (type == 1)
*vptr++ = ']';
state = -1;
}
else
{
if (*(s+1) == 0)
{
if (type == 2) /* 19,21 */
{
state = 7;
}
else
{
*vptr++ = ']';
state = -1;
}
}
}
break;
case 10: /* 1,2 first is '.' */
if (*fptr == '.')
{
fptr++;
state = 11;
}
else
state = 12;
break;
case 11: /* 2, '..' at start */
count = 1;
if (*fptr != 0)
{
if (*fptr != '/') /* got ..xxx */
{
return name;
}
do /* got ../ */
{
fptr++;
while (*fptr == '/') fptr++;
if (*fptr != '.')
break;
if (*(fptr+1) != '.')
break;
fptr += 2;
if ((*fptr == 0)
|| (*fptr == '/'))
count++;
}
while (*fptr == '/');
}
{ /* got '..' or '../' */
char cwdbuf[MAXPATHLEN+1];
s1 = getcwd(cwdbuf, MAXPATHLEN);
if (s1 == 0)
{
return ""; /* FIXME, err getcwd */
}
strcpy (vptr, s1);
s = strchr (vptr, ']');
if (s != 0)
{
while (s > vptr)
{
s--;
if (*s == '[')
{
s++;
strcpy (s, "000000]");
state = -1;
break;
}
else if (*s == '.')
{
if (--count == 0)
{
if (*fptr == 0) /* had '..' or '../' */
{
*s++ = ']';
state = -1;
}
else /* had '../xxx' */
{
state = 9;
}
*s = 0;
break;
}
}
}
}
vptr += strlen (vptr);
}
break;
case 12: /* 1, '.' at start */
if (*fptr != 0)
{
if (*fptr != '/')
{
return name;
}
fptr++;
}
{
char cwdbuf[MAXPATHLEN+1];
s1 = getcwd(cwdbuf, MAXPATHLEN);
if (s1 == 0)
{
return ""; /*FIXME, err getcwd */
}
strcpy (vptr, s1);
if (*fptr == 0)
{
state = -1;
break;
}
else
{
s = strchr (vptr, ']');
if (s == 0)
{
state = -1;
break;
}
*s = 0;
nstate = N_OPEN;
vptr += strlen (vptr);
state = 9;
}
}
break;
}
}
while (state > 0);
}
/* directory conversion done
fptr -> filename part of input string
vptr -> free space in vmsname
*/
*vptr++ = 0;
return vmsname;
}
/*
convert from vms-style to unix-style
dev:[dir1.dir2] //dev/dir1/dir2/
*/
char *
unixify (char *name)
{
static char piece[512];
char *s, *p;
if (strchr (name, '/') != 0) /* already in unix style */
return name;
p = piece;
*p = 0;
/* device part */
s = strchr (name, ':');
if (s != 0)
{
*s = 0;
*p++ = '/';
*p++ = '/';
strcpy (p, name);
p += strlen (p);
*s = ':';
}
/* directory part */
*p++ = '/';
s = strchr (name, '[');
if (s != 0)
{
s++;
switch (*s)
{
case ']': /* [] */
strcat (p, "./");
break;
case '-': /* [- */
strcat (p, "../");
break;
case '.':
strcat (p, "./"); /* [. */
break;
default:
s--;
break;
}
s++;
while (*s)
{
if (*s == '.')
*p++ = '/';
else
*p++ = *s;
s++;
if (*s == ']')
{
s++;
break;
}
}
if (*s != 0) /* more after ']' ?? */
{
if (*(p-1) != '/')
*p++ = '/';
strcpy (p, s); /* copy it anyway */
}
}
else /* no '[' anywhere */
{
*p++ = 0;
}
/* force end with '/' */
if (*(p-1) != '/')
*p++ = '/';
*p = 0;
return piece;
}
/* EOF */

View file

@ -17,7 +17,7 @@ along with GNU Make; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "make.h"
#include "file.h"
#include "filedef.h"
#include "variable.h"
@ -41,7 +41,7 @@ static struct vpath *vpaths;
static struct vpath *general_vpath;
static int selective_vpath_search ();
static int selective_vpath_search PARAMS ((struct vpath *path, char **file, time_t *mtime_ptr));
/* Reverse the chain of selective VPATH lists so they
will be searched in the order given in the makefiles