Merge in NetBSD's changes to make(1). Changes include:

- Add the .PHONY, .PARALLEL, and .WAIT directives
	- Added the -B and -m commandline flags
	- misc. man page cleanups
	- numerous job-related enhancements
	- removed unused header file (bit.h)
	- add util.c for functions not found in other envs.
	- and a few coordinated whitespace changes

Special thanks to Christos Zoulas <christos@netbsd.org>
for help in the merge.  A 'diff -ur' between Net and
FreeBSD now only contains sccsid-related diffs. :)

Obtained from: NetBSD, christos@netbsd.org, and me
This commit is contained in:
Steve Price 1996-10-06 02:35:38 +00:00
parent 81beb58a1a
commit c0d06fe463
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=18730
31 changed files with 2233 additions and 1045 deletions

View File

@ -1,10 +1,10 @@
# from: @(#)Makefile 5.2 (Berkeley) 12/28/90
# $Id: Makefile,v 1.4 1995/06/16 22:46:38 ache Exp $
# @(#)Makefile 5.2 (Berkeley) 12/28/90
# $Id: Makefile,v 1.5 1995/09/22 14:14:28 phk Exp $
PROG= make
CFLAGS+= -I${.CURDIR} -DPOSIX -DSYSVINCLUDE
CFLAGS+= -I${.CURDIR}
SRCS= arch.c buf.c compat.c cond.c dir.c for.c hash.c job.c main.c \
make.c parse.c str.c suff.c targ.c var.c
make.c parse.c str.c suff.c targ.c var.c util.c
SRCS+= lstAppend.c lstAtEnd.c lstAtFront.c lstClose.c lstConcat.c \
lstDatum.c lstDeQueue.c lstDestroy.c lstDupl.c lstEnQueue.c \
lstFind.c lstFindFrom.c lstFirst.c lstForEach.c lstForEachFrom.c \
@ -12,4 +12,8 @@ SRCS+= lstAppend.c lstAtEnd.c lstAtFront.c lstClose.c lstConcat.c \
lstMember.c lstNext.c lstOpen.c lstRemove.c lstReplace.c lstSucc.c
.PATH: ${.CURDIR}/lst.lib
.if make(install)
SUBDIR+= PSD.doc
.endif
.include <bsd.prog.mk>

View File

@ -43,7 +43,7 @@
.\" is numeric, it is taken as the depth for numbering (as for .NH), else
.\" the default (1) is assumed.
.\"
.\" $Id: tutorial.ms,v 1.4 89/01/08 20:20:22 adam Exp Locker: adam $
.\" $Id: tutorial.ms,v 1.1.1.1 1994/05/27 12:32:16 rgrimes Exp $
.\"
.\" @P The initial paragraph distance.
.\" @Q The piece of section number to increment (or 0 if none given)
@ -1272,6 +1272,15 @@ administrator. If locking is on,
will turn it off, and vice versa. Note that this locking will not
prevent \fIyou\fP from invoking PMake twice in the same place \*- if
you own the lock file, PMake will warn you about it but continue to execute.
.IP "\fB\-m\fP \fIdirectory\fP"
.Ix 0 def flags -m
Tells PMake another place to search for included makefiles via the <...>
style. Several
.B \-m
options can be given to form a search path. If this construct is used the
default system makefile search path is completely overridden.
To be explained in chapter 3, section 3.2.
.Rm 2 3.2
.IP \fB\-n\fP
.Ix 0 def flags -n
This flag tells PMake not to execute the commands needed to update the
@ -1912,11 +1921,15 @@ or this
.DE
The difference between the two is where PMake searches for the file:
the first way, PMake will look for
the file only in the system makefile directory (to find out what that
directory is, give PMake the
the file only in the system makefile directory (or directories)
(to find out what that directory is, give PMake the
.B \-h
flag).
.Ix 0 ref flags -h
The system makefile directory search path can be overridden via the
.B \-m
option.
.Ix 0 ref flags -m
For files in double-quotes, the search is more complex:
.RS
.IP 1)

View File

@ -94,7 +94,7 @@ static char sccsid[] = "@(#)arch.c 8.2 (Berkeley) 1/2/94";
#include <sys/param.h>
#include <ctype.h>
#include <ar.h>
#include <ranlib.h>
#include <utime.h>
#include <stdio.h>
#include <stdlib.h>
#include "make.h"
@ -108,12 +108,18 @@ typedef struct Arch {
char *name; /* Name of archive */
Hash_Table members; /* All the members of the archive described
* by <name, struct ar_hdr *> key/value pairs */
char *fnametab; /* Extended name table strings */
size_t fnamesize; /* Size of the string table */
} Arch;
static int ArchFindArchive __P((ClientData, ClientData));
static void ArchFree __P((ClientData));
static struct ar_hdr *ArchStatMember __P((char *, char *, Boolean));
static FILE *ArchFindMember __P((char *, char *, struct ar_hdr *, char *));
#if defined(__svr4__) || defined(__SVR4)
#define SVR4ARCHIVES
static int ArchSVR4Entry __P((Arch *, char *, size_t, FILE *));
#endif
/*-
*-----------------------------------------------------------------------
@ -143,6 +149,8 @@ ArchFree(ap)
free((Address) Hash_GetValue (entry));
free(a->name);
if (a->fnametab)
free(a->fnametab);
Hash_DeleteTable(&a->members);
free((Address) a);
}
@ -486,7 +494,7 @@ ArchStatMember (archive, member, hash)
strncpy(copy, member, AR_MAX_NAME_LEN);
copy[AR_MAX_NAME_LEN] = '\0';
}
if ( (he = Hash_FindEntry (&ar->members, copy)) )
if ((he = Hash_FindEntry (&ar->members, copy)) != NULL)
return ((struct ar_hdr *) Hash_GetValue (he));
return ((struct ar_hdr *) NULL);
}
@ -532,27 +540,58 @@ ArchStatMember (archive, member, hash)
}
ar = (Arch *)emalloc (sizeof (Arch));
ar->name = strdup (archive);
ar->name = estrdup (archive);
ar->fnametab = NULL;
ar->fnamesize = 0;
Hash_InitTable (&ar->members, -1);
memName[AR_MAX_NAME_LEN] = '\0';
while (fread ((char *)&arh, sizeof (struct ar_hdr), 1, arch) == 1) {
if (strncmp ( arh.ar_fmag, ARFMAG, sizeof (arh.ar_fmag)) != 0) {
/*
* The header is bogus, so the archive is bad
* and there's no way we can recover...
*/
fclose (arch);
Hash_DeleteTable (&ar->members);
free ((Address)ar);
return ((struct ar_hdr *) NULL);
/*
* The header is bogus, so the archive is bad
* and there's no way we can recover...
*/
goto badarch;
} else {
/*
* We need to advance the stream's pointer to the start of the
* next header. Files are padded with newlines to an even-byte
* boundary, so we need to extract the size of the file from the
* 'size' field of the header and round it up during the seek.
*/
arh.ar_size[sizeof(arh.ar_size)-1] = '\0';
size = (int) strtol(arh.ar_size, NULL, 10);
(void) strncpy (memName, arh.ar_name, sizeof(arh.ar_name));
for (cp = &memName[AR_MAX_NAME_LEN]; *cp == ' '; cp--) {
continue;
}
cp[1] = '\0';
#ifdef SVR4ARCHIVES
/*
* svr4 names are slash terminated. Also svr4 extended AR format.
*/
if (memName[0] == '/') {
/*
* svr4 magic mode; handle it
*/
switch (ArchSVR4Entry(ar, memName, size, arch)) {
case -1: /* Invalid data */
goto badarch;
case 0: /* List of files entry */
continue;
default: /* Got the entry */
break;
}
}
else {
if (cp[0] == '/')
cp[0] = '\0';
}
#endif
#ifdef AR_EFMT1
/*
* BSD 4.4 extended AR format: #1/<namelen>, with name as the
@ -563,18 +602,10 @@ ArchStatMember (archive, member, hash)
unsigned int elen = atoi(&memName[sizeof(AR_EFMT1)-1]);
if (elen > MAXPATHLEN) {
fclose (arch);
Hash_DeleteTable (&ar->members);
free ((Address)ar);
return ((struct ar_hdr *) NULL);
}
if (fread (memName, elen, 1, arch) != 1) {
fclose (arch);
Hash_DeleteTable (&ar->members);
free ((Address)ar);
return ((struct ar_hdr *) NULL);
}
if (elen > MAXPATHLEN)
goto badarch;
if (fread (memName, elen, 1, arch) != 1)
goto badarch;
memName[elen] = '\0';
fseek (arch, -elen, 1);
if (DEBUG(ARCH) || DEBUG(MAKE)) {
@ -588,14 +619,6 @@ ArchStatMember (archive, member, hash)
memcpy ((Address)Hash_GetValue (he), (Address)&arh,
sizeof (struct ar_hdr));
}
/*
* We need to advance the stream's pointer to the start of the
* next header. Files are padded with newlines to an even-byte
* boundary, so we need to extract the size of the file from the
* 'size' field of the header and round it up during the seek.
*/
arh.ar_size[sizeof(arh.ar_size)-1] = '\0';
size = (int) strtol(arh.ar_size, NULL, 10);
fseek (arch, (size + 1) & ~1, 1);
}
@ -614,8 +637,121 @@ ArchStatMember (archive, member, hash)
} else {
return ((struct ar_hdr *) NULL);
}
badarch:
fclose (arch);
Hash_DeleteTable (&ar->members);
if (ar->fnametab)
free(ar->fnametab);
free ((Address)ar);
return ((struct ar_hdr *) NULL);
}
#ifdef SVR4ARCHIVES
/*-
*-----------------------------------------------------------------------
* ArchSVR4Entry --
* Parse an SVR4 style entry that begins with a slash.
* If it is "//", then load the table of filenames
* If it is "/<offset>", then try to substitute the long file name
* from offset of a table previously read.
*
* Results:
* -1: Bad data in archive
* 0: A table was loaded from the file
* 1: Name was successfully substituted from table
* 2: Name was not successfully substituted from table
*
* Side Effects:
* If a table is read, the file pointer is moved to the next archive
* member
*
*-----------------------------------------------------------------------
*/
static int
ArchSVR4Entry(ar, name, size, arch)
Arch *ar;
char *name;
size_t size;
FILE *arch;
{
#define ARLONGNAMES1 "//"
#define ARLONGNAMES2 "/ARFILENAMES"
size_t entry;
char *ptr, *eptr;
if (strncmp(name, ARLONGNAMES1, sizeof(ARLONGNAMES1) - 1) == 0 ||
strncmp(name, ARLONGNAMES2, sizeof(ARLONGNAMES2) - 1) == 0) {
if (ar->fnametab != NULL) {
if (DEBUG(ARCH)) {
printf("Attempted to redefine an SVR4 name table\n");
}
return -1;
}
/*
* This is a table of archive names, so we build one for
* ourselves
*/
ar->fnametab = emalloc(size);
ar->fnamesize = size;
if (fread(ar->fnametab, size, 1, arch) != 1) {
if (DEBUG(ARCH)) {
printf("Reading an SVR4 name table failed\n");
}
return -1;
}
eptr = ar->fnametab + size;
for (entry = 0, ptr = ar->fnametab; ptr < eptr; ptr++)
switch (*ptr) {
case '/':
entry++;
*ptr = '\0';
break;
case '\n':
break;
default:
break;
}
if (DEBUG(ARCH)) {
printf("Found svr4 archive name table with %d entries\n", entry);
}
return 0;
}
if (name[1] == ' ' || name[1] == '\0')
return 2;
entry = (size_t) strtol(&name[1], &eptr, 0);
if ((*eptr != ' ' && *eptr != '\0') || eptr == &name[1]) {
if (DEBUG(ARCH)) {
printf("Could not parse SVR4 name %s\n", name);
}
return 2;
}
if (entry >= ar->fnamesize) {
if (DEBUG(ARCH)) {
printf("SVR4 entry offset %s is greater than %d\n",
name, ar->fnamesize);
}
return 2;
}
if (DEBUG(ARCH)) {
printf("Replaced %s with %s\n", name, &ar->fnametab[entry]);
}
(void) strncpy(name, &ar->fnametab[entry], MAXPATHLEN);
name[MAXPATHLEN] = '\0';
return 1;
}
#endif
/*-
*-----------------------------------------------------------------------
* ArchFindMember --
@ -820,9 +956,10 @@ void
Arch_TouchLib (gn)
GNode *gn; /* The node of the library to touch */
{
#ifdef RANLIBMAG
FILE * arch; /* Stream open to archive */
struct ar_hdr arh; /* Header describing table of contents */
struct timeval times[2]; /* Times for utimes() call */
struct utimbuf times; /* Times for utime() call */
arch = ArchFindMember (gn->path, RANLIBMAG, &arh, "r+");
sprintf(arh.ar_date, "%-12ld", (long) now);
@ -831,10 +968,10 @@ Arch_TouchLib (gn)
(void)fwrite ((char *)&arh, sizeof (struct ar_hdr), 1, arch);
fclose (arch);
times[0].tv_sec = times[1].tv_sec = now;
times[0].tv_usec = times[1].tv_usec = 0;
utimes(gn->path, times);
times.actime = times.modtime = now;
utime(gn->path, &times);
}
#endif
}
/*-
@ -975,7 +1112,7 @@ Arch_FindLib (gn, path)
Var_Set (TARGET, gn->name, gn);
#else
Var_Set (TARGET, gn->path == (char *) NULL ? gn->name : gn->path, gn);
#endif LIBRARIES
#endif /* LIBRARIES */
}
/*-
@ -1025,6 +1162,7 @@ Arch_LibOODate (gn)
} else if ((gn->mtime > now) || (gn->mtime < gn->cmtime)) {
oodate = TRUE;
} else {
#ifdef RANLIBMAG
struct ar_hdr *arhPtr; /* Header for __.SYMDEF */
int modTimeTOC; /* The table-of-contents's mod time */
@ -1046,6 +1184,9 @@ Arch_LibOODate (gn)
}
oodate = TRUE;
}
#else
oodate = FALSE;
#endif
}
return (oodate);
}

View File

@ -1,100 +0,0 @@
/*
* Copyright (c) 1988, 1989, 1990, 1993
* The Regents of the University of California. All rights reserved.
* Copyright (c) 1989 by Berkeley Softworks
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Adam de Boor.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)bit.h 8.1 (Berkeley) 6/6/93
*/
/*
* bit.h --
*
* Definition of macros for setting and clearing bits in an array
* of integers.
*
* It is assumed that "int" is 32 bits wide.
*/
#ifndef _BIT
#define _BIT
#include "sprite.h"
#define BIT_NUM_BITS_PER_INT 32
#define BIT_NUM_BITS_PER_BYTE 8
#define Bit_NumInts(numBits) \
(((numBits)+BIT_NUM_BITS_PER_INT -1)/BIT_NUM_BITS_PER_INT)
#define Bit_NumBytes(numBits) \
(Bit_NumInts(numBits) * sizeof(int))
#define Bit_Alloc(numBits, bitArrayPtr) \
bitArrayPtr = (int *)malloc((unsigned)Bit_NumBytes(numBits)); \
Bit_Zero((numBits), (bitArrayPtr))
#define Bit_Free(bitArrayPtr) \
free((char *)bitArrayPtr)
#define Bit_Set(numBits, bitArrayPtr) \
((bitArrayPtr)[(numBits)/BIT_NUM_BITS_PER_INT] |= \
(1 << ((numBits) % BIT_NUM_BITS_PER_INT)))
#define Bit_IsSet(numBits, bitArrayPtr) \
((bitArrayPtr)[(numBits)/BIT_NUM_BITS_PER_INT] & \
(1 << ((numBits) % BIT_NUM_BITS_PER_INT)))
#define Bit_Clear(numBits, bitArrayPtr) \
((bitArrayPtr)[(numBits)/BIT_NUM_BITS_PER_INT] &= \
~(1 << ((numBits) % BIT_NUM_BITS_PER_INT)))
#define Bit_IsClear(numBits, bitArrayPtr) \
(!(Bit_IsSet((numBits), (bitArrayPtr))))
#define Bit_Copy(numBits, srcArrayPtr, destArrayPtr) \
bcopy((char *)(srcArrayPtr), (char *)(destArrayPtr), \
Bit_NumBytes(numBits))
#define Bit_Zero(numBits, bitArrayPtr) \
bzero((char *)(bitArrayPtr), Bit_NumBytes(numBits))
extern int Bit_FindFirstSet();
extern int Bit_FindFirstClear();
extern Boolean Bit_Intersect();
extern Boolean Bit_Union();
extern Boolean Bit_AnySet();
extern int *Bit_Expand();
#endif /* _BIT */

View File

@ -63,7 +63,7 @@ static char sccsid[] = "@(#)buf.c 8.1 (Berkeley) 6/6/93";
#define BufExpand(bp,nb) \
if (bp->left < (nb)+1) {\
int newSize = (bp)->size + max((nb)+1,BUF_ADD_INC); \
Byte *newBuf = (Byte *) realloc((bp)->buffer, newSize); \
Byte *newBuf = (Byte *) erealloc((bp)->buffer, newSize); \
\
(bp)->inPtr = newBuf + ((bp)->inPtr - (bp)->buffer); \
(bp)->outPtr = newBuf + ((bp)->outPtr - (bp)->buffer);\

View File

@ -35,7 +35,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)buf.h 8.1 (Berkeley) 6/6/93
* from: @(#)buf.h 8.1 (Berkeley) 6/6/93
*/
/*-

View File

@ -55,11 +55,11 @@ static char sccsid[] = "@(#)compat.c 8.2 (Berkeley) 3/19/94";
#include <stdio.h>
#include <sys/types.h>
#include <sys/signal.h>
#include <sys/wait.h>
#include <sys/errno.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <ctype.h>
#include <errno.h>
#include <signal.h>
#include "make.h"
#include "hash.h"
#include "dir.h"
@ -105,10 +105,8 @@ CompatInterrupt (signo)
if ((curTarg != NILGNODE) && !Targ_Precious (curTarg)) {
char *p1;
char *file = Var_Value (TARGET, curTarg, &p1);
struct stat st;
if (!noExecute && lstat(file, &st) != -1 && !S_ISDIR(st.st_mode) &&
unlink(file) != -1) {
if (!noExecute && eunlink(file) != -1) {
printf ("*** %s removed\n", file);
}
if (p1)
@ -151,7 +149,7 @@ CompatRunCommand (cmdp, gnp)
register char *cp;
Boolean silent, /* Don't print command */
errCheck; /* Check errors */
union wait reason; /* Reason for child's death */
int reason; /* Reason for child's death */
int status; /* Description of child's death */
int cpid; /* Child actually found */
ReturnStatus stat; /* Status of fork */
@ -292,7 +290,7 @@ CompatRunCommand (cmdp, gnp)
*/
while (1) {
while ((stat = wait((int *)&reason)) != cpid) {
while ((stat = wait(&reason)) != cpid) {
if (stat == -1 && errno != EINTR) {
break;
}
@ -300,14 +298,14 @@ CompatRunCommand (cmdp, gnp)
if (stat > -1) {
if (WIFSTOPPED(reason)) {
status = reason.w_stopval; /* stopped */
status = WSTOPSIG(reason); /* stopped */
} else if (WIFEXITED(reason)) {
status = reason.w_retcode; /* exited */
status = WEXITSTATUS(reason); /* exited */
if (status != 0) {
printf ("*** Error code %d", status);
}
} else {
status = reason.w_termsig; /* signaled */
status = WTERMSIG(reason); /* signaled */
printf ("*** Signal %d", status);
}

View File

@ -94,6 +94,7 @@ typedef enum {
* Structures to handle elegantly the different forms of #if's. The
* last two fields are stored in condInvert and condDefProc, respectively.
*/
static void CondPushBack __P((Token));
static int CondGetArg __P((char **, char **, char *, Boolean));
static Boolean CondDoDefined __P((int, char *));
static int CondStrMatch __P((ClientData, ClientData));
@ -110,18 +111,19 @@ static struct If {
char *form; /* Form of if */
int formlen; /* Length of form */
Boolean doNot; /* TRUE if default function should be negated */
Boolean (*defProc)(); /* Default function to apply */
Boolean (*defProc) __P((int, char *)); /* Default function to apply */
} ifs[] = {
{ "ifdef", 5, FALSE, CondDoDefined },
{ "ifndef", 6, TRUE, CondDoDefined },
{ "ifmake", 6, FALSE, CondDoMake },
{ "ifnmake", 7, TRUE, CondDoMake },
{ "if", 2, FALSE, CondDoDefined },
{ (char *)0, 0, FALSE, (Boolean (*)())0 }
{ NULL, 0, FALSE, NULL }
};
static Boolean condInvert; /* Invert the default function */
static Boolean (*condDefProc)(); /* Default function to apply */
static Boolean (*condDefProc) /* Default function to apply */
__P((int, char *));
static char *condExpr; /* The expression to parse */
static Token condPushBack=None; /* Single push-back token used in
* parsing */
@ -758,7 +760,7 @@ error:
break;
}
default: {
Boolean (*evalProc)();
Boolean (*evalProc) __P((int, char *));
Boolean invert = FALSE;
char *arg;
int arglen;

View File

@ -35,7 +35,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)config.h 8.1 (Berkeley) 6/6/93
* from: @(#)config.h 8.1 (Berkeley) 6/6/93
*/
#define DEFSHELL 1 /* Bourne shell */
@ -78,15 +78,40 @@
* re-made, causing later targets to appear up-to-date. On systems
* that don't have this problem, you should defined this. Under
* NFS you probably should not, unless you aren't exporting jobs.
*
* POSIX
* If the POSIX standard for Make is to be followed. There are
* several areas that I dislike, hence this constant.
*/
#define LIBSUFF ".a"
#define RECHECK
#ifndef RANLIBMAG
#define RANLIBMAG "__.SYMDEF"
/*
* POSIX
* Adhere to the POSIX 1003.2 draft for the make(1) program.
* - Use MAKEFLAGS instead of MAKE to pick arguments from the
* environment.
* - Allow empty command lines if starting with tab.
*/
#define POSIX
/*
* SYSVINCLUDE
* Recognize system V like include directives [include "filename"]
* SYSVVARSUB
* Recognize system V like ${VAR:x=y} variable substitutions
*/
#define SYSVINCLUDE
#define SYSVVARSUB
/*
* SUNSHCMD
* Recognize SunOS and Solaris:
* VAR :sh= CMD # Assign VAR to the command substitution of CMD
* ${VAR:sh} # Return the command substitution of the value
* # of ${VAR}
*/
#define SUNSHCMD
#if !defined(__svr4__) && !defined(__SVR4)
# ifndef RANLIBMAG
# define RANLIBMAG "__.SYMDEF"
# endif
#endif
/*#define POSIX*/

View File

@ -348,7 +348,7 @@ DirMatchFiles (pattern, p, expansions)
(pattern[0] == '.')))
{
(void)Lst_AtEnd(expansions,
(isDot ? strdup(entry->name) :
(isDot ? estrdup(entry->name) :
str_concat(p->name, entry->name,
STR_ADDSLASH)));
}
@ -700,7 +700,7 @@ Dir_FindFile (name, path)
}
hits += 1;
dot->hits += 1;
return (strdup (name));
return (estrdup (name));
}
if (Lst_Open (path) == FAILURE) {
@ -811,7 +811,7 @@ Dir_FindFile (name, path)
/*
* Checking in dot -- DON'T put a leading ./ on the thing.
*/
file = strdup(name);
file = estrdup(name);
checkedDot = TRUE;
}
if (DEBUG(DIR)) {
@ -907,7 +907,7 @@ Dir_FindFile (name, path)
}
if (Hash_FindEntry (&p->files, cp) != (Hash_Entry *)NULL) {
return (strdup (name));
return (estrdup (name));
} else {
return ((char *) NULL);
}
@ -922,7 +922,7 @@ Dir_FindFile (name, path)
if (DEBUG(DIR)) {
printf("got it (in mtime cache)\n");
}
return(strdup(name));
return(estrdup(name));
} else if (stat (name, &stb) == 0) {
entry = Hash_CreateEntry(&mtimes, name, (Boolean *)NULL);
if (DEBUG(DIR)) {
@ -930,7 +930,7 @@ Dir_FindFile (name, path)
name);
}
Hash_SetValue(entry, (long)stb.st_mtime);
return (strdup (name));
return (estrdup (name));
} else {
if (DEBUG(DIR)) {
printf("failed. Returning NULL\n");
@ -973,7 +973,7 @@ Dir_MTime (gn)
}
if (fullName == (char *)NULL) {
fullName = strdup(gn->name);
fullName = estrdup(gn->name);
}
entry = Hash_FindEntry(&mtimes, fullName);
@ -1047,7 +1047,7 @@ Dir_AddDir (path, name)
if ((d = opendir (name)) != (DIR *) NULL) {
p = (Path *) emalloc (sizeof (Path));
p->name = strdup (name);
p->name = estrdup (name);
p->hits = 0;
p->refCount = 1;
Hash_InitTable (&p->files, -1);
@ -1059,7 +1059,7 @@ Dir_AddDir (path, name)
(void)readdir(d);
while ((dp = readdir (d)) != (struct dirent *) NULL) {
#ifdef sun
#if defined(sun) && defined(d_ino) /* d_ino is a sunos4 #define for d_fileno */
/*
* The sun directory library doesn't check for a 0 inode
* (0-inode slots just take up space), so we have to do
@ -1068,7 +1068,7 @@ Dir_AddDir (path, name)
if (dp->d_fileno == 0) {
continue;
}
#endif /* sun */
#endif /* sun && d_ino */
(void)Hash_CreateEntry(&p->files, dp->d_name, (Boolean *)NULL);
}
(void) closedir (d);
@ -1131,7 +1131,7 @@ Dir_MakeFlags (flag, path)
LstNode ln; /* the node of the current directory */
Path *p; /* the structure describing the current directory */
str = strdup ("");
str = estrdup ("");
if (Lst_Open (path) == SUCCESS) {
while ((ln = Lst_Next (path)) != NILLNODE) {

View File

@ -35,7 +35,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)dir.h 8.1 (Berkeley) 6/6/93
* from: @(#)dir.h 8.1 (Berkeley) 6/6/93
*/
/* dir.h --

View File

@ -35,7 +35,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)hash.h 8.1 (Berkeley) 6/6/93
* from: @(#)hash.h 8.1 (Berkeley) 6/6/93
*/
/* hash.h --

File diff suppressed because it is too large Load Diff

View File

@ -35,7 +35,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)job.h 8.1 (Berkeley) 6/6/93
* from: @(#)job.h 8.1 (Berkeley) 6/6/93
*/
/*-

View File

@ -35,7 +35,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)list.h 8.1 (Berkeley) 6/6/93
* from: @(#)list.h 8.1 (Berkeley) 6/6/93
*/
/*

View File

@ -35,7 +35,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)lst.h 8.1 (Berkeley) 6/6/93
* from: @(#)lst.h 8.1 (Berkeley) 6/6/93
*/
/*-
@ -46,7 +46,7 @@
#define _LST_H_
#include <sprite.h>
#include <sys/cdefs.h>
#include <sys/param.h>
#if __STDC__
#include <stdlib.h>
#endif

View File

@ -66,7 +66,7 @@ void
Lst_ForEachFrom (l, ln, proc, d)
Lst l;
LstNode ln;
register int (*proc)();
register int (*proc) __P((ClientData, ClientData));
register ClientData d;
{
register ListNode tln = (ListNode)ln;
@ -109,3 +109,4 @@ Lst_ForEachFrom (l, ln, proc, d)
} while (!result && !LstIsEmpty(list) && !done);
}

View File

@ -33,7 +33,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)lstInt.h 8.1 (Berkeley) 6/6/93
* from: @(#)lstInt.h 8.1 (Berkeley) 6/6/93
*/
/*-
@ -43,6 +43,7 @@
#ifndef _LSTINT_H_
#define _LSTINT_H_
#include "make.h"
#include "lst.h"
typedef struct ListNode {
@ -87,7 +88,7 @@ typedef struct {
* PAlloc (var, ptype) --
* Allocate a pointer-typedef structure 'ptype' into the variable 'var'
*/
#define PAlloc(var,ptype) var = (ptype) malloc (sizeof (*var))
#define PAlloc(var,ptype) var = (ptype) emalloc (sizeof (*var))
/*
* LstValid (l) --

View File

@ -79,7 +79,10 @@ static char sccsid[] = "@(#)main.c 8.3 (Berkeley) 3/19/94";
#include <sys/resource.h>
#include <sys/signal.h>
#include <sys/stat.h>
#ifndef MACHINE
#include <sys/utsname.h>
#endif
#include <sys/wait.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
@ -96,7 +99,7 @@ static char sccsid[] = "@(#)main.c 8.3 (Berkeley) 3/19/94";
#ifndef DEFMAXLOCAL
#define DEFMAXLOCAL DEFMAXJOBS
#endif DEFMAXLOCAL
#endif /* DEFMAXLOCAL */
#define MAKEFLAGS ".MAKEFLAGS"
@ -109,7 +112,7 @@ static Boolean noBuiltins; /* -r flag */
static Lst makefiles; /* ordered list of makefiles to read */
static Boolean printVars; /* print value of one or more vars */
static Lst variables; /* list of variables to print */
int maxJobs; /* -J argument */
int maxJobs; /* -j argument */
static int maxLocal; /* -L argument */
Boolean compatMake; /* -B argument */
Boolean debug; /* -d flag */
@ -124,8 +127,10 @@ Boolean oldVars; /* variable substitution style */
Boolean checkEnvFirst; /* -e flag */
static Boolean jobsRunning; /* TRUE if the jobs might be running */
static Boolean ReadMakefile();
static void usage();
static void MainParseArgs __P((int, char **));
char * chdir_verify_path __P((char *, char *));
static int ReadMakefile __P((ClientData, ClientData));
static void usage __P((void));
static char *curdir; /* startup directory */
static char *objdir; /* where we chdir'ed to */
@ -152,12 +157,13 @@ MainParseArgs(argc, argv)
extern int optind;
extern char *optarg;
int c;
int forceJobs = 0;
optind = 1; /* since we're called more than once */
#ifdef notyet
# define OPTFLAGS "BD:I:L:PSV:d:ef:ij:knqrst"
#ifdef REMOTE
# define OPTFLAGS "BD:I:L:PSV:d:ef:ij:km:nqrst"
#else
# define OPTFLAGS "D:I:V:d:ef:ij:knqrst"
# define OPTFLAGS "BD:I:PSV:d:ef:ij:km:nqrst"
#endif
rearg: while((c = getopt(argc, argv, OPTFLAGS)) != EOF) {
switch(c) {
@ -177,15 +183,16 @@ rearg: while((c = getopt(argc, argv, OPTFLAGS)) != EOF) {
Var_Append(MAKEFLAGS, "-V", VAR_GLOBAL);
Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
break;
#ifdef notyet
case 'B':
compatMake = TRUE;
break;
#ifdef REMOTE
case 'L':
maxLocal = atoi(optarg);
Var_Append(MAKEFLAGS, "-L", VAR_GLOBAL);
Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
break;
#endif
case 'P':
usePipes = FALSE;
Var_Append(MAKEFLAGS, "-P", VAR_GLOBAL);
@ -194,7 +201,6 @@ rearg: while((c = getopt(argc, argv, OPTFLAGS)) != EOF) {
keepgoing = FALSE;
Var_Append(MAKEFLAGS, "-S", VAR_GLOBAL);
break;
#endif
case 'd': {
char *modules = optarg;
@ -262,7 +268,11 @@ rearg: while((c = getopt(argc, argv, OPTFLAGS)) != EOF) {
Var_Append(MAKEFLAGS, "-i", VAR_GLOBAL);
break;
case 'j':
forceJobs = TRUE;
maxJobs = atoi(optarg);
#ifndef REMOTE
maxLocal = maxJobs;
#endif
Var_Append(MAKEFLAGS, "-j", VAR_GLOBAL);
Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
break;
@ -270,6 +280,11 @@ rearg: while((c = getopt(argc, argv, OPTFLAGS)) != EOF) {
keepgoing = TRUE;
Var_Append(MAKEFLAGS, "-k", VAR_GLOBAL);
break;
case 'm':
Dir_AddDir(sysIncPath, optarg);
Var_Append(MAKEFLAGS, "-m", VAR_GLOBAL);
Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
break;
case 'n':
noExecute = TRUE;
Var_Append(MAKEFLAGS, "-n", VAR_GLOBAL);
@ -297,6 +312,13 @@ rearg: while((c = getopt(argc, argv, OPTFLAGS)) != EOF) {
}
}
/*
* Be compatible if user did not specify -j and did not explicitly
* turned compatibility on
*/
if (!compatMake && !forceJobs)
compatMake = TRUE;
oldVars = TRUE;
/*
@ -317,7 +339,7 @@ rearg: while((c = getopt(argc, argv, OPTFLAGS)) != EOF) {
optind = 1; /* - */
goto rearg;
}
(void)Lst_AtEnd(create, (ClientData)strdup(*argv));
(void)Lst_AtEnd(create, (ClientData)estrdup(*argv));
}
}
@ -407,13 +429,29 @@ main(argc, argv)
Lst targs; /* target nodes to create -- passed to Make_Init */
Boolean outOfDate = TRUE; /* FALSE if all targets up to date */
struct stat sb, sa;
char *p, *p1, *path, *pathp, *pwd, *getenv(), *getwd();
char *p, *p1, *path, *pathp, *pwd;
char mdpath[MAXPATHLEN + 1];
char obpath[MAXPATHLEN + 1];
char cdpath[MAXPATHLEN + 1];
struct utsname utsname;
char *machine = getenv("MACHINE");
Lst sysMkPath; /* Path of sys.mk */
char *cp = NULL, *start;
/* avoid faults on read-only strings */
static char syspath[] = _PATH_DEFSYSPATH;
#ifdef RLIMIT_NOFILE
/*
* get rid of resource limit on file descriptors
*/
{
struct rlimit rl;
if (getrlimit(RLIMIT_NOFILE, &rl) != -1 &&
rl.rlim_cur != rl.rlim_max) {
rl.rlim_cur = rl.rlim_max;
(void) setrlimit(RLIMIT_NOFILE, &rl);
}
}
#endif
/*
* Find where we are and take care of PWD for the automounter...
* All this code is so that we know where we are when we start up
@ -447,6 +485,8 @@ main(argc, argv)
*/
if (!machine) {
#ifndef MACHINE
struct utsname utsname;
if (uname(&utsname) == -1) {
perror("make: uname");
exit(2);
@ -512,13 +552,13 @@ main(argc, argv)
debug = 0; /* No debug verbosity, please. */
jobsRunning = FALSE;
maxJobs = DEFMAXJOBS; /* Set default max concurrency */
maxLocal = DEFMAXLOCAL; /* Set default local max concurrency */
#ifdef notyet
compatMake = FALSE; /* No compat mode */
#ifdef REMOTE
maxJobs = DEFMAXJOBS; /* Set default max concurrency */
#else
compatMake = TRUE; /* No compat mode */
maxJobs = maxLocal;
#endif
compatMake = FALSE; /* No compat mode */
/*
@ -593,13 +633,41 @@ main(argc, argv)
} else
Var_Set(".TARGETS", "", VAR_GLOBAL);
/*
* Read in the built-in rules first, followed by the specified makefile,
* if it was (makefile != (char *) NULL), or the default Makefile and
* makefile, in that order, if it wasn't.
* If no user-supplied system path was given (through the -m option)
* add the directories from the DEFSYSPATH (more than one may be given
* as dir1:...:dirn) to the system include path.
*/
if (!noBuiltins && !ReadMakefile(_PATH_DEFSYSMK))
Fatal("make: no system rules (%s).", _PATH_DEFSYSMK);
if (Lst_IsEmpty(sysIncPath)) {
for (start = syspath; *start != '\0'; start = cp) {
for (cp = start; *cp != '\0' && *cp != ':'; cp++)
continue;
if (*cp == '\0') {
Dir_AddDir(sysIncPath, start);
} else {
*cp++ = '\0';
Dir_AddDir(sysIncPath, start);
}
}
}
/*
* Read in the built-in rules first, followed by the specified
* makefile, if it was (makefile != (char *) NULL), or the default
* Makefile and makefile, in that order, if it wasn't.
*/
if (!noBuiltins) {
LstNode ln;
sysMkPath = Lst_Init (FALSE);
Dir_Expand (_PATH_DEFSYSMK, sysIncPath, sysMkPath);
if (Lst_IsEmpty(sysMkPath))
Fatal("make: no system rules (%s).", _PATH_DEFSYSMK);
ln = Lst_Find(sysMkPath, (ClientData)NULL, ReadMakefile);
if (ln != NILLNODE)
Fatal("make: cannot open %s.", (char *)Lst_Datum(ln));
}
if (!Lst_IsEmpty(makefiles)) {
LstNode ln;
@ -607,10 +675,10 @@ main(argc, argv)
ln = Lst_Find(makefiles, (ClientData)NULL, ReadMakefile);
if (ln != NILLNODE)
Fatal("make: cannot open %s.", (char *)Lst_Datum(ln));
} else if (!ReadMakefile("makefile"))
(void)ReadMakefile("Makefile");
} else if (!ReadMakefile("makefile", NULL))
(void)ReadMakefile("Makefile", NULL);
(void)ReadMakefile(".depend");
(void)ReadMakefile(".depend", NULL);
Var_Append("MFLAGS", Var_Value(MAKEFLAGS, VAR_GLOBAL, &p1), VAR_GLOBAL);
if (p1)
@ -693,10 +761,6 @@ main(argc, argv)
else
targs = Targ_FindList(create, TARG_CREATE);
/*
* this was original amMake -- want to allow parallelism, so put this
* back in, eventually.
*/
if (!compatMake && !printVars) {
/*
* Initialize job module before traversing the graph, now that
@ -755,10 +819,11 @@ main(argc, argv)
* lots
*/
static Boolean
ReadMakefile(fname)
char *fname; /* makefile to read */
ReadMakefile(p, q)
ClientData p, q;
{
extern Lst parseIncPath, sysIncPath;
char *fname = p; /* makefile to read */
extern Lst parseIncPath;
FILE *stream;
char *name, path[MAXPATHLEN + 1];
@ -795,6 +860,142 @@ found: Var_Set("MAKEFILE", fname, VAR_GLOBAL);
return(TRUE);
}
/*-
* Cmd_Exec --
* Execute the command in cmd, and return the output of that command
* in a string.
*
* Results:
* A string containing the output of the command, or the empty string
* If err is not NULL, it contains the reason for the command failure
*
* Side Effects:
* The string must be freed by the caller.
*/
char *
Cmd_Exec(cmd, err)
char *cmd;
char **err;
{
char *args[4]; /* Args for invoking the shell */
int fds[2]; /* Pipe streams */
int cpid; /* Child PID */
int pid; /* PID from wait() */
char *res; /* result */
int status; /* command exit status */
Buffer buf; /* buffer to store the result */
char *cp;
int cc;
*err = NULL;
/*
* Set up arguments for shell
*/
args[0] = "sh";
args[1] = "-c";
args[2] = cmd;
args[3] = NULL;
/*
* Open a pipe for fetching its output
*/
if (pipe(fds) == -1) {
*err = "Couldn't create pipe for \"%s\"";
goto bad;
}
/*
* Fork
*/
switch (cpid = vfork()) {
case 0:
/*
* Close input side of pipe
*/
(void) close(fds[0]);
/*
* Duplicate the output stream to the shell's output, then
* shut the extra thing down. Note we don't fetch the error
* stream...why not? Why?
*/
(void) dup2(fds[1], 1);
(void) close(fds[1]);
(void) execv("/bin/sh", args);
_exit(1);
/*NOTREACHED*/
case -1:
*err = "Couldn't exec \"%s\"";
goto bad;
default:
/*
* No need for the writing half
*/
(void) close(fds[1]);
buf = Buf_Init (MAKE_BSIZE);
do {
char result[BUFSIZ];
cc = read(fds[0], result, sizeof(result));
if (cc > 0)
Buf_AddBytes(buf, cc, (Byte *) result);
}
while (cc > 0 || (cc == -1 && errno == EINTR));
/*
* Close the input side of the pipe.
*/
(void) close(fds[0]);
/*
* Wait for the process to exit.
*/
while(((pid = wait(&status)) != cpid) && (pid >= 0))
continue;
res = (char *)Buf_GetAll (buf, &cc);
Buf_Destroy (buf, FALSE);
if (cc == 0)
*err = "Couldn't read shell's output for \"%s\"";
if (status)
*err = "\"%s\" returned non-zero status";
/*
* Null-terminate the result, convert newlines to spaces and
* install it in the variable.
*/
res[cc] = '\0';
cp = &res[cc] - 1;
if (*cp == '\n') {
/*
* A final newline is just stripped
*/
*cp-- = '\0';
}
while (cp >= res) {
if (*cp == '\n') {
*cp = ' ';
}
cp--;
}
break;
}
return res;
bad:
res = emalloc(1);
*res = '\0';
return res;
}
/*-
* Error --
* Print an error message given its format.
@ -952,17 +1153,46 @@ Finish(errors)
* emalloc --
* malloc, but die on error.
*/
char *
void *
emalloc(len)
size_t len;
{
char *p;
void *p;
if ((p = (char *) malloc(len)) == NULL)
if ((p = malloc(len)) == NULL)
enomem();
return(p);
}
/*
* estrdup --
* strdup, but die on error.
*/
char *
estrdup(str)
const char *str;
{
char *p;
if ((p = strdup(str)) == NULL)
enomem();
return(p);
}
/*
* erealloc --
* realloc, but die on error.
*/
void *
erealloc(ptr, size)
void *ptr;
size_t size;
{
if ((ptr = realloc(ptr, size)) == NULL)
enomem();
return(ptr);
}
/*
* enomem --
* die when out of memory.
@ -974,6 +1204,26 @@ enomem()
exit(2);
}
/*
* enunlink --
* Remove a file carefully, avoiding directories.
*/
int
eunlink(file)
const char *file;
{
struct stat st;
if (lstat(file, &st) == -1)
return -1;
if (S_ISDIR(st.st_mode)) {
errno = EISDIR;
return -1;
}
return unlink(file);
}
/*
* usage --
* exit with usage message
@ -982,8 +1232,9 @@ static void
usage()
{
(void)fprintf(stderr,
"usage: make [-eiknqrst] [-D variable] [-d flags] [-f makefile] [-I directory]\n\
[-j max_jobs] [-V variable] [variable=value] [target ...]\n");
"usage: make [-Beiknqrst] [-D variable] [-d flags] [-f makefile ]\n\
[-I directory] [-j max_jobs] [-m directory] [-V variable]\n\
[variable=value] [target ...]\n");
exit(2);
}

View File

@ -29,8 +29,8 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" @(#)make.1 8.4 (Berkeley) 3/19/94
.\" $Id$
.\" from: @(#)make.1 8.4 (Berkeley) 3/19/94
.\" $Id: make.1,v 1.5 1996/10/05 22:27:13 wosch Exp $
.\"
.Dd March 19, 1994
.Dt MAKE 1
@ -40,13 +40,14 @@
.Nd maintain program dependencies
.Sh SYNOPSIS
.Nm make
.Op Fl eiknqrst
.Op Fl Beiknqrst
.Op Fl D Ar variable
.Op Fl d Ar flags
.Op Fl f Ar makefile
.Op Fl I Ar directory
.Bk -words
.Op Fl j Ar max_jobs
.Op Fl m Ar directory
.Ek
.Op Fl V Ar variable
.Op Ar variable=value
@ -75,6 +76,9 @@ and makefiles, please refer to
.Pp
The options are as follows:
.Bl -tag -width Ds
.It Fl B
Try to be backwards compatible by executing a single shell per command and
by executing the commands to make the sources of a dependency line in sequence.
.It Fl D Ar variable
Define
.Ar variable
@ -128,8 +132,9 @@ standard input is read.
Multiple makefile's may be specified, and are read in the order specified.
.It Fl I Ar directory
Specify a directory in which to search for makefiles and included makefiles.
The system makefile directory is automatically included as part of this
list.
The system makefile directory (or directories, see the
.Fl m
option) is automatically included as part of this list.
.It Fl i
Ignore non-zero exit of shell commands in the makefile.
Equivalent to specifying
@ -138,10 +143,20 @@ before each command line in the makefile.
.It Fl j Ar max_jobs
Specify the maximum number of jobs that
.Nm make
may have running at any one time.
may have running at any one time. Turns compatibility mode off, unless the
.Ar B
flag is also specified.
.It Fl k
Continue processing after errors are encountered, but only on those targets
that do not depend on the target whose creation caused the error.
.It Fl m Ar directory
Specify a directory in which to search for sys.mk and makefiles included
via the <...> style. Multiple directories can be added to form a search path.
This path will override the default system include path: /usr/share/mk.
Furthermore the system include path will be appended to the search path used
for "..."-style inclusions (see the
.Fl I
option).
.It Fl n
Display the commands that would have been executed, but do not actually
execute them.
@ -291,13 +306,13 @@ between the previous contents of the variable and the appended value.
Variables are expanded by surrounding the variable name with either
curly braces
.Pq Ql {}
or parenthesis
or parentheses
.Pq Ql ()
and preceding it with
a dollar sign
.Pq Ql \&$ .
If the variable name contains only a single letter, the surrounding
braces or parenthesis are not required.
braces or parentheses are not required.
This shorter form is not recommended.
.Pp
Variable substitution occurs at two distinct times, depending on where
@ -386,10 +401,11 @@ i.e.
.Ql \&$$
expands to a single dollar
sign.
.It Ev MAKE
.It Va .MAKE
The name that
.Nm make
was executed with.
was executed with
.Pq Va argv Op 0
.It Va .CURDIR
A path to the directory where
.Nm make
@ -414,7 +430,7 @@ executes.
.It Ev PWD
Alternate path to the current directory.
.Nm make
normally sets
normally sets
.Ql Va .CURDIR
to the canonical path given by
.Xr getcwd 2 .
@ -520,23 +536,23 @@ This is the
.At V
style variable substitution.
It must be the last modifier specified.
If
If
.Ar old_string
or
.Ar new_string
do not contain the pattern matching character
.Ar %
then it is assumed that they are
then it is assumed that they are
anchored at the end of each word, so only suffixes or entire
words may be replaced. Otherwise
words may be replaced. Otherwise
.Ar %
is the substring of
.Ar old_string
is the substring of
.Ar old_string
to be replaced in
.Ar new_string
.El
.Sh INCLUDE STATEMENTS, CONDITIONALS AND FOR LOOPS
Makefile inclusion, conditional structures and for loops reminiscent
Makefile inclusion, conditional structures and for loops reminiscent
of the C programming language are provided in
.Nm make .
All such structures are identified by a line beginning with a single
@ -738,14 +754,14 @@ In both cases this continues until a
or
.Ql Ic .endif
is found.
.Pp
.Pp
For loops are typically used to apply a set of rules to a list of files.
The syntax of a for loop is:
.Bl -tag -width Ds
.It Xo
.Ic \&.for
.Ar variable
.Ic in
.Ar variable
.Ic in
.Ar expression
.Xc
.It Xo
@ -756,12 +772,12 @@ The syntax of a for loop is:
.Xc
.El
After the for
.Ic expression
is evaluated, it is split into words. The
.Ic expression
is evaluated, it is split into words. The
iteration
.Ic variable
is successively set to each word, and substituted in the
.Ic make-rules
is successively set to each word, and substituted in the
.Ic make-rules
inside the body of the for loop.
.Sh COMMENTS
Comments begin with a hash
@ -815,6 +831,12 @@ If the target already has commands, the
.Ic .USE
target's commands are appended
to them.
.It Ic .WAIT
If special
.Ic .WAIT
source is appears in a dependency line, the sources that precede it are
made before the sources that succeed it in the line. Loops are not being
detected and targets that form loops will be silently ignored.
.El
.Sh "SPECIAL TARGETS"
Special targets may not be included with other targets, i.e. they must be
@ -863,11 +885,30 @@ The flags are as if typed to the shell, though the
.Fl f
option will have
no effect.
.\" XXX: NOT YET!!!!
.\" .It Ic .NOTPARALLEL
.\" The named targets are executed in non parallel mode. If no targets are
.\" specified, then all targets are executed in non parallel mode.
.It Ic .NOTPARALLEL
Disable parallel mode.
.It Ic .NO_PARALLEL
Same as above, for compatibility with other pmake variants.
.It Ic .ORDER
The named targets are made in sequence.
.\" XXX: NOT YET!!!!
.\" .It Ic .PARALLEL
.\" The named targets are executed in parallel mode. If no targets are
.\" specified, then all targets are executed in parallel mode.
.It Ic .PATH
The sources are directories which are to be searched for files not
found in the current directory.
If no sources are specified, any previously specified directories are
deleted.
.It Ic .PHONY
Apply the
.Ic .PHONY
attribute to any specified sources. Targets with this attribute are always
considered to be out of date.
.It Ic .PRECIOUS
Apply the
.Ic .PRECIOUS

View File

@ -207,7 +207,7 @@ Make_OODate (gn)
printf(".JOIN node...");
}
oodate = gn->childMade;
} else if (gn->type & (OP_FORCE|OP_EXEC)) {
} else if (gn->type & (OP_FORCE|OP_EXEC|OP_PHONY)) {
/*
* A node which is the object of the force (!) operator or which has
* the .EXEC attribute is always considered out-of-date.
@ -215,6 +215,8 @@ Make_OODate (gn)
if (DEBUG(MAKE)) {
if (gn->type & OP_FORCE) {
printf("! operator...");
} else if (gn->type & OP_PHONY) {
printf(".PHONY node...");
} else {
printf(".EXEC node...");
}
@ -570,9 +572,16 @@ MakeAddAllSrc (cgnp, pgnp)
GNode *pgn = (GNode *) pgnp;
if ((cgn->type & (OP_EXEC|OP_USE|OP_INVISIBLE)) == 0) {
char *child;
char *p1;
char *p1 = NULL;
child = Var_Value(TARGET, cgn, &p1);
if (OP_NOP(cgn->type)) {
/*
* this node is only source; use the specific pathname for it
*/
child = cgn->path ? cgn->path : cgn->name;
}
else
child = Var_Value(TARGET, cgn, &p1);
Var_Append (ALLSRC, child, pgn);
if (pgn->type & OP_JOIN) {
if (cgn->made == MADE) {

View File

@ -35,7 +35,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)make.h 8.1 (Berkeley) 6/6/93
* from: @(#)make.h 8.3 (Berkeley) 6/13/95
*/
/*-
@ -50,15 +50,17 @@
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#ifndef MAKE_BOOTSTRAP
#if !defined(MAKE_BOOTSTRAP) && defined(BSD)
#include <sys/cdefs.h>
#else
#ifndef __P
#if defined(__STDC__) || defined(__cplusplus)
#define __P(protos) protos /* full-blown ANSI C */
#else
#define __P(protos) () /* traditional C preprocessor */
#endif
#endif
#endif
#if __STDC__
#include <stdlib.h>
#include <unistd.h>
@ -100,6 +102,7 @@ typedef struct GNode {
char *name; /* The target's name */
char *path; /* The full pathname of the file */
int type; /* Its type (see the OP flags, below) */
int order; /* Its wait weight */
Boolean make; /* TRUE if this target needs to be remade */
enum {
@ -192,6 +195,7 @@ typedef struct GNode {
* local variables. */
#define OP_NOTMAIN 0x00008000 /* The node is exempt from normal 'main
* target' processing in parse.c */
#define OP_PHONY 0x00010000 /* Not a file target; run always */
/* Attributes applied by PMake */
#define OP_TRANSFORM 0x80000000 /* The node is a transformation rule */
#define OP_MEMBER 0x40000000 /* Target is a member of an archive */
@ -322,6 +326,8 @@ extern time_t now; /* The time at the start of this whole
extern Boolean oldVars; /* Do old-style variable substitution */
extern Lst sysIncPath; /* The system include path. */
/*
* debug control:
* There is one bit per module. It is up to the module what debug

View File

@ -35,7 +35,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)nonints.h 8.3 (Berkeley) 3/19/94
* from: @(#)nonints.h 8.3 (Berkeley) 3/19/94
*/
/* arch.c */
@ -63,14 +63,18 @@ void For_Run __P((void));
/* main.c */
void Main_ParseArgLine __P((char *));
int main __P((int, char **));
char *Cmd_Exec __P((char *, char **));
void Error __P((char *, ...));
void Fatal __P((char *, ...));
void Punt __P((char *, ...));
void DieHorribly __P((void));
int PrintAddr __P((ClientData, ClientData));
void Finish __P((int));
char *emalloc __P((size_t));
char *estrdup __P((const char *));
void *emalloc __P((size_t));
void *erealloc __P((void *, size_t));
void enomem __P((void));
int eunlink __P((const char *));
/* parse.c */
void Parse_Error __P((int, char *, ...));

View File

@ -90,7 +90,6 @@ static char sccsid[] = "@(#)parse.c 8.3 (Berkeley) 3/19/94";
#include <stdio.h>
#include <ctype.h>
#include <errno.h>
#include <sys/wait.h>
#include "make.h"
#include "hash.h"
#include "dir.h"
@ -162,16 +161,20 @@ typedef enum {
NotParallel, /* .NOTPARALELL */
Null, /* .NULL */
Order, /* .ORDER */
Parallel, /* .PARALLEL */
ExPath, /* .PATH */
Phony, /* .PHONY */
Precious, /* .PRECIOUS */
ExShell, /* .SHELL */
Silent, /* .SILENT */
SingleShell, /* .SINGLESHELL */
Suffixes, /* .SUFFIXES */
Wait, /* .WAIT */
Attribute /* Generic attribute */
} ParseSpecial;
static ParseSpecial specType;
static int waiting;
/*
* Predecessor node for handling .ORDER. Initialized to NILGNODE when .ORDER
@ -207,10 +210,13 @@ static struct {
{ ".MFLAGS", MFlags, 0 },
{ ".NOTMAIN", Attribute, OP_NOTMAIN },
{ ".NOTPARALLEL", NotParallel, 0 },
{ ".NO_PARALLEL", NotParallel, 0 },
{ ".NULL", Null, 0 },
{ ".OPTIONAL", Attribute, OP_OPTIONAL },
{ ".ORDER", Order, 0 },
{ ".PARALLEL", Parallel, 0 },
{ ".PATH", ExPath, 0 },
{ ".PHONY", Phony, OP_PHONY },
{ ".PRECIOUS", Precious, OP_PRECIOUS },
{ ".RECURSIVE", Attribute, OP_MAKE },
{ ".SHELL", ExShell, 0 },
@ -218,12 +224,14 @@ static struct {
{ ".SINGLESHELL", SingleShell, 0 },
{ ".SUFFIXES", Suffixes, 0 },
{ ".USE", Attribute, OP_USE },
{ ".WAIT", Wait, 0 },
};
static int ParseFindKeyword __P((char *));
static int ParseLinkSrc __P((ClientData, ClientData));
static int ParseDoOp __P((ClientData, ClientData));
static void ParseDoSrc __P((int, char *));
static int ParseAddDep __P((ClientData, ClientData));
static void ParseDoSrc __P((int, char *, Lst));
static int ParseFindMain __P((ClientData, ClientData));
static int ParseAddDir __P((ClientData, ClientData));
static int ParseClearPath __P((ClientData, ClientData));
@ -435,6 +443,45 @@ ParseDoOp (gnp, opp)
return (0);
}
/*-
*---------------------------------------------------------------------
* ParseAddDep --
* Check if the pair of GNodes given needs to be synchronized.
* This has to be when two nodes are on different sides of a
* .WAIT directive.
*
* Results:
* Returns 1 if the two targets need to be ordered, 0 otherwise.
* If it returns 1, the search can stop
*
* Side Effects:
* A dependency can be added between the two nodes.
*
*---------------------------------------------------------------------
*/
int
ParseAddDep(pp, sp)
ClientData pp;
ClientData sp;
{
GNode *p = (GNode *) pp;
GNode *s = (GNode *) sp;
if (p->order < s->order) {
/*
* XXX: This can cause loops, and loops can cause unmade targets,
* but checking is tedious, and the debugging output can show the
* problem
*/
(void)Lst_AtEnd(p->successors, (ClientData)s);
(void)Lst_AtEnd(s->preds, (ClientData)p);
return 0;
}
else
return 1;
}
/*-
*---------------------------------------------------------------------
* ParseDoSrc --
@ -453,23 +500,30 @@ ParseDoOp (gnp, opp)
*---------------------------------------------------------------------
*/
static void
ParseDoSrc (tOp, src)
ParseDoSrc (tOp, src, allsrc)
int tOp; /* operator (if any) from special targets */
char *src; /* name of the source to handle */
Lst allsrc; /* List of all sources to wait for */
{
int op; /* operator (if any) from special source */
GNode *gn;
GNode *gn = NULL;
op = 0;
if (*src == '.' && isupper (src[1])) {
int keywd = ParseFindKeyword(src);
if (keywd != -1) {
op = parseKeywords[keywd].op;
int op = parseKeywords[keywd].op;
if (op != 0) {
Lst_ForEach (targets, ParseDoOp, (ClientData)&op);
return;
}
if (parseKeywords[keywd].spec == Wait) {
waiting++;
return;
}
}
}
if (op != 0) {
Lst_ForEach (targets, ParseDoOp, (ClientData)&op);
} else if (specType == Main) {
switch (specType) {
case Main:
/*
* If we have noted the existence of a .MAIN, it means we need
* to add the sources of said target to the list of things
@ -478,13 +532,15 @@ ParseDoSrc (tOp, src)
* invoked if the user didn't specify a target on the command
* line. This is to allow #ifmake's to succeed, or something...
*/
(void) Lst_AtEnd (create, (ClientData)strdup(src));
(void) Lst_AtEnd (create, (ClientData)estrdup(src));
/*
* Add the name to the .TARGETS variable as well, so the user cna
* employ that, if desired.
*/
Var_Append(".TARGETS", src, VAR_GLOBAL);
} else if (specType == Order) {
return;
case Order:
/*
* Create proper predecessor/successor links between the previous
* source and the current one.
@ -498,7 +554,9 @@ ParseDoSrc (tOp, src)
* The current source now becomes the predecessor for the next one.
*/
predecessor = gn;
} else {
break;
default:
/*
* If the source is not an attribute, we need to find/create
* a node for it. After that we can apply any operator to it
@ -529,6 +587,13 @@ ParseDoSrc (tOp, src)
}
}
}
break;
}
gn->order = waiting;
(void)Lst_AtEnd(allsrc, (ClientData)gn);
if (waiting) {
Lst_ForEach(allsrc, ParseAddDep, (ClientData)gn);
}
}
@ -651,16 +716,20 @@ ParseDoDependency (line)
Lst paths; /* List of search paths to alter when parsing
* a list of .PATH targets */
int tOp; /* operator from special target */
Lst sources; /* list of source names after expansion */
Lst sources; /* list of archive source names after
* expansion */
Lst curTargs; /* list of target names to be found and added
* to the targets list */
Lst curSrcs; /* list of sources in order */
tOp = 0;
specType = Not;
waiting = 0;
paths = (Lst)NULL;
curTargs = Lst_Init(FALSE);
curSrcs = Lst_Init(FALSE);
do {
for (cp = line;
@ -757,6 +826,7 @@ ParseDoDependency (line)
* life easier later, when we'll
* use Make_HandleUse to actually
* apply the .DEFAULT commands.
* .PHONY The list of targets
* .BEGIN
* .END
* .INTERRUPT Are not to be considered the
@ -1100,7 +1170,7 @@ ParseDoDependency (line)
while (!Lst_IsEmpty (sources)) {
gn = (GNode *) Lst_DeQueue (sources);
ParseDoSrc (tOp, gn->name);
ParseDoSrc (tOp, gn->name, curSrcs);
}
Lst_Destroy (sources, NOFREE);
cp = line;
@ -1110,7 +1180,7 @@ ParseDoDependency (line)
cp += 1;
}
ParseDoSrc (tOp, line);
ParseDoSrc (tOp, line, curSrcs);
}
while (*cp && isspace (*cp)) {
cp++;
@ -1129,6 +1199,10 @@ ParseDoDependency (line)
Lst_ForEach (targets, ParseFindMain, (ClientData)0);
}
/*
* Finally, destroy the list of sources
*/
Lst_Destroy(curSrcs, NOFREE);
}
/*-
@ -1153,60 +1227,80 @@ Parse_IsVar (line)
{
register Boolean wasSpace = FALSE; /* set TRUE if found a space */
register Boolean haveName = FALSE; /* Set TRUE if have a variable name */
int level = 0;
#define ISEQOPERATOR(c) \
(((c) == '+') || ((c) == ':') || ((c) == '?') || ((c) == '!'))
/*
* Skip to variable name
*/
while ((*line == ' ') || (*line == '\t')) {
line++;
}
for (;(*line == ' ') || (*line == '\t'); line++)
continue;
while (*line != '=') {
if (*line == '\0') {
for (; *line != '=' || level != 0; line++)
switch (*line) {
case '\0':
/*
* end-of-line -- can't be a variable assignment.
*/
return (FALSE);
} else if ((*line == ' ') || (*line == '\t')) {
return FALSE;
case ' ':
case '\t':
/*
* there can be as much white space as desired so long as there is
* only one word before the operator
*/
wasSpace = TRUE;
} else if (wasSpace && haveName) {
/*
* Stop when an = operator is found.
*/
if ((*line == '+') || (*line == ':') || (*line == '?') ||
(*line == '!')) {
break;
break;
case '(':
case '{':
level++;
break;
case '}':
case ')':
level--;
break;
default:
if (wasSpace && haveName) {
if (ISEQOPERATOR(*line)) {
/*
* We must have a finished word
*/
if (level != 0)
return FALSE;
/*
* When an = operator [+?!:] is found, the next
* character must be an = or it ain't a valid
* assignment.
*/
if (line[1] == '=')
return haveName;
#ifdef SUNSHCMD
/*
* This is a shell command
*/
if (strncmp(line, ":sh", 3) == 0)
return haveName;
#endif
}
/*
* This is the start of another word, so not assignment.
*/
return FALSE;
}
/*
* This is the start of another word, so not assignment.
*/
return (FALSE);
} else {
haveName = TRUE;
wasSpace = FALSE;
else {
haveName = TRUE;
wasSpace = FALSE;
}
break;
}
line++;
}
/*
* A final check: if we stopped on a +, ?, ! or :, the next character must
* be an = or it ain't a valid assignment
*/
if (((*line == '+') ||
(*line == '?') ||
(*line == ':') ||
(*line == '!')) &&
(line[1] != '='))
{
return (FALSE);
} else {
return (haveName);
}
return haveName;
}
/*-
@ -1300,6 +1394,17 @@ Parse_DoVar (line, ctxt)
break;
default:
#ifdef SUNSHCMD
while (*opc != ':')
if (--opc < line)
break;
if (strncmp(opc, ":sh", 3) == 0) {
type = VAR_SHELL;
*opc = '\0';
break;
}
#endif
type = VAR_NORMAL;
break;
}
@ -1331,157 +1436,38 @@ Parse_DoVar (line, ctxt)
Var_Set(line, cp, ctxt);
free(cp);
} else if (type == VAR_SHELL) {
char *args[4]; /* Args for invoking the shell */
int fds[2]; /* Pipe streams */
int cpid; /* Child PID */
int pid; /* PID from wait() */
Boolean freeCmd; /* TRUE if the command needs to be freed, i.e.
* if any variable expansion was performed */
Boolean freeCmd = FALSE; /* TRUE if the command needs to be freed, i.e.
* if any variable expansion was performed */
char *res, *err;
/*
* Avoid clobbered variable warnings by forcing the compiler
* to ``unregister'' variables
*/
#if __GNUC__
(void) &freeCmd;
#endif
/*
* Set up arguments for shell
*/
args[0] = "sh";
args[1] = "-c";
if (strchr(cp, '$') != (char *)NULL) {
if (strchr(cp, '$') != NULL) {
/*
* There's a dollar sign in the command, so perform variable
* expansion on the whole thing. The resulting string will need
* freeing when we're done, so set freeCmd to TRUE.
*/
args[2] = Var_Subst(NULL, cp, VAR_CMD, TRUE);
cp = Var_Subst(NULL, cp, VAR_CMD, TRUE);
freeCmd = TRUE;
} else {
args[2] = cp;
freeCmd = FALSE;
}
args[3] = (char *)NULL;
/*
* Open a pipe for fetching its output
*/
pipe(fds);
res = Cmd_Exec(cp, &err);
Var_Set(line, res, ctxt);
free(res);
/*
* Fork
*/
cpid = vfork();
if (cpid == 0) {
/*
* Close input side of pipe
*/
close(fds[0]);
if (err)
Parse_Error(PARSE_WARNING, err, cp);
/*
* Duplicate the output stream to the shell's output, then
* shut the extra thing down. Note we don't fetch the error
* stream...why not? Why?
*/
dup2(fds[1], 1);
close(fds[1]);
execv("/bin/sh", args);
_exit(1);
} else if (cpid < 0) {
/*
* Couldn't fork -- tell the user and make the variable null
*/
Parse_Error(PARSE_WARNING, "Couldn't exec \"%s\"", cp);
Var_Set(line, "", ctxt);
} else {
int status;
int cc;
Buffer buf;
char *res;
/*
* No need for the writing half
*/
close(fds[1]);
buf = Buf_Init (MAKE_BSIZE);
do {
char result[BUFSIZ];
cc = read(fds[0], result, sizeof(result));
if (cc > 0)
Buf_AddBytes(buf, cc, (Byte *) result);
}
while (cc > 0 || (cc == -1 && errno == EINTR));
/*
* Close the input side of the pipe.
*/
close(fds[0]);
/*
* Wait for the process to exit.
*/
while(((pid = wait(&status)) != cpid) && (pid >= 0))
continue;
if (cc == -1) {
/*
* Couldn't read all of the child's output -- tell the user
* but still use whatever we read. Null output isn't an
* error unless there was an error reading it.
*/
Parse_Error(PARSE_WARNING, "Couldn't read shell's output");
}
res = (char *)Buf_GetAll (buf, &cc);
Buf_Destroy (buf, FALSE);
if (status) {
/*
* Child returned an error -- tell the user but still use
* the result.
*/
Parse_Error(PARSE_WARNING, "\"%s\" returned non-zero", cp);
}
/*
* Null-terminate the result, convert newlines to spaces and
* install it in the variable.
*/
res[cc] = '\0';
cp = &res[cc] - 1;
if (*cp == '\n') {
/*
* A final newline is just stripped
*/
*cp-- = '\0';
}
while (cp >= res) {
if (*cp == '\n') {
*cp = ' ';
}
cp--;
}
Var_Set(line, res, ctxt);
free(res);
}
if (freeCmd) {
free(args[2]);
}
if (freeCmd)
free(cp);
} else {
/*
* Normal assignment -- just do it.
*/
Var_Set (line, cp, ctxt);
Var_Set(line, cp, ctxt);
}
}
/*-
* ParseAddCmd --
* Lst_ForEach function to add a command line to all targets
@ -1639,17 +1625,20 @@ ParseDoInclude (file)
* leading path components and call Dir_FindFile to see if
* we can locate the beast.
*/
char *prefEnd;
char *prefEnd, *Fname;
prefEnd = strrchr (fname, '/');
/* Make a temporary copy of this, to be safe. */
Fname = estrdup(fname);
prefEnd = strrchr (Fname, '/');
if (prefEnd != (char *)NULL) {
char *newName;
*prefEnd = '\0';
if (file[0] == '/')
newName = strdup(file);
newName = estrdup(file);
else
newName = str_concat (fname, file, STR_ADDSLASH);
newName = str_concat (Fname, file, STR_ADDSLASH);
fullname = Dir_FindFile (newName, parseIncPath);
if (fullname == (char *)NULL) {
fullname = Dir_FindFile(newName, dirSearchPath);
@ -1659,6 +1648,7 @@ ParseDoInclude (file)
} else {
fullname = (char *)NULL;
}
free (Fname);
} else {
fullname = (char *)NULL;
}
@ -1763,7 +1753,7 @@ Parse_FromString(str)
curPTR = (PTR *) emalloc (sizeof (PTR));
curPTR->str = curPTR->ptr = str;
lineno = 0;
fname = strdup(fname);
fname = estrdup(fname);
}
@ -2189,7 +2179,11 @@ test_char:
break;
case '#':
if (!ignComment) {
if (compatMake && (lastc != '\\')) {
if (
#if 0
compatMake &&
#endif
(lastc != '\\')) {
/*
* If the character is a hash mark and it isn't escaped
* (or we're being compatible), the thing is a comment.
@ -2247,7 +2241,7 @@ test_char:
while (*ep)
++ep;
while (ep > line + 1 && (ep[-1] == ' ' || ep[-1] == '\t')) {
if (ep[-2] == '\\')
if (ep > line + 1 && ep[-2] == '\\')
break;
--ep;
}
@ -2421,13 +2415,13 @@ Parse_File(name, stream)
continue;
} else {
Parse_Error (PARSE_FATAL,
"Unassociated shell command \"%.20s\"",
"Unassociated shell command \"%s\"",
cp);
}
}
#ifdef SYSVINCLUDE
} else if (strncmp (line, "include", 7) == 0 &&
isspace(line[7]) &&
isspace((unsigned char) line[7]) &&
strchr(line, ':') == NULL) {
/*
* It's an S3/S5-style "include".
@ -2536,30 +2530,11 @@ Parse_File(name, stream)
void
Parse_Init ()
{
char *cp = NULL, *start;
/* avoid faults on read-only strings */
static char syspath[] = _PATH_DEFSYSPATH;
mainNode = NILGNODE;
parseIncPath = Lst_Init (FALSE);
sysIncPath = Lst_Init (FALSE);
includes = Lst_Init (FALSE);
targCmds = Lst_Init (FALSE);
/*
* Add the directories from the DEFSYSPATH (more than one may be given
* as dir1:...:dirn) to the system include path.
*/
for (start = syspath; *start != '\0'; start = cp) {
for (cp = start; *cp != '\0' && *cp != ':'; cp++)
continue;
if (*cp == '\0') {
Dir_AddDir(sysIncPath, start);
} else {
*cp++ = '\0';
Dir_AddDir(sysIncPath, start);
}
}
}
void

View File

@ -31,11 +31,11 @@
* SUCH DAMAGE.
*
* from: @(#)pathnames.h 5.2 (Berkeley) 6/1/90
* $Id: pathnames.h,v 1.3 1996/06/24 04:24:35 jkh Exp $
* $Id: pathnames.h,v 1.4 1996/09/18 06:06:39 swallace Exp $
*/
#define _PATH_OBJDIR "obj"
#define _PATH_OBJDIRPREFIX "/usr/obj"
#define _PATH_DEFSHELLDIR "/bin"
#define _PATH_DEFSYSMK "/usr/share/mk/sys.mk"
#define _PATH_DEFSYSMK "sys.mk"
#define _PATH_DEFSYSPATH "/usr/share/mk"

View File

@ -35,7 +35,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)sprite.h 8.1 (Berkeley) 6/6/93
* from: @(#)sprite.h 8.1 (Berkeley) 6/6/93
*/
/*

View File

@ -38,7 +38,7 @@
#ifndef lint
/* from: static char sccsid[] = "@(#)str.c 5.8 (Berkeley) 6/1/90"; */
static char *rcsid = "$Id: str.c,v 1.4 1995/05/30 06:32:05 rgrimes Exp $";
static char *rcsid = "$Id: str.c,v 1.5 1995/06/18 12:34:12 ache Exp $";
#endif /* not lint */
#include "make.h"
@ -55,7 +55,7 @@ void
str_init()
{
char *p1;
argv = (char **)emalloc((argmax = 50) * sizeof(char *));
argv = (char **)emalloc(((argmax = 50) + 1) * sizeof(char *));
argv[0] = Var_Value(".MAKE", VAR_GLOBAL, &p1);
}
@ -202,9 +202,8 @@ brk_string(str, store_argc, expand)
*t++ = '\0';
if (argc == argmax) {
argmax *= 2; /* ramp up fast */
if (!(argv = (char **)realloc(argv,
argmax * sizeof(char *))))
enomem();
argv = (char **)erealloc(argv,
(argmax + 1) * sizeof(char *));
}
argv[argc++] = start;
start = (char *)NULL;

View File

@ -95,7 +95,6 @@ static char sccsid[] = "@(#)suff.c 8.4 (Berkeley) 3/21/94";
#include "make.h"
#include "hash.h"
#include "dir.h"
#include "bit.h"
static Lst sufflist; /* Lst of suffixes */
static Lst suffClean; /* Lst of suffixes to be cleaned */
@ -159,6 +158,7 @@ static int SuffSuffIsSuffixP __P((ClientData, ClientData));
static int SuffSuffHasNameP __P((ClientData, ClientData));
static int SuffSuffIsPrefix __P((ClientData, ClientData));
static int SuffGNHasNameP __P((ClientData, ClientData));
static void SuffUnRef __P((ClientData, ClientData));
static void SuffFree __P((ClientData));
static void SuffInsert __P((Lst, Suff *));
static void SuffRemove __P((Lst, Suff *));
@ -796,7 +796,7 @@ Suff_AddSuffix (str)
if (ln == NILLNODE) {
s = (Suff *) emalloc (sizeof (Suff));
s->name = strdup (str);
s->name = estrdup (str);
s->nameLen = strlen (s->name);
s->searchPath = Lst_Init (FALSE);
s->children = Lst_Init (FALSE);
@ -1003,7 +1003,7 @@ SuffAddSrc (sp, lsp)
* that...
*/
s2 = (Src *) emalloc (sizeof (Src));
s2->file = strdup(targ->pref);
s2->file = estrdup(targ->pref);
s2->pref = targ->pref;
s2->parent = targ;
s2->node = NILGNODE;
@ -1266,7 +1266,7 @@ SuffFindCmds (targ, slst)
* again (ick)), and return the new structure.
*/
ret = (Src *)emalloc (sizeof (Src));
ret->file = strdup(s->name);
ret->file = estrdup(s->name);
ret->pref = targ->pref;
ret->suff = suff;
suff->refCount++;
@ -1841,7 +1841,8 @@ SuffFindNormalDeps(gn, slst)
* children, then look for any overriding transformations they imply.
* Should we find one, we discard the one we found before.
*/
while(ln != NILLNODE) {
while (ln != NILLNODE) {
/*
* Look for next possible suffix...
*/
@ -1855,7 +1856,7 @@ SuffFindNormalDeps(gn, slst)
* Allocate a Src structure to which things can be transformed
*/
targ = (Src *)emalloc(sizeof (Src));
targ->file = strdup(gn->name);
targ->file = estrdup(gn->name);
targ->suff = (Suff *)Lst_Datum(ln);
targ->suff->refCount++;
targ->node = gn;
@ -1900,13 +1901,13 @@ SuffFindNormalDeps(gn, slst)
}
targ = (Src *)emalloc(sizeof (Src));
targ->file = strdup(gn->name);
targ->file = estrdup(gn->name);
targ->suff = suffNull;
targ->suff->refCount++;
targ->node = gn;
targ->parent = (Src *)NULL;
targ->children = 0;
targ->pref = strdup(sopref);
targ->pref = estrdup(sopref);
#ifdef DEBUG_SRC
targ->cp = Lst_Init(FALSE);
#endif
@ -1916,7 +1917,7 @@ SuffFindNormalDeps(gn, slst)
* or dependencies defined for this gnode
*/
if (Lst_IsEmpty(gn->commands) && Lst_IsEmpty(gn->children))
SuffAddLevel(srcs, targ);
SuffAddLevel(srcs, targ);
else {
if (DEBUG(SUFF))
printf("not ");
@ -1988,6 +1989,7 @@ sfnd_abort:
(targ == NULL ? dirSearchPath :
targ->suff->searchPath));
if (gn->path != NULL) {
char *ptr;
Var_Set(TARGET, gn->path, gn);
if (targ != NULL) {
@ -1995,7 +1997,7 @@ sfnd_abort:
* Suffix known for the thing -- trim the suffix off
* the path to form the proper .PREFIX variable.
*/
int len = strlen(gn->path);
int savep = strlen(gn->path) - targ->suff->nameLen;
char savec;
if (gn->suffix)
@ -2003,12 +2005,17 @@ sfnd_abort:
gn->suffix = targ->suff;
gn->suffix->refCount++;
savec = gn->path[len-targ->suff->nameLen];
gn->path[len-targ->suff->nameLen] = '\0';
savec = gn->path[savep];
gn->path[savep] = '\0';
Var_Set(PREFIX, gn->path, gn);
if ((ptr = strrchr(gn->path, '/')) != NULL)
ptr++;
else
ptr = gn->path;
gn->path[len-targ->suff->nameLen] = savec;
Var_Set(PREFIX, ptr, gn);
gn->path[savep] = savec;
} else {
/*
* The .PREFIX gets the full path if the target has
@ -2018,7 +2025,12 @@ sfnd_abort:
gn->suffix->refCount--;
gn->suffix = NULL;
Var_Set(PREFIX, gn->path, gn);
if ((ptr = strrchr(gn->path, '/')) != NULL)
ptr++;
else
ptr = gn->path;
Var_Set(PREFIX, ptr, gn);
}
}
} else {
@ -2034,7 +2046,7 @@ sfnd_abort:
gn->suffix->refCount++;
if (gn->path != NULL)
free(gn->path);
gn->path = strdup(gn->name);
gn->path = estrdup(gn->name);
}
goto sfnd_return;
@ -2135,7 +2147,7 @@ sfnd_abort:
*/
if (gn->path)
free(gn->path);
gn->path = strdup(gn->name);
gn->path = estrdup(gn->name);
/*
* Nuke the transformation path and the Src structures left over in the
@ -2316,7 +2328,7 @@ Suff_Init ()
*/
emptySuff = suffNull = (Suff *) emalloc (sizeof (Suff));
suffNull->name = strdup ("");
suffNull->name = estrdup ("");
suffNull->nameLen = 0;
suffNull->searchPath = Lst_Init (FALSE);
Dir_Concat(suffNull->searchPath, dirSearchPath);

View File

@ -158,7 +158,7 @@ Targ_NewGN (name)
register GNode *gn;
gn = (GNode *) emalloc (sizeof (GNode));
gn->name = strdup (name);
gn->name = estrdup (name);
gn->path = (char *) 0;
if (name[0] == '-' && name[1] == 'l') {
gn->type = OP_LIB;
@ -169,6 +169,7 @@ Targ_NewGN (name)
gn->make = FALSE;
gn->made = UNMADE;
gn->childMade = FALSE;
gn->order = 0;
gn->mtime = gn->cmtime = 0;
gn->iParents = Lst_Init (FALSE);
gn->cohorts = Lst_Init (FALSE);
@ -467,9 +468,9 @@ Targ_FmtTime (time)
parts = localtime(&time);
sprintf (buf, "%d:%02d:%02d %s %d, 19%d",
sprintf (buf, "%d:%02d:%02d %s %d, %d",
parts->tm_hour, parts->tm_min, parts->tm_sec,
months[parts->tm_mon], parts->tm_mday, parts->tm_year);
months[parts->tm_mon], parts->tm_mday, 1900 + parts->tm_year);
return(buf);
}

349
usr.bin/make/util.c Normal file
View File

@ -0,0 +1,349 @@
/*
* Missing stuff from OS's
*/
#ifndef lint
static char rcsid[] = "$NetBSD: util.c,v 1.7 1996/08/30 17:59:44 thorpej Exp $";
#endif
#include <stdio.h>
#include "make.h"
#if !__STDC__
# ifndef const
# define const
# endif
#endif
#ifdef sun
extern int errno, sys_nerr;
extern char *sys_errlist[];
char *
strerror(e)
int e;
{
static char buf[100];
if (e < 0 || e >= sys_nerr) {
sprintf(buf, "Unknown error %d", e);
return buf;
}
else
return sys_errlist[e];
}
#endif
#ifdef ultrix
#include <string.h>
/* strdup
*
* Make a duplicate of a string.
* For systems which lack this function.
*/
char *
strdup(str)
const char *str;
{
size_t len;
if (str == NULL)
return NULL;
len = strlen(str) + 1;
if ((p = malloc(len)) == NULL)
return NULL;
return memcpy(p, str, len);
}
#endif
#if defined(sun) || defined(__hpux) || defined(__sgi)
int
setenv(name, value, dum)
const char *name;
const char *value;
int dum;
{
register char *p;
int len = strlen(name) + strlen(value) + 2; /* = \0 */
char *ptr = (char*) malloc(len);
(void) dum;
if (ptr == NULL)
return -1;
p = ptr;
while (*name)
*p++ = *name++;
*p++ = '=';
while (*value)
*p++ = *value++;
*p = '\0';
len = putenv(ptr);
/* free(ptr); */
return len;
}
#endif
#ifdef __hpux
#include <sys/types.h>
#include <sys/param.h>
#include <sys/syscall.h>
#include <sys/signal.h>
#include <sys/stat.h>
#include <stdio.h>
#include <dirent.h>
#include <sys/time.h>
#include <time.h>
#include <unistd.h>
int
killpg(pid, sig)
int pid, sig;
{
return kill(-pid, sig);
}
void
srandom(seed)
long seed;
{
srand48(seed);
}
long
random()
{
return lrand48();
}
/* turn into bsd signals */
void (*
signal(s, a)) ()
int s;
void (*a)();
{
struct sigvec osv, sv;
(void) sigvector(s, (struct sigvec *) 0, &osv);
sv = osv;
sv.sv_handler = a;
#ifdef SV_BSDSIG
sv.sv_flags = SV_BSDSIG;
#endif
if (sigvector(s, &sv, (struct sigvec *) 0) == -1)
return (BADSIG);
return (osv.sv_handler);
}
#if !defined(BSD) && !defined(d_fileno)
# define d_fileno d_ino
#endif
#ifndef DEV_DEV_COMPARE
# define DEV_DEV_COMPARE(a, b) ((a) == (b))
#endif
#define ISDOT(c) ((c)[0] == '.' && (((c)[1] == '\0') || ((c)[1] == '/')))
#define ISDOTDOT(c) ((c)[0] == '.' && ISDOT(&((c)[1])))
/* strrcpy():
* Like strcpy, going backwards and returning the new pointer
*/
static char *
strrcpy(ptr, str)
register char *ptr, *str;
{
register int len = strlen(str);
while (len)
*--ptr = str[--len];
return (ptr);
} /* end strrcpy */
char *
getwd(pathname)
char *pathname;
{
DIR *dp;
struct dirent *d;
extern int errno;
struct stat st_root, st_cur, st_next, st_dotdot;
char pathbuf[MAXPATHLEN], nextpathbuf[MAXPATHLEN * 2];
char *pathptr, *nextpathptr, *cur_name_add;
/* find the inode of root */
if (stat("/", &st_root) == -1) {
(void) sprintf(pathname,
"getwd: Cannot stat \"/\" (%s)", strerror(errno));
return (NULL);
}
pathbuf[MAXPATHLEN - 1] = '\0';
pathptr = &pathbuf[MAXPATHLEN - 1];
nextpathbuf[MAXPATHLEN - 1] = '\0';
cur_name_add = nextpathptr = &nextpathbuf[MAXPATHLEN - 1];
/* find the inode of the current directory */
if (lstat(".", &st_cur) == -1) {
(void) sprintf(pathname,
"getwd: Cannot stat \".\" (%s)", strerror(errno));
return (NULL);
}
nextpathptr = strrcpy(nextpathptr, "../");
/* Descend to root */
for (;;) {
/* look if we found root yet */
if (st_cur.st_ino == st_root.st_ino &&
DEV_DEV_COMPARE(st_cur.st_dev, st_root.st_dev)) {
(void) strcpy(pathname, *pathptr != '/' ? "/" : pathptr);
return (pathname);
}
/* open the parent directory */
if (stat(nextpathptr, &st_dotdot) == -1) {
(void) sprintf(pathname,
"getwd: Cannot stat directory \"%s\" (%s)",
nextpathptr, strerror(errno));
return (NULL);
}
if ((dp = opendir(nextpathptr)) == NULL) {
(void) sprintf(pathname,
"getwd: Cannot open directory \"%s\" (%s)",
nextpathptr, strerror(errno));
return (NULL);
}
/* look in the parent for the entry with the same inode */
if (DEV_DEV_COMPARE(st_dotdot.st_dev, st_cur.st_dev)) {
/* Parent has same device. No need to stat every member */
for (d = readdir(dp); d != NULL; d = readdir(dp))
if (d->d_fileno == st_cur.st_ino)
break;
}
else {
/*
* Parent has a different device. This is a mount point so we
* need to stat every member
*/
for (d = readdir(dp); d != NULL; d = readdir(dp)) {
if (ISDOT(d->d_name) || ISDOTDOT(d->d_name))
continue;
(void) strcpy(cur_name_add, d->d_name);
if (lstat(nextpathptr, &st_next) == -1) {
(void) sprintf(pathname, "getwd: Cannot stat \"%s\" (%s)",
d->d_name, strerror(errno));
(void) closedir(dp);
return (NULL);
}
/* check if we found it yet */
if (st_next.st_ino == st_cur.st_ino &&
DEV_DEV_COMPARE(st_next.st_dev, st_cur.st_dev))
break;
}
}
if (d == NULL) {
(void) sprintf(pathname, "getwd: Cannot find \".\" in \"..\"");
(void) closedir(dp);
return (NULL);
}
st_cur = st_dotdot;
pathptr = strrcpy(pathptr, d->d_name);
pathptr = strrcpy(pathptr, "/");
nextpathptr = strrcpy(nextpathptr, "../");
(void) closedir(dp);
*cur_name_add = '\0';
}
} /* end getwd */
char *sys_siglist[] = {
"Signal 0",
"Hangup", /* SIGHUP */
"Interrupt", /* SIGINT */
"Quit", /* SIGQUIT */
"Illegal instruction", /* SIGILL */
"Trace/BPT trap", /* SIGTRAP */
"IOT trap", /* SIGIOT */
"EMT trap", /* SIGEMT */
"Floating point exception", /* SIGFPE */
"Killed", /* SIGKILL */
"Bus error", /* SIGBUS */
"Segmentation fault", /* SIGSEGV */
"Bad system call", /* SIGSYS */
"Broken pipe", /* SIGPIPE */
"Alarm clock", /* SIGALRM */
"Terminated", /* SIGTERM */
"User defined signal 1", /* SIGUSR1 */
"User defined signal 2", /* SIGUSR2 */
"Child exited", /* SIGCLD */
"Power-fail restart", /* SIGPWR */
"Virtual timer expired", /* SIGVTALRM */
"Profiling timer expired", /* SIGPROF */
"I/O possible", /* SIGIO */
"Window size changes", /* SIGWINDOW */
"Stopped (signal)", /* SIGSTOP */
"Stopped", /* SIGTSTP */
"Continued", /* SIGCONT */
"Stopped (tty input)", /* SIGTTIN */
"Stopped (tty output)", /* SIGTTOU */
"Urgent I/O condition", /* SIGURG */
"Remote lock lost (NFS)", /* SIGLOST */
"Signal 31", /* reserved */
"DIL signal" /* SIGDIL */
};
int
utimes(file, tvp)
char *file;
struct timeval tvp[2];
{
struct utimbuf t;
t.actime = tvp[0].tv_sec;
t.modtime = tvp[1].tv_sec;
return(utime(file, &t));
}
#endif /* __hpux */
#if defined(sun) && defined(__svr4__)
#include <signal.h>
/* turn into bsd signals */
void (*
signal(s, a)) ()
int s;
void (*a)();
{
struct sigaction sa, osa;
sa.sa_handler = a;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
if (sigaction(s, &sa, &osa) == -1)
return SIG_ERR;
else
return osa.sa_handler;
}
#endif

View File

@ -158,7 +158,9 @@ static Boolean VarTail __P((char *, Boolean, Buffer, ClientData));
static Boolean VarSuffix __P((char *, Boolean, Buffer, ClientData));
static Boolean VarRoot __P((char *, Boolean, Buffer, ClientData));
static Boolean VarMatch __P((char *, Boolean, Buffer, ClientData));
#ifdef SYSVVARSUB
static Boolean VarSYSVMatch __P((char *, Boolean, Buffer, ClientData));
#endif
static Boolean VarNoMatch __P((char *, Boolean, Buffer, ClientData));
static Boolean VarSubstitute __P((char *, Boolean, Buffer, ClientData));
static char *VarModify __P((char *, Boolean (*)(char *, Boolean, Buffer,
@ -272,7 +274,7 @@ VarFind (name, ctxt, flags)
int len;
v = (Var *) emalloc(sizeof(Var));
v->name = strdup(name);
v->name = estrdup(name);
len = strlen(env);
@ -325,7 +327,7 @@ VarAdd (name, val, ctxt)
v = (Var *) emalloc (sizeof (Var));
v->name = strdup (name);
v->name = estrdup (name);
len = val ? strlen(val) : 0;
v->val = Buf_Init(len+1);
@ -775,8 +777,7 @@ VarMatch (word, addSpace, buf, pattern)
return(addSpace);
}
#ifdef SYSVVARSUB
/*-
*-----------------------------------------------------------------------
* VarSYSVMatch --
@ -818,6 +819,7 @@ VarSYSVMatch (word, addSpace, buf, patp)
return(addSpace);
}
#endif
/*-
@ -1100,7 +1102,7 @@ Var_Parse (str, ctxt, err, lengthPtr, freePtr)
Boolean haveModifier;/* TRUE if have modifiers for the variable */
register char endc; /* Ending character when variable in parens
* or braces */
register char startc; /* Starting character when variable in parens
register char startc=0; /* Starting character when variable in parens
* or braces */
int cnt; /* Used to count brace pairs when variable in
* in parens or braces */
@ -1617,7 +1619,22 @@ Var_Parse (str, ctxt, err, lengthPtr, freePtr)
break;
}
/*FALLTHRU*/
default: {
#ifdef SUNSHCMD
case 's':
if (tstr[1] == 'h' && (tstr[2] == endc || tstr[2] == ':')) {
char *err;
newStr = Cmd_Exec (str, &err);
if (err)
Error (err, str);
cp = tstr + 2;
termc = *cp;
break;
}
/*FALLTHRU*/
#endif
default:
{
#ifdef SYSVVARSUB
/*
* This can either be a bogus modifier or a System-V
* substitution command.
@ -1684,7 +1701,9 @@ Var_Parse (str, ctxt, err, lengthPtr, freePtr)
pattern.lhs[pattern.leftLen] = '=';
pattern.rhs[pattern.rightLen] = endc;
termc = endc;
} else {
} else
#endif
{
Error ("Unknown modifier '%c'\n", *tstr);
for (cp = tstr+1;
*cp != ':' && *cp != endc && *cp != '\0';