BSD 4.4 Lite Usr.bin Sources
This commit is contained in:
commit
95bef72976
14
usr.bin/make/Makefile
Normal file
14
usr.bin/make/Makefile
Normal file
@ -0,0 +1,14 @@
|
||||
# @(#)Makefile 8.1 (Berkeley) 6/6/93
|
||||
|
||||
PROG= make
|
||||
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
|
||||
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 \
|
||||
lstInit.c lstInsert.c lstIsAtEnd.c lstIsEmpty.c lstLast.c \
|
||||
lstMember.c lstNext.c lstOpen.c lstRemove.c lstReplace.c lstSucc.c
|
||||
.PATH: ${.CURDIR}/lst.lib
|
||||
|
||||
.include <bsd.prog.mk>
|
7
usr.bin/make/PSD.doc/Makefile
Normal file
7
usr.bin/make/PSD.doc/Makefile
Normal file
@ -0,0 +1,7 @@
|
||||
# @(#)Makefile 8.1 (Berkeley) 8/14/93
|
||||
|
||||
DIR= psd/12.make
|
||||
SRCS= tutorial.ms
|
||||
MACROS= -ms
|
||||
|
||||
.include <bsd.doc.mk>
|
3732
usr.bin/make/PSD.doc/tutorial.ms
Normal file
3732
usr.bin/make/PSD.doc/tutorial.ms
Normal file
File diff suppressed because it is too large
Load Diff
955
usr.bin/make/arch.c
Normal file
955
usr.bin/make/arch.c
Normal file
@ -0,0 +1,955 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)arch.c 8.2 (Berkeley) 1/2/94";
|
||||
#endif /* not lint */
|
||||
|
||||
/*-
|
||||
* arch.c --
|
||||
* Functions to manipulate libraries, archives and their members.
|
||||
*
|
||||
* Once again, cacheing/hashing comes into play in the manipulation
|
||||
* of archives. The first time an archive is referenced, all of its members'
|
||||
* headers are read and hashed and the archive closed again. All hashed
|
||||
* archives are kept on a list which is searched each time an archive member
|
||||
* is referenced.
|
||||
*
|
||||
* The interface to this module is:
|
||||
* Arch_ParseArchive Given an archive specification, return a list
|
||||
* of GNode's, one for each member in the spec.
|
||||
* FAILURE is returned if the specification is
|
||||
* invalid for some reason.
|
||||
*
|
||||
* Arch_Touch Alter the modification time of the archive
|
||||
* member described by the given node to be
|
||||
* the current time.
|
||||
*
|
||||
* Arch_TouchLib Update the modification time of the library
|
||||
* described by the given node. This is special
|
||||
* because it also updates the modification time
|
||||
* of the library's table of contents.
|
||||
*
|
||||
* Arch_MTime Find the modification time of a member of
|
||||
* an archive *in the archive*. The time is also
|
||||
* placed in the member's GNode. Returns the
|
||||
* modification time.
|
||||
*
|
||||
* Arch_MemTime Find the modification time of a member of
|
||||
* an archive. Called when the member doesn't
|
||||
* already exist. Looks in the archive for the
|
||||
* modification time. Returns the modification
|
||||
* time.
|
||||
*
|
||||
* Arch_FindLib Search for a library along a path. The
|
||||
* library name in the GNode should be in
|
||||
* -l<name> format.
|
||||
*
|
||||
* Arch_LibOODate Special function to decide if a library node
|
||||
* is out-of-date.
|
||||
*
|
||||
* Arch_Init Initialize this module.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <ctype.h>
|
||||
#include <ar.h>
|
||||
#include <ranlib.h>
|
||||
#include <stdio.h>
|
||||
#include "make.h"
|
||||
#include "hash.h"
|
||||
#include "dir.h"
|
||||
#include "config.h"
|
||||
|
||||
static Lst archives; /* Lst of archives we've already examined */
|
||||
|
||||
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 */
|
||||
} Arch;
|
||||
|
||||
static int ArchFindArchive __P((Arch *, char *));
|
||||
static struct ar_hdr *ArchStatMember __P((char *, char *, Boolean));
|
||||
static FILE *ArchFindMember __P((char *, char *, struct ar_hdr *, char *));
|
||||
|
||||
/*-
|
||||
*-----------------------------------------------------------------------
|
||||
* Arch_ParseArchive --
|
||||
* Parse the archive specification in the given line and find/create
|
||||
* the nodes for the specified archive members, placing their nodes
|
||||
* on the given list.
|
||||
*
|
||||
* Results:
|
||||
* SUCCESS if it was a valid specification. The linePtr is updated
|
||||
* to point to the first non-space after the archive spec. The
|
||||
* nodes for the members are placed on the given list.
|
||||
*
|
||||
* Side Effects:
|
||||
* Some nodes may be created. The given list is extended.
|
||||
*
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
ReturnStatus
|
||||
Arch_ParseArchive (linePtr, nodeLst, ctxt)
|
||||
char **linePtr; /* Pointer to start of specification */
|
||||
Lst nodeLst; /* Lst on which to place the nodes */
|
||||
GNode *ctxt; /* Context in which to expand variables */
|
||||
{
|
||||
register char *cp; /* Pointer into line */
|
||||
GNode *gn; /* New node */
|
||||
char *libName; /* Library-part of specification */
|
||||
char *memName; /* Member-part of specification */
|
||||
char nameBuf[MAKE_BSIZE]; /* temporary place for node name */
|
||||
char saveChar; /* Ending delimiter of member-name */
|
||||
Boolean subLibName; /* TRUE if libName should have/had
|
||||
* variable substitution performed on it */
|
||||
|
||||
libName = *linePtr;
|
||||
|
||||
subLibName = FALSE;
|
||||
|
||||
for (cp = libName; *cp != '(' && *cp != '\0'; cp++) {
|
||||
if (*cp == '$') {
|
||||
/*
|
||||
* Variable spec, so call the Var module to parse the puppy
|
||||
* so we can safely advance beyond it...
|
||||
*/
|
||||
int length;
|
||||
Boolean freeIt;
|
||||
char *result;
|
||||
|
||||
result=Var_Parse(cp, ctxt, TRUE, &length, &freeIt);
|
||||
if (result == var_Error) {
|
||||
return(FAILURE);
|
||||
} else {
|
||||
subLibName = TRUE;
|
||||
}
|
||||
|
||||
if (freeIt) {
|
||||
free(result);
|
||||
}
|
||||
cp += length-1;
|
||||
}
|
||||
}
|
||||
|
||||
*cp++ = '\0';
|
||||
if (subLibName) {
|
||||
libName = Var_Subst(NULL, libName, ctxt, TRUE);
|
||||
}
|
||||
|
||||
|
||||
for (;;) {
|
||||
/*
|
||||
* First skip to the start of the member's name, mark that
|
||||
* place and skip to the end of it (either white-space or
|
||||
* a close paren).
|
||||
*/
|
||||
Boolean doSubst = FALSE; /* TRUE if need to substitute in memName */
|
||||
|
||||
while (*cp != '\0' && *cp != ')' && isspace (*cp)) {
|
||||
cp++;
|
||||
}
|
||||
memName = cp;
|
||||
while (*cp != '\0' && *cp != ')' && !isspace (*cp)) {
|
||||
if (*cp == '$') {
|
||||
/*
|
||||
* Variable spec, so call the Var module to parse the puppy
|
||||
* so we can safely advance beyond it...
|
||||
*/
|
||||
int length;
|
||||
Boolean freeIt;
|
||||
char *result;
|
||||
|
||||
result=Var_Parse(cp, ctxt, TRUE, &length, &freeIt);
|
||||
if (result == var_Error) {
|
||||
return(FAILURE);
|
||||
} else {
|
||||
doSubst = TRUE;
|
||||
}
|
||||
|
||||
if (freeIt) {
|
||||
free(result);
|
||||
}
|
||||
cp += length;
|
||||
} else {
|
||||
cp++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If the specification ends without a closing parenthesis,
|
||||
* chances are there's something wrong (like a missing backslash),
|
||||
* so it's better to return failure than allow such things to happen
|
||||
*/
|
||||
if (*cp == '\0') {
|
||||
printf("No closing parenthesis in archive specification\n");
|
||||
return (FAILURE);
|
||||
}
|
||||
|
||||
/*
|
||||
* If we didn't move anywhere, we must be done
|
||||
*/
|
||||
if (cp == memName) {
|
||||
break;
|
||||
}
|
||||
|
||||
saveChar = *cp;
|
||||
*cp = '\0';
|
||||
|
||||
/*
|
||||
* XXX: This should be taken care of intelligently by
|
||||
* SuffExpandChildren, both for the archive and the member portions.
|
||||
*/
|
||||
/*
|
||||
* If member contains variables, try and substitute for them.
|
||||
* This will slow down archive specs with dynamic sources, of course,
|
||||
* since we'll be (non-)substituting them three times, but them's
|
||||
* the breaks -- we need to do this since SuffExpandChildren calls
|
||||
* us, otherwise we could assume the thing would be taken care of
|
||||
* later.
|
||||
*/
|
||||
if (doSubst) {
|
||||
char *buf;
|
||||
char *sacrifice;
|
||||
char *oldMemName = memName;
|
||||
|
||||
memName = Var_Subst(NULL, memName, ctxt, TRUE);
|
||||
|
||||
/*
|
||||
* Now form an archive spec and recurse to deal with nested
|
||||
* variables and multi-word variable values.... The results
|
||||
* are just placed at the end of the nodeLst we're returning.
|
||||
*/
|
||||
buf = sacrifice = emalloc(strlen(memName)+strlen(libName)+3);
|
||||
|
||||
sprintf(buf, "%s(%s)", libName, memName);
|
||||
|
||||
if (strchr(memName, '$') && strcmp(memName, oldMemName) == 0) {
|
||||
/*
|
||||
* Must contain dynamic sources, so we can't deal with it now.
|
||||
* Just create an ARCHV node for the thing and let
|
||||
* SuffExpandChildren handle it...
|
||||
*/
|
||||
gn = Targ_FindNode(buf, TARG_CREATE);
|
||||
|
||||
if (gn == NILGNODE) {
|
||||
free(buf);
|
||||
return(FAILURE);
|
||||
} else {
|
||||
gn->type |= OP_ARCHV;
|
||||
(void)Lst_AtEnd(nodeLst, (ClientData)gn);
|
||||
}
|
||||
} else if (Arch_ParseArchive(&sacrifice, nodeLst, ctxt)!=SUCCESS) {
|
||||
/*
|
||||
* Error in nested call -- free buffer and return FAILURE
|
||||
* ourselves.
|
||||
*/
|
||||
free(buf);
|
||||
return(FAILURE);
|
||||
}
|
||||
/*
|
||||
* Free buffer and continue with our work.
|
||||
*/
|
||||
free(buf);
|
||||
} else if (Dir_HasWildcards(memName)) {
|
||||
Lst members = Lst_Init(FALSE);
|
||||
char *member;
|
||||
|
||||
Dir_Expand(memName, dirSearchPath, members);
|
||||
while (!Lst_IsEmpty(members)) {
|
||||
member = (char *)Lst_DeQueue(members);
|
||||
|
||||
sprintf(nameBuf, "%s(%s)", libName, member);
|
||||
free(member);
|
||||
gn = Targ_FindNode (nameBuf, TARG_CREATE);
|
||||
if (gn == NILGNODE) {
|
||||
return (FAILURE);
|
||||
} else {
|
||||
/*
|
||||
* We've found the node, but have to make sure the rest of
|
||||
* the world knows it's an archive member, without having
|
||||
* to constantly check for parentheses, so we type the
|
||||
* thing with the OP_ARCHV bit before we place it on the
|
||||
* end of the provided list.
|
||||
*/
|
||||
gn->type |= OP_ARCHV;
|
||||
(void) Lst_AtEnd (nodeLst, (ClientData)gn);
|
||||
}
|
||||
}
|
||||
Lst_Destroy(members, NOFREE);
|
||||
} else {
|
||||
sprintf(nameBuf, "%s(%s)", libName, memName);
|
||||
gn = Targ_FindNode (nameBuf, TARG_CREATE);
|
||||
if (gn == NILGNODE) {
|
||||
return (FAILURE);
|
||||
} else {
|
||||
/*
|
||||
* We've found the node, but have to make sure the rest of the
|
||||
* world knows it's an archive member, without having to
|
||||
* constantly check for parentheses, so we type the thing with
|
||||
* the OP_ARCHV bit before we place it on the end of the
|
||||
* provided list.
|
||||
*/
|
||||
gn->type |= OP_ARCHV;
|
||||
(void) Lst_AtEnd (nodeLst, (ClientData)gn);
|
||||
}
|
||||
}
|
||||
if (doSubst) {
|
||||
free(memName);
|
||||
}
|
||||
|
||||
*cp = saveChar;
|
||||
}
|
||||
|
||||
/*
|
||||
* If substituted libName, free it now, since we need it no longer.
|
||||
*/
|
||||
if (subLibName) {
|
||||
free(libName);
|
||||
}
|
||||
|
||||
/*
|
||||
* We promised the pointer would be set up at the next non-space, so
|
||||
* we must advance cp there before setting *linePtr... (note that on
|
||||
* entrance to the loop, cp is guaranteed to point at a ')')
|
||||
*/
|
||||
do {
|
||||
cp++;
|
||||
} while (*cp != '\0' && isspace (*cp));
|
||||
|
||||
*linePtr = cp;
|
||||
return (SUCCESS);
|
||||
}
|
||||
|
||||
/*-
|
||||
*-----------------------------------------------------------------------
|
||||
* ArchFindArchive --
|
||||
* See if the given archive is the one we are looking for. Called
|
||||
* From ArchStatMember and ArchFindMember via Lst_Find.
|
||||
*
|
||||
* Results:
|
||||
* 0 if it is, non-zero if it isn't.
|
||||
*
|
||||
* Side Effects:
|
||||
* None.
|
||||
*
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
static int
|
||||
ArchFindArchive (ar, archName)
|
||||
Arch *ar; /* Current list element */
|
||||
char *archName; /* Name we want */
|
||||
{
|
||||
return (strcmp (archName, ar->name));
|
||||
}
|
||||
|
||||
/*-
|
||||
*-----------------------------------------------------------------------
|
||||
* ArchStatMember --
|
||||
* Locate a member of an archive, given the path of the archive and
|
||||
* the path of the desired member.
|
||||
*
|
||||
* Results:
|
||||
* A pointer to the current struct ar_hdr structure for the member. Note
|
||||
* That no position is returned, so this is not useful for touching
|
||||
* archive members. This is mostly because we have no assurances that
|
||||
* The archive will remain constant after we read all the headers, so
|
||||
* there's not much point in remembering the position...
|
||||
*
|
||||
* Side Effects:
|
||||
*
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
static struct ar_hdr *
|
||||
ArchStatMember (archive, member, hash)
|
||||
char *archive; /* Path to the archive */
|
||||
char *member; /* Name of member. If it is a path, only the
|
||||
* last component is used. */
|
||||
Boolean hash; /* TRUE if archive should be hashed if not
|
||||
* already so. */
|
||||
{
|
||||
#define AR_MAX_NAME_LEN (sizeof(arh.ar_name)-1)
|
||||
FILE * arch; /* Stream to archive */
|
||||
int size; /* Size of archive member */
|
||||
char *cp; /* Useful character pointer */
|
||||
char magic[SARMAG];
|
||||
int len;
|
||||
LstNode ln; /* Lst member containing archive descriptor */
|
||||
Arch *ar; /* Archive descriptor */
|
||||
Hash_Entry *he; /* Entry containing member's description */
|
||||
struct ar_hdr arh; /* archive-member header for reading archive */
|
||||
char memName[AR_MAX_NAME_LEN+1];
|
||||
/* Current member name while hashing. The name is
|
||||
* truncated to AR_MAX_NAME_LEN bytes, but we need
|
||||
* room for the null byte... */
|
||||
char copy[AR_MAX_NAME_LEN+1];
|
||||
/* Holds copy of last path element from member, if
|
||||
* it has to be truncated, so we don't have to
|
||||
* figure it out again once the table is hashed. */
|
||||
|
||||
/*
|
||||
* Because of space constraints and similar things, files are archived
|
||||
* using their final path components, not the entire thing, so we need
|
||||
* to point 'member' to the final component, if there is one, to make
|
||||
* the comparisons easier...
|
||||
*/
|
||||
cp = strrchr (member, '/');
|
||||
if (cp != (char *) NULL) {
|
||||
member = cp + 1;
|
||||
}
|
||||
len = strlen (member);
|
||||
if (len > AR_MAX_NAME_LEN) {
|
||||
len = AR_MAX_NAME_LEN;
|
||||
strncpy(copy, member, AR_MAX_NAME_LEN);
|
||||
copy[AR_MAX_NAME_LEN] = '\0';
|
||||
member = copy;
|
||||
}
|
||||
|
||||
ln = Lst_Find (archives, (ClientData) archive, ArchFindArchive);
|
||||
if (ln != NILLNODE) {
|
||||
ar = (Arch *) Lst_Datum (ln);
|
||||
|
||||
he = Hash_FindEntry (&ar->members, member);
|
||||
|
||||
if (he != (Hash_Entry *) NULL) {
|
||||
return ((struct ar_hdr *) Hash_GetValue (he));
|
||||
} else {
|
||||
return ((struct ar_hdr *) NULL);
|
||||
}
|
||||
}
|
||||
|
||||
if (!hash) {
|
||||
/*
|
||||
* Caller doesn't want the thing hashed, just use ArchFindMember
|
||||
* to read the header for the member out and close down the stream
|
||||
* again. Since the archive is not to be hashed, we assume there's
|
||||
* no need to allocate extra room for the header we're returning,
|
||||
* so just declare it static.
|
||||
*/
|
||||
static struct ar_hdr sarh;
|
||||
|
||||
arch = ArchFindMember(archive, member, &sarh, "r");
|
||||
|
||||
if (arch == (FILE *)NULL) {
|
||||
return ((struct ar_hdr *)NULL);
|
||||
} else {
|
||||
fclose(arch);
|
||||
return (&sarh);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* We don't have this archive on the list yet, so we want to find out
|
||||
* everything that's in it and cache it so we can get at it quickly.
|
||||
*/
|
||||
arch = fopen (archive, "r");
|
||||
if (arch == (FILE *) NULL) {
|
||||
return ((struct ar_hdr *) NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* We use the ARMAG string to make sure this is an archive we
|
||||
* can handle...
|
||||
*/
|
||||
if ((fread (magic, SARMAG, 1, arch) != 1) ||
|
||||
(strncmp (magic, ARMAG, SARMAG) != 0)) {
|
||||
fclose (arch);
|
||||
return ((struct ar_hdr *) NULL);
|
||||
}
|
||||
|
||||
ar = (Arch *)emalloc (sizeof (Arch));
|
||||
ar->name = strdup (archive);
|
||||
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);
|
||||
} else {
|
||||
(void) strncpy (memName, arh.ar_name, sizeof(arh.ar_name));
|
||||
for (cp = &memName[AR_MAX_NAME_LEN]; *cp == ' '; cp--) {
|
||||
continue;
|
||||
}
|
||||
cp[1] = '\0';
|
||||
|
||||
he = Hash_CreateEntry (&ar->members, strdup (memName),
|
||||
(Boolean *)NULL);
|
||||
Hash_SetValue (he, (ClientData)emalloc (sizeof (struct ar_hdr)));
|
||||
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';
|
||||
(void) sscanf (arh.ar_size, "%10d", &size);
|
||||
fseek (arch, (size + 1) & ~1, 1);
|
||||
}
|
||||
|
||||
fclose (arch);
|
||||
|
||||
(void) Lst_AtEnd (archives, (ClientData) ar);
|
||||
|
||||
/*
|
||||
* Now that the archive has been read and cached, we can look into
|
||||
* the hash table to find the desired member's header.
|
||||
*/
|
||||
he = Hash_FindEntry (&ar->members, member);
|
||||
|
||||
if (he != (Hash_Entry *) NULL) {
|
||||
return ((struct ar_hdr *) Hash_GetValue (he));
|
||||
} else {
|
||||
return ((struct ar_hdr *) NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/*-
|
||||
*-----------------------------------------------------------------------
|
||||
* ArchFindMember --
|
||||
* Locate a member of an archive, given the path of the archive and
|
||||
* the path of the desired member. If the archive is to be modified,
|
||||
* the mode should be "r+", if not, it should be "r".
|
||||
*
|
||||
* Results:
|
||||
* An FILE *, opened for reading and writing, positioned at the
|
||||
* start of the member's struct ar_hdr, or NULL if the member was
|
||||
* nonexistent. The current struct ar_hdr for member.
|
||||
*
|
||||
* Side Effects:
|
||||
* The passed struct ar_hdr structure is filled in.
|
||||
*
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
static FILE *
|
||||
ArchFindMember (archive, member, arhPtr, mode)
|
||||
char *archive; /* Path to the archive */
|
||||
char *member; /* Name of member. If it is a path, only the
|
||||
* last component is used. */
|
||||
struct ar_hdr *arhPtr; /* Pointer to header structure to be filled in */
|
||||
char *mode; /* The mode for opening the stream */
|
||||
{
|
||||
FILE * arch; /* Stream to archive */
|
||||
int size; /* Size of archive member */
|
||||
char *cp; /* Useful character pointer */
|
||||
char magic[SARMAG];
|
||||
int len;
|
||||
|
||||
arch = fopen (archive, mode);
|
||||
if (arch == (FILE *) NULL) {
|
||||
return ((FILE *) NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* We use the ARMAG string to make sure this is an archive we
|
||||
* can handle...
|
||||
*/
|
||||
if ((fread (magic, SARMAG, 1, arch) != 1) ||
|
||||
(strncmp (magic, ARMAG, SARMAG) != 0)) {
|
||||
fclose (arch);
|
||||
return ((FILE *) NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Because of space constraints and similar things, files are archived
|
||||
* using their final path components, not the entire thing, so we need
|
||||
* to point 'member' to the final component, if there is one, to make
|
||||
* the comparisons easier...
|
||||
*/
|
||||
cp = strrchr (member, '/');
|
||||
if (cp != (char *) NULL) {
|
||||
member = cp + 1;
|
||||
}
|
||||
len = strlen (member);
|
||||
if (len > sizeof (arhPtr->ar_name)) {
|
||||
len = sizeof (arhPtr->ar_name);
|
||||
}
|
||||
|
||||
while (fread ((char *)arhPtr, sizeof (struct ar_hdr), 1, arch) == 1) {
|
||||
if (strncmp(arhPtr->ar_fmag, ARFMAG, sizeof (arhPtr->ar_fmag) ) != 0) {
|
||||
/*
|
||||
* The header is bogus, so the archive is bad
|
||||
* and there's no way we can recover...
|
||||
*/
|
||||
fclose (arch);
|
||||
return ((FILE *) NULL);
|
||||
} else if (strncmp (member, arhPtr->ar_name, len) == 0) {
|
||||
/*
|
||||
* If the member's name doesn't take up the entire 'name' field,
|
||||
* we have to be careful of matching prefixes. Names are space-
|
||||
* padded to the right, so if the character in 'name' at the end
|
||||
* of the matched string is anything but a space, this isn't the
|
||||
* member we sought.
|
||||
*/
|
||||
if (len != sizeof(arhPtr->ar_name) && arhPtr->ar_name[len] != ' '){
|
||||
continue;
|
||||
} else {
|
||||
/*
|
||||
* To make life easier, we reposition the file at the start
|
||||
* of the header we just read before we return the stream.
|
||||
* In a more general situation, it might be better to leave
|
||||
* the file at the actual member, rather than its header, but
|
||||
* not here...
|
||||
*/
|
||||
fseek (arch, -sizeof(struct ar_hdr), 1);
|
||||
return (arch);
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* This isn't the member we're after, so 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.
|
||||
*/
|
||||
arhPtr->ar_size[sizeof(arhPtr->ar_size)-1] = '\0';
|
||||
(void)sscanf (arhPtr->ar_size, "%10d", &size);
|
||||
fseek (arch, (size + 1) & ~1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* We've looked everywhere, but the member is not to be found. Close the
|
||||
* archive and return NULL -- an error.
|
||||
*/
|
||||
fclose (arch);
|
||||
return ((FILE *) NULL);
|
||||
}
|
||||
|
||||
/*-
|
||||
*-----------------------------------------------------------------------
|
||||
* Arch_Touch --
|
||||
* Touch a member of an archive.
|
||||
*
|
||||
* Results:
|
||||
* The 'time' field of the member's header is updated.
|
||||
*
|
||||
* Side Effects:
|
||||
* The modification time of the entire archive is also changed.
|
||||
* For a library, this could necessitate the re-ranlib'ing of the
|
||||
* whole thing.
|
||||
*
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
void
|
||||
Arch_Touch (gn)
|
||||
GNode *gn; /* Node of member to touch */
|
||||
{
|
||||
FILE * arch; /* Stream open to archive, positioned properly */
|
||||
struct ar_hdr arh; /* Current header describing member */
|
||||
|
||||
arch = ArchFindMember(Var_Value (ARCHIVE, gn),
|
||||
Var_Value (TARGET, gn),
|
||||
&arh, "r+");
|
||||
sprintf(arh.ar_date, "%-12ld", (long) now);
|
||||
|
||||
if (arch != (FILE *) NULL) {
|
||||
(void)fwrite ((char *)&arh, sizeof (struct ar_hdr), 1, arch);
|
||||
fclose (arch);
|
||||
}
|
||||
}
|
||||
|
||||
/*-
|
||||
*-----------------------------------------------------------------------
|
||||
* Arch_TouchLib --
|
||||
* Given a node which represents a library, touch the thing, making
|
||||
* sure that the table of contents also is touched.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
*
|
||||
* Side Effects:
|
||||
* Both the modification time of the library and of the RANLIBMAG
|
||||
* member are set to 'now'.
|
||||
*
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
void
|
||||
Arch_TouchLib (gn)
|
||||
GNode *gn; /* The node of the library to touch */
|
||||
{
|
||||
FILE * arch; /* Stream open to archive */
|
||||
struct ar_hdr arh; /* Header describing table of contents */
|
||||
struct timeval times[2]; /* Times for utimes() call */
|
||||
|
||||
arch = ArchFindMember (gn->path, RANLIBMAG, &arh, "r+");
|
||||
sprintf(arh.ar_date, "%-12ld", (long) now);
|
||||
|
||||
if (arch != (FILE *) NULL) {
|
||||
(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);
|
||||
}
|
||||
}
|
||||
|
||||
/*-
|
||||
*-----------------------------------------------------------------------
|
||||
* Arch_MTime --
|
||||
* Return the modification time of a member of an archive.
|
||||
*
|
||||
* Results:
|
||||
* The modification time (seconds).
|
||||
*
|
||||
* Side Effects:
|
||||
* The mtime field of the given node is filled in with the value
|
||||
* returned by the function.
|
||||
*
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
int
|
||||
Arch_MTime (gn)
|
||||
GNode *gn; /* Node describing archive member */
|
||||
{
|
||||
struct ar_hdr *arhPtr; /* Header of desired member */
|
||||
int modTime; /* Modification time as an integer */
|
||||
|
||||
arhPtr = ArchStatMember (Var_Value (ARCHIVE, gn),
|
||||
Var_Value (TARGET, gn),
|
||||
TRUE);
|
||||
if (arhPtr != (struct ar_hdr *) NULL) {
|
||||
(void)sscanf (arhPtr->ar_date, "%12d", &modTime);
|
||||
} else {
|
||||
modTime = 0;
|
||||
}
|
||||
|
||||
gn->mtime = modTime;
|
||||
return (modTime);
|
||||
}
|
||||
|
||||
/*-
|
||||
*-----------------------------------------------------------------------
|
||||
* Arch_MemMTime --
|
||||
* Given a non-existent archive member's node, get its modification
|
||||
* time from its archived form, if it exists.
|
||||
*
|
||||
* Results:
|
||||
* The modification time.
|
||||
*
|
||||
* Side Effects:
|
||||
* The mtime field is filled in.
|
||||
*
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
int
|
||||
Arch_MemMTime (gn)
|
||||
GNode *gn;
|
||||
{
|
||||
LstNode ln;
|
||||
GNode *pgn;
|
||||
char *nameStart,
|
||||
*nameEnd;
|
||||
|
||||
if (Lst_Open (gn->parents) != SUCCESS) {
|
||||
gn->mtime = 0;
|
||||
return (0);
|
||||
}
|
||||
while ((ln = Lst_Next (gn->parents)) != NILLNODE) {
|
||||
pgn = (GNode *) Lst_Datum (ln);
|
||||
|
||||
if (pgn->type & OP_ARCHV) {
|
||||
/*
|
||||
* If the parent is an archive specification and is being made
|
||||
* and its member's name matches the name of the node we were
|
||||
* given, record the modification time of the parent in the
|
||||
* child. We keep searching its parents in case some other
|
||||
* parent requires this child to exist...
|
||||
*/
|
||||
nameStart = strchr (pgn->name, '(') + 1;
|
||||
nameEnd = strchr (nameStart, ')');
|
||||
|
||||
if (pgn->make &&
|
||||
strncmp(nameStart, gn->name, nameEnd - nameStart) == 0) {
|
||||
gn->mtime = Arch_MTime(pgn);
|
||||
}
|
||||
} else if (pgn->make) {
|
||||
/*
|
||||
* Something which isn't a library depends on the existence of
|
||||
* this target, so it needs to exist.
|
||||
*/
|
||||
gn->mtime = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Lst_Close (gn->parents);
|
||||
|
||||
return (gn->mtime);
|
||||
}
|
||||
|
||||
/*-
|
||||
*-----------------------------------------------------------------------
|
||||
* Arch_FindLib --
|
||||
* Search for a library along the given search path.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
*
|
||||
* Side Effects:
|
||||
* The node's 'path' field is set to the found path (including the
|
||||
* actual file name, not -l...). If the system can handle the -L
|
||||
* flag when linking (or we cannot find the library), we assume that
|
||||
* the user has placed the .LIBRARIES variable in the final linking
|
||||
* command (or the linker will know where to find it) and set the
|
||||
* TARGET variable for this node to be the node's name. Otherwise,
|
||||
* we set the TARGET variable to be the full path of the library,
|
||||
* as returned by Dir_FindFile.
|
||||
*
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
void
|
||||
Arch_FindLib (gn, path)
|
||||
GNode *gn; /* Node of library to find */
|
||||
Lst path; /* Search path */
|
||||
{
|
||||
char *libName; /* file name for archive */
|
||||
|
||||
libName = (char *)emalloc (strlen (gn->name) + 6 - 2);
|
||||
sprintf(libName, "lib%s.a", &gn->name[2]);
|
||||
|
||||
gn->path = Dir_FindFile (libName, path);
|
||||
|
||||
free (libName);
|
||||
|
||||
#ifdef LIBRARIES
|
||||
Var_Set (TARGET, gn->name, gn);
|
||||
#else
|
||||
Var_Set (TARGET, gn->path == (char *) NULL ? gn->name : gn->path, gn);
|
||||
#endif LIBRARIES
|
||||
}
|
||||
|
||||
/*-
|
||||
*-----------------------------------------------------------------------
|
||||
* Arch_LibOODate --
|
||||
* Decide if a node with the OP_LIB attribute is out-of-date. Called
|
||||
* from Make_OODate to make its life easier.
|
||||
*
|
||||
* There are several ways for a library to be out-of-date that are
|
||||
* not available to ordinary files. In addition, there are ways
|
||||
* that are open to regular files that are not available to
|
||||
* libraries. A library that is only used as a source is never
|
||||
* considered out-of-date by itself. This does not preclude the
|
||||
* library's modification time from making its parent be out-of-date.
|
||||
* A library will be considered out-of-date for any of these reasons,
|
||||
* given that it is a target on a dependency line somewhere:
|
||||
* Its modification time is less than that of one of its
|
||||
* sources (gn->mtime < gn->cmtime).
|
||||
* Its modification time is greater than the time at which the
|
||||
* make began (i.e. it's been modified in the course
|
||||
* of the make, probably by archiving).
|
||||
* Its modification time doesn't agree with the modification
|
||||
* time of its RANLIBMAG member (i.e. its table of contents
|
||||
* is out-of-date).
|
||||
*
|
||||
*
|
||||
* Results:
|
||||
* TRUE if the library is out-of-date. FALSE otherwise.
|
||||
*
|
||||
* Side Effects:
|
||||
* The library will be hashed if it hasn't been already.
|
||||
*
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
Boolean
|
||||
Arch_LibOODate (gn)
|
||||
GNode *gn; /* The library's graph node */
|
||||
{
|
||||
Boolean oodate;
|
||||
|
||||
if (OP_NOP(gn->type) && Lst_IsEmpty(gn->children)) {
|
||||
oodate = FALSE;
|
||||
} else if ((gn->mtime > now) || (gn->mtime < gn->cmtime)) {
|
||||
oodate = TRUE;
|
||||
} else {
|
||||
struct ar_hdr *arhPtr; /* Header for __.SYMDEF */
|
||||
int modTimeTOC; /* The table-of-contents's mod time */
|
||||
|
||||
arhPtr = ArchStatMember (gn->path, RANLIBMAG, FALSE);
|
||||
|
||||
if (arhPtr != (struct ar_hdr *)NULL) {
|
||||
(void)sscanf (arhPtr->ar_date, "%12d", &modTimeTOC);
|
||||
|
||||
if (DEBUG(ARCH) || DEBUG(MAKE)) {
|
||||
printf("%s modified %s...", RANLIBMAG, Targ_FmtTime(modTimeTOC));
|
||||
}
|
||||
oodate = (gn->mtime > modTimeTOC);
|
||||
} else {
|
||||
/*
|
||||
* A library w/o a table of contents is out-of-date
|
||||
*/
|
||||
if (DEBUG(ARCH) || DEBUG(MAKE)) {
|
||||
printf("No t.o.c....");
|
||||
}
|
||||
oodate = TRUE;
|
||||
}
|
||||
}
|
||||
return (oodate);
|
||||
}
|
||||
|
||||
/*-
|
||||
*-----------------------------------------------------------------------
|
||||
* Arch_Init --
|
||||
* Initialize things for this module.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
*
|
||||
* Side Effects:
|
||||
* The 'archives' list is initialized.
|
||||
*
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
void
|
||||
Arch_Init ()
|
||||
{
|
||||
archives = Lst_Init (FALSE);
|
||||
}
|
436
usr.bin/make/buf.c
Normal file
436
usr.bin/make/buf.c
Normal file
@ -0,0 +1,436 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)buf.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif /* not lint */
|
||||
|
||||
/*-
|
||||
* buf.c --
|
||||
* Functions for automatically-expanded buffers.
|
||||
*/
|
||||
|
||||
#include "sprite.h"
|
||||
#include "make.h"
|
||||
#include "buf.h"
|
||||
|
||||
#ifndef max
|
||||
#define max(a,b) ((a) > (b) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
/*
|
||||
* BufExpand --
|
||||
* Expand the given buffer to hold the given number of additional
|
||||
* bytes.
|
||||
* Makes sure there's room for an extra NULL byte at the end of the
|
||||
* buffer in case it holds a string.
|
||||
*/
|
||||
#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); \
|
||||
\
|
||||
(bp)->inPtr = newBuf + ((bp)->inPtr - (bp)->buffer); \
|
||||
(bp)->outPtr = newBuf + ((bp)->outPtr - (bp)->buffer);\
|
||||
(bp)->buffer = newBuf;\
|
||||
(bp)->size = newSize;\
|
||||
(bp)->left = newSize - ((bp)->inPtr - (bp)->buffer);\
|
||||
}
|
||||
|
||||
#define BUF_DEF_SIZE 256 /* Default buffer size */
|
||||
#define BUF_ADD_INC 256 /* Expansion increment when Adding */
|
||||
#define BUF_UNGET_INC 16 /* Expansion increment when Ungetting */
|
||||
|
||||
/*-
|
||||
*-----------------------------------------------------------------------
|
||||
* Buf_OvAddByte --
|
||||
* Add a single byte to the buffer. left is zero or negative.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
*
|
||||
* Side Effects:
|
||||
* The buffer may be expanded.
|
||||
*
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
void
|
||||
Buf_OvAddByte (bp, byte)
|
||||
register Buffer bp;
|
||||
int byte;
|
||||
{
|
||||
|
||||
bp->left = 0;
|
||||
BufExpand (bp, 1);
|
||||
|
||||
*bp->inPtr++ = byte;
|
||||
bp->left--;
|
||||
|
||||
/*
|
||||
* Null-terminate
|
||||
*/
|
||||
*bp->inPtr = 0;
|
||||
}
|
||||
|
||||
/*-
|
||||
*-----------------------------------------------------------------------
|
||||
* Buf_AddBytes --
|
||||
* Add a number of bytes to the buffer.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
*
|
||||
* Side Effects:
|
||||
* Guess what?
|
||||
*
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
void
|
||||
Buf_AddBytes (bp, numBytes, bytesPtr)
|
||||
register Buffer bp;
|
||||
int numBytes;
|
||||
Byte *bytesPtr;
|
||||
{
|
||||
|
||||
BufExpand (bp, numBytes);
|
||||
|
||||
memcpy (bp->inPtr, bytesPtr, numBytes);
|
||||
bp->inPtr += numBytes;
|
||||
bp->left -= numBytes;
|
||||
|
||||
/*
|
||||
* Null-terminate
|
||||
*/
|
||||
*bp->inPtr = 0;
|
||||
}
|
||||
|
||||
/*-
|
||||
*-----------------------------------------------------------------------
|
||||
* Buf_UngetByte --
|
||||
* Place the byte back at the beginning of the buffer.
|
||||
*
|
||||
* Results:
|
||||
* SUCCESS if the byte was added ok. FAILURE if not.
|
||||
*
|
||||
* Side Effects:
|
||||
* The byte is stuffed in the buffer and outPtr is decremented.
|
||||
*
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
void
|
||||
Buf_UngetByte (bp, byte)
|
||||
register Buffer bp;
|
||||
int byte;
|
||||
{
|
||||
|
||||
if (bp->outPtr != bp->buffer) {
|
||||
bp->outPtr--;
|
||||
*bp->outPtr = byte;
|
||||
} else if (bp->outPtr == bp->inPtr) {
|
||||
*bp->inPtr = byte;
|
||||
bp->inPtr++;
|
||||
bp->left--;
|
||||
*bp->inPtr = 0;
|
||||
} else {
|
||||
/*
|
||||
* Yech. have to expand the buffer to stuff this thing in.
|
||||
* We use a different expansion constant because people don't
|
||||
* usually push back many bytes when they're doing it a byte at
|
||||
* a time...
|
||||
*/
|
||||
int numBytes = bp->inPtr - bp->outPtr;
|
||||
Byte *newBuf;
|
||||
|
||||
newBuf = (Byte *)emalloc(bp->size + BUF_UNGET_INC);
|
||||
memcpy ((char *)(newBuf+BUF_UNGET_INC), (char *)bp->outPtr, numBytes+1);
|
||||
bp->outPtr = newBuf + BUF_UNGET_INC;
|
||||
bp->inPtr = bp->outPtr + numBytes;
|
||||
free ((char *)bp->buffer);
|
||||
bp->buffer = newBuf;
|
||||
bp->size += BUF_UNGET_INC;
|
||||
bp->left = bp->size - (bp->inPtr - bp->buffer);
|
||||
bp->outPtr -= 1;
|
||||
*bp->outPtr = byte;
|
||||
}
|
||||
}
|
||||
|
||||
/*-
|
||||
*-----------------------------------------------------------------------
|
||||
* Buf_UngetBytes --
|
||||
* Push back a series of bytes at the beginning of the buffer.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
*
|
||||
* Side Effects:
|
||||
* outPtr is decremented and the bytes copied into the buffer.
|
||||
*
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
void
|
||||
Buf_UngetBytes (bp, numBytes, bytesPtr)
|
||||
register Buffer bp;
|
||||
int numBytes;
|
||||
Byte *bytesPtr;
|
||||
{
|
||||
|
||||
if (bp->outPtr - bp->buffer >= numBytes) {
|
||||
bp->outPtr -= numBytes;
|
||||
memcpy (bp->outPtr, bytesPtr, numBytes);
|
||||
} else if (bp->outPtr == bp->inPtr) {
|
||||
Buf_AddBytes (bp, numBytes, bytesPtr);
|
||||
} else {
|
||||
int curNumBytes = bp->inPtr - bp->outPtr;
|
||||
Byte *newBuf;
|
||||
int newBytes = max(numBytes,BUF_UNGET_INC);
|
||||
|
||||
newBuf = (Byte *)emalloc (bp->size + newBytes);
|
||||
memcpy((char *)(newBuf+newBytes), (char *)bp->outPtr, curNumBytes+1);
|
||||
bp->outPtr = newBuf + newBytes;
|
||||
bp->inPtr = bp->outPtr + curNumBytes;
|
||||
free ((char *)bp->buffer);
|
||||
bp->buffer = newBuf;
|
||||
bp->size += newBytes;
|
||||
bp->left = bp->size - (bp->inPtr - bp->buffer);
|
||||
bp->outPtr -= numBytes;
|
||||
memcpy ((char *)bp->outPtr, (char *)bytesPtr, numBytes);
|
||||
}
|
||||
}
|
||||
|
||||
/*-
|
||||
*-----------------------------------------------------------------------
|
||||
* Buf_GetByte --
|
||||
* Return the next byte from the buffer. Actually returns an integer.
|
||||
*
|
||||
* Results:
|
||||
* Returns BUF_ERROR if there's no byte in the buffer, or the byte
|
||||
* itself if there is one.
|
||||
*
|
||||
* Side Effects:
|
||||
* outPtr is incremented and both outPtr and inPtr will be reset if
|
||||
* the buffer is emptied.
|
||||
*
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
int
|
||||
Buf_GetByte (bp)
|
||||
register Buffer bp;
|
||||
{
|
||||
int res;
|
||||
|
||||
if (bp->inPtr == bp->outPtr) {
|
||||
return (BUF_ERROR);
|
||||
} else {
|
||||
res = (int) *bp->outPtr;
|
||||
bp->outPtr += 1;
|
||||
if (bp->outPtr == bp->inPtr) {
|
||||
bp->outPtr = bp->inPtr = bp->buffer;
|
||||
bp->left = bp->size;
|
||||
*bp->inPtr = 0;
|
||||
}
|
||||
return (res);
|
||||
}
|
||||
}
|
||||
|
||||
/*-
|
||||
*-----------------------------------------------------------------------
|
||||
* Buf_GetBytes --
|
||||
* Extract a number of bytes from the buffer.
|
||||
*
|
||||
* Results:
|
||||
* The number of bytes gotten.
|
||||
*
|
||||
* Side Effects:
|
||||
* The passed array is overwritten.
|
||||
*
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
int
|
||||
Buf_GetBytes (bp, numBytes, bytesPtr)
|
||||
register Buffer bp;
|
||||
int numBytes;
|
||||
Byte *bytesPtr;
|
||||
{
|
||||
|
||||
if (bp->inPtr - bp->outPtr < numBytes) {
|
||||
numBytes = bp->inPtr - bp->outPtr;
|
||||
}
|
||||
memcpy (bytesPtr, bp->outPtr, numBytes);
|
||||
bp->outPtr += numBytes;
|
||||
|
||||
if (bp->outPtr == bp->inPtr) {
|
||||
bp->outPtr = bp->inPtr = bp->buffer;
|
||||
bp->left = bp->size;
|
||||
*bp->inPtr = 0;
|
||||
}
|
||||
return (numBytes);
|
||||
}
|
||||
|
||||
/*-
|
||||
*-----------------------------------------------------------------------
|
||||
* Buf_GetAll --
|
||||
* Get all the available data at once.
|
||||
*
|
||||
* Results:
|
||||
* A pointer to the data and the number of bytes available.
|
||||
*
|
||||
* Side Effects:
|
||||
* None.
|
||||
*
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
Byte *
|
||||
Buf_GetAll (bp, numBytesPtr)
|
||||
register Buffer bp;
|
||||
int *numBytesPtr;
|
||||
{
|
||||
|
||||
if (numBytesPtr != (int *)NULL) {
|
||||
*numBytesPtr = bp->inPtr - bp->outPtr;
|
||||
}
|
||||
|
||||
return (bp->outPtr);
|
||||
}
|
||||
|
||||
/*-
|
||||
*-----------------------------------------------------------------------
|
||||
* Buf_Discard --
|
||||
* Throw away bytes in a buffer.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
*
|
||||
* Side Effects:
|
||||
* The bytes are discarded.
|
||||
*
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
void
|
||||
Buf_Discard (bp, numBytes)
|
||||
register Buffer bp;
|
||||
int numBytes;
|
||||
{
|
||||
|
||||
if (bp->inPtr - bp->outPtr <= numBytes) {
|
||||
bp->inPtr = bp->outPtr = bp->buffer;
|
||||
bp->left = bp->size;
|
||||
*bp->inPtr = 0;
|
||||
} else {
|
||||
bp->outPtr += numBytes;
|
||||
}
|
||||
}
|
||||
|
||||
/*-
|
||||
*-----------------------------------------------------------------------
|
||||
* Buf_Size --
|
||||
* Returns the number of bytes in the given buffer. Doesn't include
|
||||
* the null-terminating byte.
|
||||
*
|
||||
* Results:
|
||||
* The number of bytes.
|
||||
*
|
||||
* Side Effects:
|
||||
* None.
|
||||
*
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
int
|
||||
Buf_Size (buf)
|
||||
Buffer buf;
|
||||
{
|
||||
return (buf->inPtr - buf->outPtr);
|
||||
}
|
||||
|
||||
/*-
|
||||
*-----------------------------------------------------------------------
|
||||
* Buf_Init --
|
||||
* Initialize a buffer. If no initial size is given, a reasonable
|
||||
* default is used.
|
||||
*
|
||||
* Results:
|
||||
* A buffer to be given to other functions in this library.
|
||||
*
|
||||
* Side Effects:
|
||||
* The buffer is created, the space allocated and pointers
|
||||
* initialized.
|
||||
*
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
Buffer
|
||||
Buf_Init (size)
|
||||
int size; /* Initial size for the buffer */
|
||||
{
|
||||
Buffer bp; /* New Buffer */
|
||||
|
||||
bp = (Buffer)emalloc(sizeof(*bp));
|
||||
|
||||
if (size <= 0) {
|
||||
size = BUF_DEF_SIZE;
|
||||
}
|
||||
bp->left = bp->size = size;
|
||||
bp->buffer = (Byte *)emalloc(size);
|
||||
bp->inPtr = bp->outPtr = bp->buffer;
|
||||
*bp->inPtr = 0;
|
||||
|
||||
return (bp);
|
||||
}
|
||||
|
||||
/*-
|
||||
*-----------------------------------------------------------------------
|
||||
* Buf_Destroy --
|
||||
* Nuke a buffer and all its resources.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
*
|
||||
* Side Effects:
|
||||
* The buffer is freed.
|
||||
*
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
void
|
||||
Buf_Destroy (buf, freeData)
|
||||
Buffer buf; /* Buffer to destroy */
|
||||
Boolean freeData; /* TRUE if the data should be destroyed as well */
|
||||
{
|
||||
|
||||
if (freeData) {
|
||||
free ((char *)buf->buffer);
|
||||
}
|
||||
free ((char *)buf);
|
||||
}
|
80
usr.bin/make/buf.h
Normal file
80
usr.bin/make/buf.h
Normal file
@ -0,0 +1,80 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* @(#)buf.h 8.1 (Berkeley) 6/6/93
|
||||
*/
|
||||
|
||||
/*-
|
||||
* buf.h --
|
||||
* Header for users of the buf library.
|
||||
*/
|
||||
|
||||
#ifndef _BUF_H
|
||||
#define _BUF_H
|
||||
|
||||
#include "sprite.h"
|
||||
|
||||
typedef unsigned char Byte;
|
||||
|
||||
typedef struct Buffer {
|
||||
int size; /* Current size of the buffer */
|
||||
int left; /* Space left (== size - (inPtr - buffer)) */
|
||||
Byte *buffer; /* The buffer itself */
|
||||
Byte *inPtr; /* Place to write to */
|
||||
Byte *outPtr; /* Place to read from */
|
||||
} *Buffer;
|
||||
|
||||
/* Buf_AddByte adds a single byte to a buffer. */
|
||||
#define Buf_AddByte(bp, byte) \
|
||||
(void) (--(bp)->left <= 0 ? Buf_OvAddByte(bp, byte), 1 : \
|
||||
(*(bp)->inPtr++ = (byte), *(bp)->inPtr = 0), 1)
|
||||
|
||||
#define BUF_ERROR 256
|
||||
|
||||
void Buf_AddBytes __P((Buffer, int, Byte *));
|
||||
void Buf_Destroy __P((Buffer, Boolean));
|
||||
void Buf_Discard __P((Buffer, int));
|
||||
Byte *Buf_GetAll __P((Buffer, int *));
|
||||
int Buf_GetByte __P((Buffer));
|
||||
int Buf_GetBytes __P((Buffer, int, Byte *));
|
||||
Buffer Buf_Init __P((int));
|
||||
void Buf_OvAddByte __P((Buffer, int));
|
||||
int Buf_Size __P((Buffer));
|
||||
void Buf_UngetByte __P((Buffer, int));
|
||||
void Buf_UngetBytes __P((Buffer, int, Byte *));
|
||||
|
||||
#endif /* _BUF_H */
|
641
usr.bin/make/compat.c
Normal file
641
usr.bin/make/compat.c
Normal file
@ -0,0 +1,641 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)compat.c 8.2 (Berkeley) 3/19/94";
|
||||
#endif /* not lint */
|
||||
|
||||
/*-
|
||||
* compat.c --
|
||||
* The routines in this file implement the full-compatibility
|
||||
* mode of PMake. Most of the special functionality of PMake
|
||||
* is available in this mode. Things not supported:
|
||||
* - different shells.
|
||||
* - friendly variable substitution.
|
||||
*
|
||||
* Interface:
|
||||
* Compat_Run Initialize things for this module and recreate
|
||||
* thems as need creatin'
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "make.h"
|
||||
#include "hash.h"
|
||||
#include "dir.h"
|
||||
#include "job.h"
|
||||
extern int errno;
|
||||
|
||||
/*
|
||||
* The following array is used to make a fast determination of which
|
||||
* characters are interpreted specially by the shell. If a command
|
||||
* contains any of these characters, it is executed by the shell, not
|
||||
* directly by us.
|
||||
*/
|
||||
|
||||
static char meta[256];
|
||||
|
||||
static GNode *curTarg = NILGNODE;
|
||||
static GNode *ENDNode;
|
||||
static void CompatInterrupt __P((int));
|
||||
static int CompatRunCommand __P((char *, GNode *));
|
||||
static int CompatMake __P((GNode *, GNode *));
|
||||
|
||||
/*-
|
||||
*-----------------------------------------------------------------------
|
||||
* CompatInterrupt --
|
||||
* Interrupt the creation of the current target and remove it if
|
||||
* it ain't precious.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
*
|
||||
* Side Effects:
|
||||
* The target is removed and the process exits. If .INTERRUPT exists,
|
||||
* its commands are run first WITH INTERRUPTS IGNORED..
|
||||
*
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
static void
|
||||
CompatInterrupt (signo)
|
||||
int signo;
|
||||
{
|
||||
struct stat sb;
|
||||
GNode *gn;
|
||||
|
||||
if ((curTarg != NILGNODE) && !Targ_Precious (curTarg)) {
|
||||
char *file = Var_Value (TARGET, curTarg);
|
||||
|
||||
if (!stat(file, &sb) && S_ISREG(sb.st_mode) &&
|
||||
unlink (file) == SUCCESS) {
|
||||
printf ("*** %s removed\n", file);
|
||||
}
|
||||
|
||||
/*
|
||||
* Run .INTERRUPT only if hit with interrupt signal
|
||||
*/
|
||||
if (signo == SIGINT) {
|
||||
gn = Targ_FindNode(".INTERRUPT", TARG_NOCREATE);
|
||||
if (gn != NILGNODE) {
|
||||
Lst_ForEach(gn->commands, CompatRunCommand, (ClientData)gn);
|
||||
}
|
||||
}
|
||||
}
|
||||
exit (0);
|
||||
}
|
||||
|
||||
/*-
|
||||
*-----------------------------------------------------------------------
|
||||
* CompatRunCommand --
|
||||
* Execute the next command for a target. If the command returns an
|
||||
* error, the node's made field is set to ERROR and creation stops.
|
||||
*
|
||||
* Results:
|
||||
* 0 if the command succeeded, 1 if an error occurred.
|
||||
*
|
||||
* Side Effects:
|
||||
* The node's 'made' field may be set to ERROR.
|
||||
*
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
static int
|
||||
CompatRunCommand (cmd, gn)
|
||||
char *cmd; /* Command to execute */
|
||||
GNode *gn; /* Node from which the command came */
|
||||
{
|
||||
char *cmdStart; /* Start of expanded command */
|
||||
register char *cp;
|
||||
Boolean silent, /* Don't print command */
|
||||
errCheck; /* Check errors */
|
||||
union wait reason; /* Reason for child's death */
|
||||
int status; /* Description of child's death */
|
||||
int cpid; /* Child actually found */
|
||||
ReturnStatus stat; /* Status of fork */
|
||||
LstNode cmdNode; /* Node where current command is located */
|
||||
char **av; /* Argument vector for thing to exec */
|
||||
int argc; /* Number of arguments in av or 0 if not
|
||||
* dynamically allocated */
|
||||
Boolean local; /* TRUE if command should be executed
|
||||
* locally */
|
||||
|
||||
/*
|
||||
* Avoid clobbered variable warnings by forcing the compiler
|
||||
* to ``unregister'' variables
|
||||
*/
|
||||
#if __GNUC__
|
||||
(void) &av;
|
||||
(void) &errCheck;
|
||||
#endif
|
||||
|
||||
silent = gn->type & OP_SILENT;
|
||||
errCheck = !(gn->type & OP_IGNORE);
|
||||
|
||||
cmdNode = Lst_Member (gn->commands, (ClientData)cmd);
|
||||
cmdStart = Var_Subst (NULL, cmd, gn, FALSE);
|
||||
|
||||
/*
|
||||
* brk_string will return an argv with a NULL in av[1], thus causing
|
||||
* execvp to choke and die horribly. Besides, how can we execute a null
|
||||
* command? In any case, we warn the user that the command expanded to
|
||||
* nothing (is this the right thing to do?).
|
||||
*/
|
||||
|
||||
if (*cmdStart == '\0') {
|
||||
Error("%s expands to empty string", cmd);
|
||||
return(0);
|
||||
} else {
|
||||
cmd = cmdStart;
|
||||
}
|
||||
Lst_Replace (cmdNode, (ClientData)cmdStart);
|
||||
|
||||
if ((gn->type & OP_SAVE_CMDS) && (gn != ENDNode)) {
|
||||
(void)Lst_AtEnd(ENDNode->commands, (ClientData)cmdStart);
|
||||
return(0);
|
||||
} else if (strcmp(cmdStart, "...") == 0) {
|
||||
gn->type |= OP_SAVE_CMDS;
|
||||
return(0);
|
||||
}
|
||||
|
||||
while ((*cmd == '@') || (*cmd == '-')) {
|
||||
if (*cmd == '@') {
|
||||
silent = TRUE;
|
||||
} else {
|
||||
errCheck = FALSE;
|
||||
}
|
||||
cmd++;
|
||||
}
|
||||
|
||||
while (isspace((unsigned char)*cmd))
|
||||
cmd++;
|
||||
|
||||
/*
|
||||
* Search for meta characters in the command. If there are no meta
|
||||
* characters, there's no need to execute a shell to execute the
|
||||
* command.
|
||||
*/
|
||||
for (cp = cmd; !meta[(unsigned char)*cp]; cp++) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Print the command before echoing if we're not supposed to be quiet for
|
||||
* this one. We also print the command if -n given.
|
||||
*/
|
||||
if (!silent || noExecute) {
|
||||
printf ("%s\n", cmd);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
/*
|
||||
* If we're not supposed to execute any commands, this is as far as
|
||||
* we go...
|
||||
*/
|
||||
if (noExecute) {
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (*cp != '\0') {
|
||||
/*
|
||||
* If *cp isn't the null character, we hit a "meta" character and
|
||||
* need to pass the command off to the shell. We give the shell the
|
||||
* -e flag as well as -c if it's supposed to exit when it hits an
|
||||
* error.
|
||||
*/
|
||||
static char *shargv[4] = { "/bin/sh" };
|
||||
|
||||
shargv[1] = (errCheck ? "-ec" : "-c");
|
||||
shargv[2] = cmd;
|
||||
shargv[3] = (char *)NULL;
|
||||
av = shargv;
|
||||
argc = 0;
|
||||
} else {
|
||||
/*
|
||||
* No meta-characters, so no need to exec a shell. Break the command
|
||||
* into words to form an argument vector we can execute.
|
||||
* brk_string sticks our name in av[0], so we have to
|
||||
* skip over it...
|
||||
*/
|
||||
av = brk_string(cmd, &argc);
|
||||
av += 1;
|
||||
}
|
||||
|
||||
local = TRUE;
|
||||
|
||||
/*
|
||||
* Fork and execute the single command. If the fork fails, we abort.
|
||||
*/
|
||||
cpid = vfork();
|
||||
if (cpid < 0) {
|
||||
Fatal("Could not fork");
|
||||
}
|
||||
if (cpid == 0) {
|
||||
if (local) {
|
||||
execvp(av[0], av);
|
||||
(void) write (2, av[0], strlen (av[0]));
|
||||
(void) write (2, ": not found\n", sizeof(": not found"));
|
||||
} else {
|
||||
(void)execv(av[0], av);
|
||||
}
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* The child is off and running. Now all we can do is wait...
|
||||
*/
|
||||
while (1) {
|
||||
int id;
|
||||
|
||||
if (!local) {
|
||||
id = 0;
|
||||
}
|
||||
|
||||
while ((stat = wait((int *)&reason)) != cpid) {
|
||||
if (stat == -1 && errno != EINTR) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (stat > -1) {
|
||||
if (WIFSTOPPED(reason)) {
|
||||
status = reason.w_stopval; /* stopped */
|
||||
} else if (WIFEXITED(reason)) {
|
||||
status = reason.w_retcode; /* exited */
|
||||
if (status != 0) {
|
||||
printf ("*** Error code %d", status);
|
||||
}
|
||||
} else {
|
||||
status = reason.w_termsig; /* signaled */
|
||||
printf ("*** Signal %d", status);
|
||||
}
|
||||
|
||||
|
||||
if (!WIFEXITED(reason) || (status != 0)) {
|
||||
if (errCheck) {
|
||||
gn->made = ERROR;
|
||||
if (keepgoing) {
|
||||
/*
|
||||
* Abort the current target, but let others
|
||||
* continue.
|
||||
*/
|
||||
printf (" (continuing)\n");
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* Continue executing commands for this target.
|
||||
* If we return 0, this will happen...
|
||||
*/
|
||||
printf (" (ignored)\n");
|
||||
status = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
Fatal ("error in wait: %d", stat);
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
}
|
||||
|
||||
return (status);
|
||||
}
|
||||
|
||||
/*-
|
||||
*-----------------------------------------------------------------------
|
||||
* CompatMake --
|
||||
* Make a target.
|
||||
*
|
||||
* Results:
|
||||
* 0
|
||||
*
|
||||
* Side Effects:
|
||||
* If an error is detected and not being ignored, the process exits.
|
||||
*
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
static int
|
||||
CompatMake (gn, pgn)
|
||||
GNode *gn; /* The node to make */
|
||||
GNode *pgn; /* Parent to abort if necessary */
|
||||
{
|
||||
if (gn->type & OP_USE) {
|
||||
Make_HandleUse(gn, pgn);
|
||||
} else if (gn->made == UNMADE) {
|
||||
/*
|
||||
* First mark ourselves to be made, then apply whatever transformations
|
||||
* the suffix module thinks are necessary. Once that's done, we can
|
||||
* descend and make all our children. If any of them has an error
|
||||
* but the -k flag was given, our 'make' field will be set FALSE again.
|
||||
* This is our signal to not attempt to do anything but abort our
|
||||
* parent as well.
|
||||
*/
|
||||
gn->make = TRUE;
|
||||
gn->made = BEINGMADE;
|
||||
Suff_FindDeps (gn);
|
||||
Lst_ForEach (gn->children, CompatMake, (ClientData)gn);
|
||||
if (!gn->make) {
|
||||
gn->made = ABORTED;
|
||||
pgn->make = FALSE;
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (Lst_Member (gn->iParents, pgn) != NILLNODE) {
|
||||
Var_Set (IMPSRC, Var_Value(TARGET, gn), pgn);
|
||||
}
|
||||
|
||||
/*
|
||||
* All the children were made ok. Now cmtime contains the modification
|
||||
* time of the newest child, we need to find out if we exist and when
|
||||
* we were modified last. The criteria for datedness are defined by the
|
||||
* Make_OODate function.
|
||||
*/
|
||||
if (DEBUG(MAKE)) {
|
||||
printf("Examining %s...", gn->name);
|
||||
}
|
||||
if (! Make_OODate(gn)) {
|
||||
gn->made = UPTODATE;
|
||||
if (DEBUG(MAKE)) {
|
||||
printf("up-to-date.\n");
|
||||
}
|
||||
return (0);
|
||||
} else if (DEBUG(MAKE)) {
|
||||
printf("out-of-date.\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* If the user is just seeing if something is out-of-date, exit now
|
||||
* to tell him/her "yes".
|
||||
*/
|
||||
if (queryFlag) {
|
||||
exit (-1);
|
||||
}
|
||||
|
||||
/*
|
||||
* We need to be re-made. We also have to make sure we've got a $?
|
||||
* variable. To be nice, we also define the $> variable using
|
||||
* Make_DoAllVar().
|
||||
*/
|
||||
Make_DoAllVar(gn);
|
||||
|
||||
/*
|
||||
* Alter our type to tell if errors should be ignored or things
|
||||
* should not be printed so CompatRunCommand knows what to do.
|
||||
*/
|
||||
if (Targ_Ignore (gn)) {
|
||||
gn->type |= OP_IGNORE;
|
||||
}
|
||||
if (Targ_Silent (gn)) {
|
||||
gn->type |= OP_SILENT;
|
||||
}
|
||||
|
||||
if (Job_CheckCommands (gn, Fatal)) {
|
||||
/*
|
||||
* Our commands are ok, but we still have to worry about the -t
|
||||
* flag...
|
||||
*/
|
||||
if (!touchFlag) {
|
||||
curTarg = gn;
|
||||
Lst_ForEach (gn->commands, CompatRunCommand, (ClientData)gn);
|
||||
curTarg = NILGNODE;
|
||||
} else {
|
||||
Job_Touch (gn, gn->type & OP_SILENT);
|
||||
}
|
||||
} else {
|
||||
gn->made = ERROR;
|
||||
}
|
||||
|
||||
if (gn->made != ERROR) {
|
||||
/*
|
||||
* If the node was made successfully, mark it so, update
|
||||
* its modification time and timestamp all its parents. Note
|
||||
* that for .ZEROTIME targets, the timestamping isn't done.
|
||||
* This is to keep its state from affecting that of its parent.
|
||||
*/
|
||||
gn->made = MADE;
|
||||
#ifndef RECHECK
|
||||
/*
|
||||
* We can't re-stat the thing, but we can at least take care of
|
||||
* rules where a target depends on a source that actually creates
|
||||
* the target, but only if it has changed, e.g.
|
||||
*
|
||||
* parse.h : parse.o
|
||||
*
|
||||
* parse.o : parse.y
|
||||
* yacc -d parse.y
|
||||
* cc -c y.tab.c
|
||||
* mv y.tab.o parse.o
|
||||
* cmp -s y.tab.h parse.h || mv y.tab.h parse.h
|
||||
*
|
||||
* In this case, if the definitions produced by yacc haven't
|
||||
* changed from before, parse.h won't have been updated and
|
||||
* gn->mtime will reflect the current modification time for
|
||||
* parse.h. This is something of a kludge, I admit, but it's a
|
||||
* useful one..
|
||||
*
|
||||
* XXX: People like to use a rule like
|
||||
*
|
||||
* FRC:
|
||||
*
|
||||
* To force things that depend on FRC to be made, so we have to
|
||||
* check for gn->children being empty as well...
|
||||
*/
|
||||
if (!Lst_IsEmpty(gn->commands) || Lst_IsEmpty(gn->children)) {
|
||||
gn->mtime = now;
|
||||
}
|
||||
#else
|
||||
/*
|
||||
* This is what Make does and it's actually a good thing, as it
|
||||
* allows rules like
|
||||
*
|
||||
* cmp -s y.tab.h parse.h || cp y.tab.h parse.h
|
||||
*
|
||||
* to function as intended. Unfortunately, thanks to the stateless
|
||||
* nature of NFS (and the speed of this program), there are times
|
||||
* when the modification time of a file created on a remote
|
||||
* machine will not be modified before the stat() implied by
|
||||
* the Dir_MTime occurs, thus leading us to believe that the file
|
||||
* is unchanged, wreaking havoc with files that depend on this one.
|
||||
*
|
||||
* I have decided it is better to make too much than to make too
|
||||
* little, so this stuff is commented out unless you're sure it's
|
||||
* ok.
|
||||
* -- ardeb 1/12/88
|
||||
*/
|
||||
if (noExecute || Dir_MTime(gn) == 0) {
|
||||
gn->mtime = now;
|
||||
}
|
||||
if (gn->cmtime > gn->mtime)
|
||||
gn->mtime = gn->cmtime;
|
||||
if (DEBUG(MAKE)) {
|
||||
printf("update time: %s\n", Targ_FmtTime(gn->mtime));
|
||||
}
|
||||
#endif
|
||||
if (!(gn->type & OP_EXEC)) {
|
||||
pgn->childMade = TRUE;
|
||||
Make_TimeStamp(pgn, gn);
|
||||
}
|
||||
} else if (keepgoing) {
|
||||
pgn->make = FALSE;
|
||||
} else {
|
||||
printf ("\n\nStop.\n");
|
||||
exit (1);
|
||||
}
|
||||
} else if (gn->made == ERROR) {
|
||||
/*
|
||||
* Already had an error when making this beastie. Tell the parent
|
||||
* to abort.
|
||||
*/
|
||||
pgn->make = FALSE;
|
||||
} else {
|
||||
if (Lst_Member (gn->iParents, pgn) != NILLNODE) {
|
||||
Var_Set (IMPSRC, Var_Value(TARGET, gn), pgn);
|
||||
}
|
||||
switch(gn->made) {
|
||||
case BEINGMADE:
|
||||
Error("Graph cycles through %s\n", gn->name);
|
||||
gn->made = ERROR;
|
||||
pgn->make = FALSE;
|
||||
break;
|
||||
case MADE:
|
||||
if ((gn->type & OP_EXEC) == 0) {
|
||||
pgn->childMade = TRUE;
|
||||
Make_TimeStamp(pgn, gn);
|
||||
}
|
||||
break;
|
||||
case UPTODATE:
|
||||
if ((gn->type & OP_EXEC) == 0) {
|
||||
Make_TimeStamp(pgn, gn);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*-
|
||||
*-----------------------------------------------------------------------
|
||||
* Compat_Run --
|
||||
* Initialize this mode and start making.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
*
|
||||
* Side Effects:
|
||||
* Guess what?
|
||||
*
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
void
|
||||
Compat_Run(targs)
|
||||
Lst targs; /* List of target nodes to re-create */
|
||||
{
|
||||
char *cp; /* Pointer to string of shell meta-characters */
|
||||
GNode *gn = NULL;/* Current root target */
|
||||
int errors; /* Number of targets not remade due to errors */
|
||||
|
||||
if (signal(SIGINT, SIG_IGN) != SIG_IGN) {
|
||||
signal(SIGINT, CompatInterrupt);
|
||||
}
|
||||
if (signal(SIGTERM, SIG_IGN) != SIG_IGN) {
|
||||
signal(SIGTERM, CompatInterrupt);
|
||||
}
|
||||
if (signal(SIGHUP, SIG_IGN) != SIG_IGN) {
|
||||
signal(SIGHUP, CompatInterrupt);
|
||||
}
|
||||
if (signal(SIGQUIT, SIG_IGN) != SIG_IGN) {
|
||||
signal(SIGQUIT, CompatInterrupt);
|
||||
}
|
||||
|
||||
for (cp = "#=|^(){};&<>*?[]:$`\\\n"; *cp != '\0'; cp++) {
|
||||
meta[(unsigned char) *cp] = 1;
|
||||
}
|
||||
/*
|
||||
* The null character serves as a sentinel in the string.
|
||||
*/
|
||||
meta[0] = 1;
|
||||
|
||||
ENDNode = Targ_FindNode(".END", TARG_CREATE);
|
||||
/*
|
||||
* If the user has defined a .BEGIN target, execute the commands attached
|
||||
* to it.
|
||||
*/
|
||||
if (!queryFlag) {
|
||||
gn = Targ_FindNode(".BEGIN", TARG_NOCREATE);
|
||||
if (gn != NILGNODE) {
|
||||
Lst_ForEach(gn->commands, CompatRunCommand, (ClientData)gn);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* For each entry in the list of targets to create, call CompatMake on
|
||||
* it to create the thing. CompatMake will leave the 'made' field of gn
|
||||
* in one of several states:
|
||||
* UPTODATE gn was already up-to-date
|
||||
* MADE gn was recreated successfully
|
||||
* ERROR An error occurred while gn was being created
|
||||
* ABORTED gn was not remade because one of its inferiors
|
||||
* could not be made due to errors.
|
||||
*/
|
||||
errors = 0;
|
||||
while (!Lst_IsEmpty (targs)) {
|
||||
gn = (GNode *) Lst_DeQueue (targs);
|
||||
CompatMake (gn, gn);
|
||||
|
||||
if (gn->made == UPTODATE) {
|
||||
printf ("`%s' is up to date.\n", gn->name);
|
||||
} else if (gn->made == ABORTED) {
|
||||
printf ("`%s' not remade because of errors.\n", gn->name);
|
||||
errors += 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If the user has defined a .END target, run its commands.
|
||||
*/
|
||||
if (errors == 0) {
|
||||
Lst_ForEach(ENDNode->commands, CompatRunCommand, (ClientData)gn);
|
||||
}
|
||||
}
|
1247
usr.bin/make/cond.c
Normal file
1247
usr.bin/make/cond.c
Normal file
File diff suppressed because it is too large
Load Diff
92
usr.bin/make/config.h
Normal file
92
usr.bin/make/config.h
Normal file
@ -0,0 +1,92 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* @(#)config.h 8.1 (Berkeley) 6/6/93
|
||||
*/
|
||||
|
||||
#define DEFSHELL 1 /* Bourne shell */
|
||||
|
||||
/*
|
||||
* DEFMAXJOBS
|
||||
* DEFMAXLOCAL
|
||||
* These control the default concurrency. On no occasion will more
|
||||
* than DEFMAXJOBS targets be created at once (locally or remotely)
|
||||
* DEFMAXLOCAL is the highest number of targets which will be
|
||||
* created on the local machine at once. Note that if you set this
|
||||
* to 0, nothing will ever happen...
|
||||
*/
|
||||
#define DEFMAXJOBS 4
|
||||
#define DEFMAXLOCAL 1
|
||||
|
||||
/*
|
||||
* INCLUDES
|
||||
* LIBRARIES
|
||||
* These control the handling of the .INCLUDES and .LIBS variables.
|
||||
* If INCLUDES is defined, the .INCLUDES variable will be filled
|
||||
* from the search paths of those suffixes which are marked by
|
||||
* .INCLUDES dependency lines. Similarly for LIBRARIES and .LIBS
|
||||
* See suff.c for more details.
|
||||
*/
|
||||
#define INCLUDES
|
||||
#define LIBRARIES
|
||||
|
||||
/*
|
||||
* LIBSUFF
|
||||
* Is the suffix used to denote libraries and is used by the Suff module
|
||||
* to find the search path on which to seek any -l<xx> targets.
|
||||
*
|
||||
* RECHECK
|
||||
* If defined, Make_Update will check a target for its current
|
||||
* modification time after it has been re-made, setting it to the
|
||||
* starting time of the make only if the target still doesn't exist.
|
||||
* Unfortunately, under NFS the modification time often doesn't
|
||||
* get updated in time, so a target will appear to not have been
|
||||
* 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"
|
||||
#endif
|
||||
/*#define POSIX*/
|
1238
usr.bin/make/dir.c
Normal file
1238
usr.bin/make/dir.c
Normal file
File diff suppressed because it is too large
Load Diff
70
usr.bin/make/dir.h
Normal file
70
usr.bin/make/dir.h
Normal file
@ -0,0 +1,70 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* @(#)dir.h 8.1 (Berkeley) 6/6/93
|
||||
*/
|
||||
|
||||
/* dir.h --
|
||||
*/
|
||||
|
||||
#ifndef _DIR
|
||||
#define _DIR
|
||||
|
||||
typedef struct Path {
|
||||
char *name; /* Name of directory */
|
||||
int refCount; /* Number of paths with this directory */
|
||||
int hits; /* the number of times a file in this
|
||||
* directory has been found */
|
||||
Hash_Table files; /* Hash table of files in directory */
|
||||
} Path;
|
||||
|
||||
void Dir_AddDir __P((Lst, char *));
|
||||
void Dir_ClearPath __P((Lst));
|
||||
void Dir_Concat __P((Lst, Lst));
|
||||
ClientData
|
||||
Dir_CopyDir __P((Path *));
|
||||
void Dir_Destroy __P((Path *));
|
||||
void Dir_Expand __P((char *, Lst, Lst));
|
||||
char *Dir_FindFile __P((char *, Lst));
|
||||
Boolean Dir_HasWildcards __P((char *));
|
||||
void Dir_Init __P((void));
|
||||
char *Dir_MakeFlags __P((char *, Lst));
|
||||
int Dir_MTime __P((GNode *));
|
||||
void Dir_PrintDirectories __P((void));
|
||||
void Dir_PrintPath __P((Lst));
|
||||
|
||||
#endif /* _DIR */
|
296
usr.bin/make/for.c
Normal file
296
usr.bin/make/for.c
Normal file
@ -0,0 +1,296 @@
|
||||
/*
|
||||
* Copyright (c) 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Christos Zoulas.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)for.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif /* not lint */
|
||||
|
||||
/*-
|
||||
* for.c --
|
||||
* Functions to handle loops in a makefile.
|
||||
*
|
||||
* Interface:
|
||||
* For_Eval Evaluate the loop in the passed line.
|
||||
* For_Run Run accumulated loop
|
||||
*
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
#include "make.h"
|
||||
#include "hash.h"
|
||||
#include "dir.h"
|
||||
#include "buf.h"
|
||||
|
||||
/*
|
||||
* For statements are of the form:
|
||||
*
|
||||
* .for <variable> in <varlist>
|
||||
* ...
|
||||
* .endfor
|
||||
*
|
||||
* The trick is to look for the matching end inside for for loop
|
||||
* To do that, we count the current nesting level of the for loops.
|
||||
* and the .endfor statements, accumulating all the statements between
|
||||
* the initial .for loop and the matching .endfor;
|
||||
* then we evaluate the for loop for each variable in the varlist.
|
||||
*/
|
||||
|
||||
static int forLevel = 0; /* Nesting level */
|
||||
static char *forVar; /* Iteration variable */
|
||||
static Buffer forBuf; /* Commands in loop */
|
||||
static Lst forLst; /* List of items */
|
||||
|
||||
/*
|
||||
* State of a for loop.
|
||||
*/
|
||||
struct For {
|
||||
Buffer buf; /* Unexpanded buffer */
|
||||
char* var; /* Index name */
|
||||
Lst lst; /* List of variables */
|
||||
};
|
||||
|
||||
static int ForExec __P((char *, struct For *));
|
||||
|
||||
|
||||
|
||||
|
||||
/*-
|
||||
*-----------------------------------------------------------------------
|
||||
* For_Eval --
|
||||
* Evaluate the for loop in the passed line. The line
|
||||
* looks like this:
|
||||
* .for <variable> in <varlist>
|
||||
*
|
||||
* Results:
|
||||
* TRUE: We found a for loop, or we are inside a for loop
|
||||
* FALSE: We did not find a for loop, or we found the end of the for
|
||||
* for loop.
|
||||
*
|
||||
* Side Effects:
|
||||
* None.
|
||||
*
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
int
|
||||
For_Eval (line)
|
||||
char *line; /* Line to parse */
|
||||
{
|
||||
char *ptr = line, *sub, *wrd;
|
||||
int level; /* Level at which to report errors. */
|
||||
|
||||
level = PARSE_FATAL;
|
||||
|
||||
|
||||
if (forLevel == 0) {
|
||||
Buffer buf;
|
||||
int varlen;
|
||||
|
||||
for (ptr++; *ptr && isspace(*ptr); ptr++)
|
||||
continue;
|
||||
/*
|
||||
* If we are not in a for loop quickly determine if the statement is
|
||||
* a for.
|
||||
*/
|
||||
if (ptr[0] != 'f' || ptr[1] != 'o' || ptr[2] != 'r' || !isspace(ptr[3]))
|
||||
return FALSE;
|
||||
ptr += 3;
|
||||
|
||||
/*
|
||||
* we found a for loop, and now we are going to parse it.
|
||||
*/
|
||||
while (*ptr && isspace(*ptr))
|
||||
ptr++;
|
||||
|
||||
/*
|
||||
* Grab the variable
|
||||
*/
|
||||
buf = Buf_Init(0);
|
||||
for (wrd = ptr; *ptr && !isspace(*ptr); ptr++)
|
||||
continue;
|
||||
Buf_AddBytes(buf, ptr - wrd, (Byte *) wrd);
|
||||
|
||||
forVar = (char *) Buf_GetAll(buf, &varlen);
|
||||
if (varlen == 0) {
|
||||
Parse_Error (level, "missing variable in for");
|
||||
return 0;
|
||||
}
|
||||
Buf_Destroy(buf, FALSE);
|
||||
|
||||
while (*ptr && isspace(*ptr))
|
||||
ptr++;
|
||||
|
||||
/*
|
||||
* Grab the `in'
|
||||
*/
|
||||
if (ptr[0] != 'i' || ptr[1] != 'n' || !isspace(ptr[2])) {
|
||||
Parse_Error (level, "missing `in' in for");
|
||||
printf("%s\n", ptr);
|
||||
return 0;
|
||||
}
|
||||
ptr += 3;
|
||||
|
||||
while (*ptr && isspace(*ptr))
|
||||
ptr++;
|
||||
|
||||
/*
|
||||
* Make a list with the remaining words
|
||||
*/
|
||||
forLst = Lst_Init(FALSE);
|
||||
buf = Buf_Init(0);
|
||||
sub = Var_Subst(NULL, ptr, VAR_GLOBAL, FALSE);
|
||||
|
||||
#define ADDWORD() \
|
||||
Buf_AddBytes(buf, ptr - wrd, (Byte *) wrd), \
|
||||
Buf_AddByte(buf, (Byte) '\0'), \
|
||||
Lst_AtEnd(forLst, (ClientData) Buf_GetAll(buf, &varlen)), \
|
||||
Buf_Destroy(buf, FALSE)
|
||||
|
||||
for (ptr = sub; *ptr && isspace(*ptr); ptr++)
|
||||
continue;
|
||||
|
||||
for (wrd = ptr; *ptr; ptr++)
|
||||
if (isspace(*ptr)) {
|
||||
ADDWORD();
|
||||
buf = Buf_Init(0);
|
||||
while (*ptr && isspace(*ptr))
|
||||
ptr++;
|
||||
wrd = ptr--;
|
||||
}
|
||||
if (DEBUG(FOR))
|
||||
(void) fprintf(stderr, "For: Iterator %s List %s\n", forVar, sub);
|
||||
if (ptr - wrd > 0)
|
||||
ADDWORD();
|
||||
else
|
||||
Buf_Destroy(buf, TRUE);
|
||||
free((Address) sub);
|
||||
|
||||
forBuf = Buf_Init(0);
|
||||
forLevel++;
|
||||
return 1;
|
||||
}
|
||||
else if (*ptr == '.') {
|
||||
|
||||
for (ptr++; *ptr && isspace(*ptr); ptr++)
|
||||
continue;
|
||||
|
||||
if (strncmp(ptr, "endfor", 6) == 0 && (isspace(ptr[6]) || !ptr[6])) {
|
||||
if (DEBUG(FOR))
|
||||
(void) fprintf(stderr, "For: end for %d\n", forLevel);
|
||||
if (--forLevel < 0) {
|
||||
Parse_Error (level, "for-less endfor");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else if (strncmp(ptr, "for", 3) == 0 && isspace(ptr[3])) {
|
||||
forLevel++;
|
||||
if (DEBUG(FOR))
|
||||
(void) fprintf(stderr, "For: new loop %d\n", forLevel);
|
||||
}
|
||||
}
|
||||
|
||||
if (forLevel != 0) {
|
||||
Buf_AddBytes(forBuf, strlen(line), (Byte *) line);
|
||||
Buf_AddByte(forBuf, (Byte) '\n');
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*-
|
||||
*-----------------------------------------------------------------------
|
||||
* ForExec --
|
||||
* Expand the for loop for this index and push it in the Makefile
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
*
|
||||
* Side Effects:
|
||||
* None.
|
||||
*
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
static int
|
||||
ForExec(name, arg)
|
||||
char *name;
|
||||
struct For *arg;
|
||||
{
|
||||
int len;
|
||||
Var_Set(arg->var, name, VAR_GLOBAL);
|
||||
if (DEBUG(FOR))
|
||||
(void) fprintf(stderr, "--- %s = %s\n", arg->var, name);
|
||||
Parse_FromString(Var_Subst(arg->var, (char *) Buf_GetAll(arg->buf, &len),
|
||||
VAR_GLOBAL, FALSE));
|
||||
Var_Delete(arg->var, VAR_GLOBAL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*-
|
||||
*-----------------------------------------------------------------------
|
||||
* For_Run --
|
||||
* Run the for loop, immitating the actions of an include file
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
*
|
||||
* Side Effects:
|
||||
* None.
|
||||
*
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
void
|
||||
For_Run()
|
||||
{
|
||||
struct For arg;
|
||||
|
||||
if (forVar == NULL || forBuf == NULL || forLst == NULL)
|
||||
return;
|
||||
arg.var = forVar;
|
||||
arg.buf = forBuf;
|
||||
arg.lst = forLst;
|
||||
forVar = NULL;
|
||||
forBuf = NULL;
|
||||
forLst = NULL;
|
||||
|
||||
Lst_ForEach(arg.lst, ForExec, (ClientData) &arg);
|
||||
|
||||
free((Address)arg.var);
|
||||
Lst_Destroy(arg.lst, free);
|
||||
Buf_Destroy(arg.buf, TRUE);
|
||||
}
|
418
usr.bin/make/hash.c
Normal file
418
usr.bin/make/hash.c
Normal file
@ -0,0 +1,418 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)hash.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif /* not lint */
|
||||
|
||||
/* hash.c --
|
||||
*
|
||||
* This module contains routines to manipulate a hash table.
|
||||
* See hash.h for a definition of the structure of the hash
|
||||
* table. Hash tables grow automatically as the amount of
|
||||
* information increases.
|
||||
*/
|
||||
#include "sprite.h"
|
||||
#include "make.h"
|
||||
#include "hash.h"
|
||||
|
||||
/*
|
||||
* Forward references to local procedures that are used before they're
|
||||
* defined:
|
||||
*/
|
||||
|
||||
static void RebuildTable __P((Hash_Table *));
|
||||
|
||||
/*
|
||||
* The following defines the ratio of # entries to # buckets
|
||||
* at which we rebuild the table to make it larger.
|
||||
*/
|
||||
|
||||
#define rebuildLimit 8
|
||||
|
||||
/*
|
||||
*---------------------------------------------------------
|
||||
*
|
||||
* Hash_InitTable --
|
||||
*
|
||||
* This routine just sets up the hash table.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
*
|
||||
* Side Effects:
|
||||
* Memory is allocated for the initial bucket area.
|
||||
*
|
||||
*---------------------------------------------------------
|
||||
*/
|
||||
|
||||
void
|
||||
Hash_InitTable(t, numBuckets)
|
||||
register Hash_Table *t; /* Structure to use to hold table. */
|
||||
int numBuckets; /* How many buckets to create for starters.
|
||||
* This number is rounded up to a power of
|
||||
* two. If <= 0, a reasonable default is
|
||||
* chosen. The table will grow in size later
|
||||
* as needed. */
|
||||
{
|
||||
register int i;
|
||||
register struct Hash_Entry **hp;
|
||||
|
||||
/*
|
||||
* Round up the size to a power of two.
|
||||
*/
|
||||
if (numBuckets <= 0)
|
||||
i = 16;
|
||||
else {
|
||||
for (i = 2; i < numBuckets; i <<= 1)
|
||||
continue;
|
||||
}
|
||||
t->numEntries = 0;
|
||||
t->size = i;
|
||||
t->mask = i - 1;
|
||||
t->bucketPtr = hp = (struct Hash_Entry **)emalloc(sizeof(*hp) * i);
|
||||
while (--i >= 0)
|
||||
*hp++ = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
*---------------------------------------------------------
|
||||
*
|
||||
* Hash_DeleteTable --
|
||||
*
|
||||
* This routine removes everything from a hash table
|
||||
* and frees up the memory space it occupied (except for
|
||||
* the space in the Hash_Table structure).
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
*
|
||||
* Side Effects:
|
||||
* Lots of memory is freed up.
|
||||
*
|
||||
*---------------------------------------------------------
|
||||
*/
|
||||
|
||||
void
|
||||
Hash_DeleteTable(t)
|
||||
Hash_Table *t;
|
||||
{
|
||||
register struct Hash_Entry **hp, *h, *nexth = NULL;
|
||||
register int i;
|
||||
|
||||
for (hp = t->bucketPtr, i = t->size; --i >= 0;) {
|
||||
for (h = *hp++; h != NULL; h = nexth) {
|
||||
nexth = h->next;
|
||||
free((char *)h);
|
||||
}
|
||||
}
|
||||
free((char *)t->bucketPtr);
|
||||
|
||||
/*
|
||||
* Set up the hash table to cause memory faults on any future access
|
||||
* attempts until re-initialization.
|
||||
*/
|
||||
t->bucketPtr = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
*---------------------------------------------------------
|
||||
*
|
||||
* Hash_FindEntry --
|
||||
*
|
||||
* Searches a hash table for an entry corresponding to key.
|
||||
*
|
||||
* Results:
|
||||
* The return value is a pointer to the entry for key,
|
||||
* if key was present in the table. If key was not
|
||||
* present, NULL is returned.
|
||||
*
|
||||
* Side Effects:
|
||||
* None.
|
||||
*
|
||||
*---------------------------------------------------------
|
||||
*/
|
||||
|
||||
Hash_Entry *
|
||||
Hash_FindEntry(t, key)
|
||||
Hash_Table *t; /* Hash table to search. */
|
||||
char *key; /* A hash key. */
|
||||
{
|
||||
register Hash_Entry *e;
|
||||
register unsigned h;
|
||||
register char *p;
|
||||
|
||||
for (h = 0, p = key; *p;)
|
||||
h = (h << 5) - h + *p++;
|
||||
p = key;
|
||||
for (e = t->bucketPtr[h & t->mask]; e != NULL; e = e->next)
|
||||
if (e->namehash == h && strcmp(e->name, p) == 0)
|
||||
return (e);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
*---------------------------------------------------------
|
||||
*
|
||||
* Hash_CreateEntry --
|
||||
*
|
||||
* Searches a hash table for an entry corresponding to
|
||||
* key. If no entry is found, then one is created.
|
||||
*
|
||||
* Results:
|
||||
* The return value is a pointer to the entry. If *newPtr
|
||||
* isn't NULL, then *newPtr is filled in with TRUE if a
|
||||
* new entry was created, and FALSE if an entry already existed
|
||||
* with the given key.
|
||||
*
|
||||
* Side Effects:
|
||||
* Memory may be allocated, and the hash buckets may be modified.
|
||||
*---------------------------------------------------------
|
||||
*/
|
||||
|
||||
Hash_Entry *
|
||||
Hash_CreateEntry(t, key, newPtr)
|
||||
register Hash_Table *t; /* Hash table to search. */
|
||||
char *key; /* A hash key. */
|
||||
Boolean *newPtr; /* Filled in with TRUE if new entry created,
|
||||
* FALSE otherwise. */
|
||||
{
|
||||
register Hash_Entry *e;
|
||||
register unsigned h;
|
||||
register char *p;
|
||||
int keylen;
|
||||
struct Hash_Entry **hp;
|
||||
|
||||
/*
|
||||
* Hash the key. As a side effect, save the length (strlen) of the
|
||||
* key in case we need to create the entry.
|
||||
*/
|
||||
for (h = 0, p = key; *p;)
|
||||
h = (h << 5) - h + *p++;
|
||||
keylen = p - key;
|
||||
p = key;
|
||||
for (e = t->bucketPtr[h & t->mask]; e != NULL; e = e->next) {
|
||||
if (e->namehash == h && strcmp(e->name, p) == 0) {
|
||||
if (newPtr != NULL)
|
||||
*newPtr = FALSE;
|
||||
return (e);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The desired entry isn't there. Before allocating a new entry,
|
||||
* expand the table if necessary (and this changes the resulting
|
||||
* bucket chain).
|
||||
*/
|
||||
if (t->numEntries >= rebuildLimit * t->size)
|
||||
RebuildTable(t);
|
||||
e = (Hash_Entry *) emalloc(sizeof(*e) + keylen);
|
||||
hp = &t->bucketPtr[h & t->mask];
|
||||
e->next = *hp;
|
||||
*hp = e;
|
||||
e->clientData = NULL;
|
||||
e->namehash = h;
|
||||
(void) strcpy(e->name, p);
|
||||
t->numEntries++;
|
||||
|
||||
if (newPtr != NULL)
|
||||
*newPtr = TRUE;
|
||||
return (e);
|
||||
}
|
||||
|
||||
/*
|
||||
*---------------------------------------------------------
|
||||
*
|
||||
* Hash_DeleteEntry --
|
||||
*
|
||||
* Delete the given hash table entry and free memory associated with
|
||||
* it.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
*
|
||||
* Side Effects:
|
||||
* Hash chain that entry lives in is modified and memory is freed.
|
||||
*
|
||||
*---------------------------------------------------------
|
||||
*/
|
||||
|
||||
void
|
||||
Hash_DeleteEntry(t, e)
|
||||
Hash_Table *t;
|
||||
Hash_Entry *e;
|
||||
{
|
||||
register Hash_Entry **hp, *p;
|
||||
|
||||
if (e == NULL)
|
||||
return;
|
||||
for (hp = &t->bucketPtr[e->namehash & t->mask];
|
||||
(p = *hp) != NULL; hp = &p->next) {
|
||||
if (p == e) {
|
||||
*hp = p->next;
|
||||
free((char *)p);
|
||||
t->numEntries--;
|
||||
return;
|
||||
}
|
||||
}
|
||||
(void) write(2, "bad call to Hash_DeleteEntry\n", 29);
|
||||
abort();
|
||||
}
|
||||
|
||||
/*
|
||||
*---------------------------------------------------------
|
||||
*
|
||||
* Hash_EnumFirst --
|
||||
* This procedure sets things up for a complete search
|
||||
* of all entries recorded in the hash table.
|
||||
*
|
||||
* Results:
|
||||
* The return value is the address of the first entry in
|
||||
* the hash table, or NULL if the table is empty.
|
||||
*
|
||||
* Side Effects:
|
||||
* The information in searchPtr is initialized so that successive
|
||||
* calls to Hash_Next will return successive HashEntry's
|
||||
* from the table.
|
||||
*
|
||||
*---------------------------------------------------------
|
||||
*/
|
||||
|
||||
Hash_Entry *
|
||||
Hash_EnumFirst(t, searchPtr)
|
||||
Hash_Table *t; /* Table to be searched. */
|
||||
register Hash_Search *searchPtr;/* Area in which to keep state
|
||||
* about search.*/
|
||||
{
|
||||
searchPtr->tablePtr = t;
|
||||
searchPtr->nextIndex = 0;
|
||||
searchPtr->hashEntryPtr = NULL;
|
||||
return Hash_EnumNext(searchPtr);
|
||||
}
|
||||
|
||||
/*
|
||||
*---------------------------------------------------------
|
||||
*
|
||||
* Hash_EnumNext --
|
||||
* This procedure returns successive entries in the hash table.
|
||||
*
|
||||
* Results:
|
||||
* The return value is a pointer to the next HashEntry
|
||||
* in the table, or NULL when the end of the table is
|
||||
* reached.
|
||||
*
|
||||
* Side Effects:
|
||||
* The information in searchPtr is modified to advance to the
|
||||
* next entry.
|
||||
*
|
||||
*---------------------------------------------------------
|
||||
*/
|
||||
|
||||
Hash_Entry *
|
||||
Hash_EnumNext(searchPtr)
|
||||
register Hash_Search *searchPtr; /* Area used to keep state about
|
||||
search. */
|
||||
{
|
||||
register Hash_Entry *e;
|
||||
Hash_Table *t = searchPtr->tablePtr;
|
||||
|
||||
/*
|
||||
* The hashEntryPtr field points to the most recently returned
|
||||
* entry, or is nil if we are starting up. If not nil, we have
|
||||
* to start at the next one in the chain.
|
||||
*/
|
||||
e = searchPtr->hashEntryPtr;
|
||||
if (e != NULL)
|
||||
e = e->next;
|
||||
/*
|
||||
* If the chain ran out, or if we are starting up, we need to
|
||||
* find the next nonempty chain.
|
||||
*/
|
||||
while (e == NULL) {
|
||||
if (searchPtr->nextIndex >= t->size)
|
||||
return (NULL);
|
||||
e = t->bucketPtr[searchPtr->nextIndex++];
|
||||
}
|
||||
searchPtr->hashEntryPtr = e;
|
||||
return (e);
|
||||
}
|
||||
|
||||
/*
|
||||
*---------------------------------------------------------
|
||||
*
|
||||
* RebuildTable --
|
||||
* This local routine makes a new hash table that
|
||||
* is larger than the old one.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
*
|
||||
* Side Effects:
|
||||
* The entire hash table is moved, so any bucket numbers
|
||||
* from the old table are invalid.
|
||||
*
|
||||
*---------------------------------------------------------
|
||||
*/
|
||||
|
||||
static void
|
||||
RebuildTable(t)
|
||||
register Hash_Table *t;
|
||||
{
|
||||
register Hash_Entry *e, *next = NULL, **hp, **xp;
|
||||
register int i, mask;
|
||||
register Hash_Entry **oldhp;
|
||||
int oldsize;
|
||||
|
||||
oldhp = t->bucketPtr;
|
||||
oldsize = i = t->size;
|
||||
i <<= 1;
|
||||
t->size = i;
|
||||
t->mask = mask = i - 1;
|
||||
t->bucketPtr = hp = (struct Hash_Entry **) emalloc(sizeof(*hp) * i);
|
||||
while (--i >= 0)
|
||||
*hp++ = NULL;
|
||||
for (hp = oldhp, i = oldsize; --i >= 0;) {
|
||||
for (e = *hp++; e != NULL; e = next) {
|
||||
next = e->next;
|
||||
xp = &t->bucketPtr[e->namehash & mask];
|
||||
e->next = *xp;
|
||||
*xp = e;
|
||||
}
|
||||
}
|
||||
free((char *)oldhp);
|
||||
}
|
116
usr.bin/make/hash.h
Normal file
116
usr.bin/make/hash.h
Normal file
@ -0,0 +1,116 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* @(#)hash.h 8.1 (Berkeley) 6/6/93
|
||||
*/
|
||||
|
||||
/* hash.h --
|
||||
*
|
||||
* This file contains definitions used by the hash module,
|
||||
* which maintains hash tables.
|
||||
*/
|
||||
|
||||
#ifndef _HASH
|
||||
#define _HASH
|
||||
|
||||
/*
|
||||
* The following defines one entry in the hash table.
|
||||
*/
|
||||
|
||||
typedef struct Hash_Entry {
|
||||
struct Hash_Entry *next; /* Used to link together all the
|
||||
* entries associated with the same
|
||||
* bucket. */
|
||||
ClientData clientData; /* Arbitrary piece of data associated
|
||||
* with key. */
|
||||
unsigned namehash; /* hash value of key */
|
||||
char name[1]; /* key string */
|
||||
} Hash_Entry;
|
||||
|
||||
typedef struct Hash_Table {
|
||||
struct Hash_Entry **bucketPtr;/* Pointers to Hash_Entry, one
|
||||
* for each bucket in the table. */
|
||||
int size; /* Actual size of array. */
|
||||
int numEntries; /* Number of entries in the table. */
|
||||
int mask; /* Used to select bits for hashing. */
|
||||
} Hash_Table;
|
||||
|
||||
/*
|
||||
* The following structure is used by the searching routines
|
||||
* to record where we are in the search.
|
||||
*/
|
||||
|
||||
typedef struct Hash_Search {
|
||||
Hash_Table *tablePtr; /* Table being searched. */
|
||||
int nextIndex; /* Next bucket to check (after current). */
|
||||
Hash_Entry *hashEntryPtr; /* Next entry to check in current bucket. */
|
||||
} Hash_Search;
|
||||
|
||||
/*
|
||||
* Macros.
|
||||
*/
|
||||
|
||||
/*
|
||||
* ClientData Hash_GetValue(h)
|
||||
* Hash_Entry *h;
|
||||
*/
|
||||
|
||||
#define Hash_GetValue(h) ((h)->clientData)
|
||||
|
||||
/*
|
||||
* Hash_SetValue(h, val);
|
||||
* Hash_Entry *h;
|
||||
* char *val;
|
||||
*/
|
||||
|
||||
#define Hash_SetValue(h, val) ((h)->clientData = (ClientData) (val))
|
||||
|
||||
/*
|
||||
* Hash_Size(n) returns the number of words in an object of n bytes
|
||||
*/
|
||||
|
||||
#define Hash_Size(n) (((n) + sizeof (int) - 1) / sizeof (int))
|
||||
|
||||
Hash_Entry *Hash_CreateEntry __P((Hash_Table *, char *, Boolean *));
|
||||
void Hash_DeleteEntry __P((Hash_Table *, Hash_Entry *));
|
||||
void Hash_DeleteTable __P((Hash_Table *));
|
||||
Hash_Entry *Hash_EnumFirst __P((Hash_Table *, Hash_Search *));
|
||||
Hash_Entry *Hash_EnumNext __P((Hash_Search *));
|
||||
Hash_Entry *Hash_FindEntry __P((Hash_Table *, char *));
|
||||
void Hash_InitTable __P((Hash_Table *, int));
|
||||
|
||||
#endif /* _HASH */
|
2661
usr.bin/make/job.c
Normal file
2661
usr.bin/make/job.c
Normal file
File diff suppressed because it is too large
Load Diff
233
usr.bin/make/job.h
Normal file
233
usr.bin/make/job.h
Normal file
@ -0,0 +1,233 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* @(#)job.h 8.1 (Berkeley) 6/6/93
|
||||
*/
|
||||
|
||||
/*-
|
||||
* job.h --
|
||||
* Definitions pertaining to the running of jobs in parallel mode.
|
||||
* Exported from job.c for the use of remote-execution modules.
|
||||
*/
|
||||
#ifndef _JOB_H_
|
||||
#define _JOB_H_
|
||||
|
||||
#define TMPPAT "/tmp/makeXXXXX"
|
||||
|
||||
/*
|
||||
* The SEL_ constants determine the maximum amount of time spent in select
|
||||
* before coming out to see if a child has finished. SEL_SEC is the number of
|
||||
* seconds and SEL_USEC is the number of micro-seconds
|
||||
*/
|
||||
#define SEL_SEC 0
|
||||
#define SEL_USEC 500000
|
||||
|
||||
|
||||
/*-
|
||||
* Job Table definitions.
|
||||
*
|
||||
* Each job has several things associated with it:
|
||||
* 1) The process id of the child shell
|
||||
* 2) The graph node describing the target being made by this job
|
||||
* 3) A LstNode for the first command to be saved after the job
|
||||
* completes. This is NILLNODE if there was no "..." in the job's
|
||||
* commands.
|
||||
* 4) An FILE* for writing out the commands. This is only
|
||||
* used before the job is actually started.
|
||||
* 5) A union of things used for handling the shell's output. Different
|
||||
* parts of the union are used based on the value of the usePipes
|
||||
* flag. If it is true, the output is being caught via a pipe and
|
||||
* the descriptors of our pipe, an array in which output is line
|
||||
* buffered and the current position in that buffer are all
|
||||
* maintained for each job. If, on the other hand, usePipes is false,
|
||||
* the output is routed to a temporary file and all that is kept
|
||||
* is the name of the file and the descriptor open to the file.
|
||||
* 6) An identifier provided by and for the exclusive use of the
|
||||
* Rmt module.
|
||||
* 7) A word of flags which determine how the module handles errors,
|
||||
* echoing, etc. for the job
|
||||
*
|
||||
* The job "table" is kept as a linked Lst in 'jobs', with the number of
|
||||
* active jobs maintained in the 'nJobs' variable. At no time will this
|
||||
* exceed the value of 'maxJobs', initialized by the Job_Init function.
|
||||
*
|
||||
* When a job is finished, the Make_Update function is called on each of the
|
||||
* parents of the node which was just remade. This takes care of the upward
|
||||
* traversal of the dependency graph.
|
||||
*/
|
||||
#define JOB_BUFSIZE 1024
|
||||
typedef struct Job {
|
||||
int pid; /* The child's process ID */
|
||||
GNode *node; /* The target the child is making */
|
||||
LstNode tailCmds; /* The node of the first command to be
|
||||
* saved when the job has been run */
|
||||
FILE *cmdFILE; /* When creating the shell script, this is
|
||||
* where the commands go */
|
||||
int rmtID; /* ID returned from Rmt module */
|
||||
short flags; /* Flags to control treatment of job */
|
||||
#define JOB_IGNERR 0x001 /* Ignore non-zero exits */
|
||||
#define JOB_SILENT 0x002 /* no output */
|
||||
#define JOB_SPECIAL 0x004 /* Target is a special one. i.e. run it locally
|
||||
* if we can't export it and maxLocal is 0 */
|
||||
#define JOB_IGNDOTS 0x008 /* Ignore "..." lines when processing
|
||||
* commands */
|
||||
#define JOB_REMOTE 0x010 /* Job is running remotely */
|
||||
#define JOB_FIRST 0x020 /* Job is first job for the node */
|
||||
#define JOB_REMIGRATE 0x040 /* Job needs to be remigrated */
|
||||
#define JOB_RESTART 0x080 /* Job needs to be completely restarted */
|
||||
#define JOB_RESUME 0x100 /* Job needs to be resumed b/c it stopped,
|
||||
* for some reason */
|
||||
#define JOB_CONTINUING 0x200 /* We are in the process of resuming this job.
|
||||
* Used to avoid infinite recursion between
|
||||
* JobFinish and JobRestart */
|
||||
union {
|
||||
struct {
|
||||
int op_inPipe; /* Input side of pipe associated
|
||||
* with job's output channel */
|
||||
int op_outPipe; /* Output side of pipe associated with
|
||||
* job's output channel */
|
||||
char op_outBuf[JOB_BUFSIZE + 1];
|
||||
/* Buffer for storing the output of the
|
||||
* job, line by line */
|
||||
int op_curPos; /* Current position in op_outBuf */
|
||||
} o_pipe; /* data used when catching the output via
|
||||
* a pipe */
|
||||
struct {
|
||||
char of_outFile[sizeof(TMPPAT)+2];
|
||||
/* Name of file to which shell output
|
||||
* was rerouted */
|
||||
int of_outFd; /* Stream open to the output
|
||||
* file. Used to funnel all
|
||||
* from a single job to one file
|
||||
* while still allowing
|
||||
* multiple shell invocations */
|
||||
} o_file; /* Data used when catching the output in
|
||||
* a temporary file */
|
||||
} output; /* Data for tracking a shell's output */
|
||||
} Job;
|
||||
|
||||
#define outPipe output.o_pipe.op_outPipe
|
||||
#define inPipe output.o_pipe.op_inPipe
|
||||
#define outBuf output.o_pipe.op_outBuf
|
||||
#define curPos output.o_pipe.op_curPos
|
||||
#define outFile output.o_file.of_outFile
|
||||
#define outFd output.o_file.of_outFd
|
||||
|
||||
|
||||
/*-
|
||||
* Shell Specifications:
|
||||
* Each shell type has associated with it the following information:
|
||||
* 1) The string which must match the last character of the shell name
|
||||
* for the shell to be considered of this type. The longest match
|
||||
* wins.
|
||||
* 2) A command to issue to turn off echoing of command lines
|
||||
* 3) A command to issue to turn echoing back on again
|
||||
* 4) What the shell prints, and its length, when given the echo-off
|
||||
* command. This line will not be printed when received from the shell
|
||||
* 5) A boolean to tell if the shell has the ability to control
|
||||
* error checking for individual commands.
|
||||
* 6) The string to turn this checking on.
|
||||
* 7) The string to turn it off.
|
||||
* 8) The command-flag to give to cause the shell to start echoing
|
||||
* commands right away.
|
||||
* 9) The command-flag to cause the shell to Lib_Exit when an error is
|
||||
* detected in one of the commands.
|
||||
*
|
||||
* Some special stuff goes on if a shell doesn't have error control. In such
|
||||
* a case, errCheck becomes a printf template for echoing the command,
|
||||
* should echoing be on and ignErr becomes another printf template for
|
||||
* executing the command while ignoring the return status. If either of these
|
||||
* strings is empty when hasErrCtl is FALSE, the command will be executed
|
||||
* anyway as is and if it causes an error, so be it.
|
||||
*/
|
||||
typedef struct Shell {
|
||||
char *name; /* the name of the shell. For Bourne and C
|
||||
* shells, this is used only to find the
|
||||
* shell description when used as the single
|
||||
* source of a .SHELL target. For user-defined
|
||||
* shells, this is the full path of the shell.
|
||||
*/
|
||||
Boolean hasEchoCtl; /* True if both echoOff and echoOn defined */
|
||||
char *echoOff; /* command to turn off echo */
|
||||
char *echoOn; /* command to turn it back on again */
|
||||
char *noPrint; /* command to skip when printing output from
|
||||
* shell. This is usually the command which
|
||||
* was executed to turn off echoing */
|
||||
int noPLen; /* length of noPrint command */
|
||||
Boolean hasErrCtl; /* set if can control error checking for
|
||||
* individual commands */
|
||||
char *errCheck; /* string to turn error checking on */
|
||||
char *ignErr; /* string to turn off error checking */
|
||||
/*
|
||||
* command-line flags
|
||||
*/
|
||||
char *echo; /* echo commands */
|
||||
char *exit; /* exit on error */
|
||||
} Shell;
|
||||
|
||||
|
||||
extern char *targFmt; /* Format string for banner that separates
|
||||
* output from multiple jobs. Contains a
|
||||
* single %s where the name of the node being
|
||||
* made should be put. */
|
||||
extern GNode *lastNode; /* Last node for which a banner was printed.
|
||||
* If Rmt module finds it necessary to print
|
||||
* a banner, it should set this to the node
|
||||
* for which the banner was printed */
|
||||
extern int nJobs; /* Number of jobs running (local and remote) */
|
||||
extern int nLocal; /* Number of jobs running locally */
|
||||
extern Lst jobs; /* List of active job descriptors */
|
||||
extern Lst stoppedJobs; /* List of jobs that are stopped or didn't
|
||||
* quite get started */
|
||||
extern Boolean jobFull; /* Non-zero if no more jobs should/will start*/
|
||||
|
||||
void JobFlagForMigration __P((int));
|
||||
void Job_AbortAll __P((void));
|
||||
void Job_CatchChildren __P((Boolean));
|
||||
void Job_CatchOutput __P((void));
|
||||
Boolean Job_CheckCommands __P((GNode *,
|
||||
void (*abortProc )(const char *, ...)));
|
||||
Boolean Job_Empty __P((void));
|
||||
int Job_End __P((void));
|
||||
Boolean Job_Full __P((void));
|
||||
void Job_Init __P((int, int));
|
||||
void Job_Make __P((GNode *));
|
||||
ReturnStatus Job_ParseShell __P((char *));
|
||||
void Job_Touch __P((GNode *, Boolean));
|
||||
void Job_Wait __P((void));
|
||||
|
||||
#endif /* _JOB_H_ */
|
298
usr.bin/make/list.h
Normal file
298
usr.bin/make/list.h
Normal file
@ -0,0 +1,298 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* @(#)list.h 8.1 (Berkeley) 6/6/93
|
||||
*/
|
||||
|
||||
/*
|
||||
* list.h --
|
||||
*
|
||||
* Structures, macros, and routines exported by the List module.
|
||||
*/
|
||||
|
||||
#ifndef _LIST
|
||||
#define _LIST
|
||||
|
||||
#ifndef _SPRITE
|
||||
#include "sprite.h"
|
||||
#endif _SPRITE
|
||||
|
||||
/*
|
||||
* This module defines the list abstraction, which enables one to link
|
||||
* together arbitrary data structures. Lists are doubly-linked and
|
||||
* circular. A list contains a header followed by its real members, if
|
||||
* any. (An empty list therefore consists of a single element, the
|
||||
* header, whose nextPtr and prevPtr fields point to itself). To refer
|
||||
* to a list as a whole, the user keeps a pointer to the header; that
|
||||
* header is initialized by a call to List_Init(), which creates an empty
|
||||
* list given a pointer to a List_Links structure (described below).
|
||||
*
|
||||
* The links are contained in a two-element structure called List_Links.
|
||||
* A list joins List_Links records (that is, each List_Links structure
|
||||
* points to other List_Links structures), but if the List_Links is the
|
||||
* first field within a larger structure, then the larger structures are
|
||||
* effectively linked together as follows:
|
||||
*
|
||||
* header
|
||||
* (List_Links) first elt. second elt.
|
||||
* ----------------- ----------------- -----------------
|
||||
* ..-> | nextPtr | ----> | List_Links | ----> | List_Links |----..
|
||||
* | - - - - - - - | | | | |
|
||||
* ..-- | prevPtr | <---- | | <---- | |<---..
|
||||
* ----------------- - --- --- --- - - --- --- --- -
|
||||
* | rest of | | rest of |
|
||||
* | structure | | structure |
|
||||
* | | | |
|
||||
* | ... | | ... |
|
||||
* ----------------- -----------------
|
||||
*
|
||||
* It is possible to link structures through List_Links fields that are
|
||||
* not at the beginning of the larger structure, but it is then necessary
|
||||
* to perform pointer arithmetic to find the beginning of the larger
|
||||
* structure, given a pointer to some point within it.
|
||||
*
|
||||
* A typical structure might be something like:
|
||||
*
|
||||
* typedef struct {
|
||||
* List_Links links;
|
||||
* char ch;
|
||||
* integer flags;
|
||||
* } EditChar;
|
||||
*
|
||||
* Before an element is inserted in a list for the first time, it must
|
||||
* be initialized by calling the macro List_InitElement().
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* data structure for lists
|
||||
*/
|
||||
|
||||
typedef struct List_Links {
|
||||
struct List_Links *prevPtr;
|
||||
struct List_Links *nextPtr;
|
||||
} List_Links;
|
||||
|
||||
/*
|
||||
* procedures
|
||||
*/
|
||||
|
||||
void List_Init(); /* initialize a header to a list */
|
||||
void List_Insert(); /* insert an element into a list */
|
||||
void List_Remove(); /* remove an element from a list */
|
||||
void List_Move(); /* move an element elsewhere in a list */
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
* List_InitElement --
|
||||
*
|
||||
* Initialize a list element. Must be called before an element is first
|
||||
* inserted into a list.
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
#define List_InitElement(elementPtr) \
|
||||
(elementPtr)->prevPtr = (List_Links *) NIL; \
|
||||
(elementPtr)->nextPtr = (List_Links *) NIL;
|
||||
|
||||
/*
|
||||
* Macros for stepping through or selecting parts of lists
|
||||
*/
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
* LIST_FORALL --
|
||||
*
|
||||
* Macro to loop through a list and perform an operation on each member.
|
||||
*
|
||||
* Usage: LIST_FORALL(headerPtr, itemPtr) {
|
||||
* / *
|
||||
* * operation on itemPtr, which points to successive members
|
||||
* * of the list
|
||||
* *
|
||||
* * It may be appropriate to first assign
|
||||
* * foobarPtr = (Foobar *) itemPtr;
|
||||
* * to refer to the entire Foobar structure.
|
||||
* * /
|
||||
* }
|
||||
*
|
||||
* Note: itemPtr must be a List_Links pointer variable, and headerPtr
|
||||
* must evaluate to a pointer to a List_Links structure.
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#define LIST_FORALL(headerPtr, itemPtr) \
|
||||
for (itemPtr = List_First(headerPtr); \
|
||||
!List_IsAtEnd((headerPtr),itemPtr); \
|
||||
itemPtr = List_Next(itemPtr))
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
* List_IsEmpty --
|
||||
*
|
||||
* Macro: Boolean value, TRUE if the given list does not contain any
|
||||
* members.
|
||||
*
|
||||
* Usage: if (List_IsEmpty(headerPtr)) ...
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#define List_IsEmpty(headerPtr) \
|
||||
((headerPtr) == (headerPtr)->nextPtr)
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
* List_IsAtEnd --
|
||||
*
|
||||
* Macro: Boolean value, TRUE if itemPtr is after the end of headerPtr
|
||||
* (i.e., itemPtr is the header of the list).
|
||||
*
|
||||
* Usage: if (List_IsAtEnd(headerPtr, itemPtr)) ...
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
#define List_IsAtEnd(headerPtr, itemPtr) \
|
||||
((itemPtr) == (headerPtr))
|
||||
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
* List_First --
|
||||
*
|
||||
* Macro to return the first member in a list, which is the header if
|
||||
* the list is empty.
|
||||
*
|
||||
* Usage: firstPtr = List_First(headerPtr);
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#define List_First(headerPtr) ((headerPtr)->nextPtr)
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
* List_Last --
|
||||
*
|
||||
* Macro to return the last member in a list, which is the header if
|
||||
* the list is empty.
|
||||
*
|
||||
* Usage: lastPtr = List_Last(headerPtr);
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#define List_Last(headerPtr) ((headerPtr)->prevPtr)
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
* List_Prev --
|
||||
*
|
||||
* Macro to return the member preceding the given member in its list.
|
||||
* If the given list member is the first element in the list, List_Prev
|
||||
* returns the list header.
|
||||
*
|
||||
* Usage: prevPtr = List_Prev(itemPtr);
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#define List_Prev(itemPtr) ((itemPtr)->prevPtr)
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
* List_Next --
|
||||
*
|
||||
* Macro to return the member following the given member in its list.
|
||||
* If the given list member is the last element in the list, List_Next
|
||||
* returns the list header.
|
||||
*
|
||||
* Usage: nextPtr = List_Next(itemPtr);
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#define List_Next(itemPtr) ((itemPtr)->nextPtr)
|
||||
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
* The List_Insert procedure takes two arguments. The first argument
|
||||
* is a pointer to the structure to be inserted into a list, and
|
||||
* the second argument is a pointer to the list member after which
|
||||
* the new element is to be inserted. Macros are used to determine
|
||||
* which existing member will precede the new one.
|
||||
*
|
||||
* The List_Move procedure takes a destination argument with the same
|
||||
* semantics as List_Insert.
|
||||
*
|
||||
* The following macros define where to insert the new element
|
||||
* in the list:
|
||||
*
|
||||
* LIST_AFTER(itemPtr) -- insert after itemPtr
|
||||
* LIST_BEFORE(itemPtr) -- insert before itemPtr
|
||||
* LIST_ATFRONT(headerPtr) -- insert at front of list
|
||||
* LIST_ATREAR(headerPtr) -- insert at end of list
|
||||
*
|
||||
* For example,
|
||||
*
|
||||
* List_Insert(itemPtr, LIST_AFTER(otherPtr));
|
||||
*
|
||||
* will insert itemPtr following otherPtr in the list containing otherPtr.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#define LIST_AFTER(itemPtr) ((List_Links *) itemPtr)
|
||||
|
||||
#define LIST_BEFORE(itemPtr) (((List_Links *) itemPtr)->prevPtr)
|
||||
|
||||
#define LIST_ATFRONT(headerPtr) ((List_Links *) headerPtr)
|
||||
|
||||
#define LIST_ATREAR(headerPtr) (((List_Links *) headerPtr)->prevPtr)
|
||||
|
||||
#endif /* _LIST */
|
145
usr.bin/make/lst.h
Normal file
145
usr.bin/make/lst.h
Normal file
@ -0,0 +1,145 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* @(#)lst.h 8.1 (Berkeley) 6/6/93
|
||||
*/
|
||||
|
||||
/*-
|
||||
* lst.h --
|
||||
* Header for using the list library
|
||||
*/
|
||||
#ifndef _LST_H_
|
||||
#define _LST_H_
|
||||
|
||||
#include <sprite.h>
|
||||
#if __STDC__
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* basic typedef. This is what the Lst_ functions handle
|
||||
*/
|
||||
|
||||
typedef struct Lst *Lst;
|
||||
typedef struct LstNode *LstNode;
|
||||
|
||||
#define NILLST ((Lst) NIL)
|
||||
#define NILLNODE ((LstNode) NIL)
|
||||
|
||||
/*
|
||||
* NOFREE can be used as the freeProc to Lst_Destroy when the elements are
|
||||
* not to be freed.
|
||||
* NOCOPY performs similarly when given as the copyProc to Lst_Duplicate.
|
||||
*/
|
||||
#define NOFREE ((void (*)()) 0)
|
||||
#define NOCOPY ((ClientData (*)()) 0)
|
||||
|
||||
#define LST_CONCNEW 0 /* create new LstNode's when using Lst_Concat */
|
||||
#define LST_CONCLINK 1 /* relink LstNode's when using Lst_Concat */
|
||||
|
||||
/*
|
||||
* Creation/destruction functions
|
||||
*/
|
||||
Lst Lst_Init(); /* Create a new list */
|
||||
Lst Lst_Duplicate(); /* Duplicate an existing list */
|
||||
void Lst_Destroy(); /* Destroy an old one */
|
||||
|
||||
int Lst_Length(); /* Find the length of a list */
|
||||
Boolean Lst_IsEmpty(); /* True if list is empty */
|
||||
|
||||
/*
|
||||
* Functions to modify a list
|
||||
*/
|
||||
ReturnStatus Lst_Insert(); /* Insert an element before another */
|
||||
ReturnStatus Lst_Append(); /* Insert an element after another */
|
||||
ReturnStatus Lst_AtFront(); /* Place an element at the front of
|
||||
* a lst. */
|
||||
ReturnStatus Lst_AtEnd(); /* Place an element at the end of a
|
||||
* lst. */
|
||||
ReturnStatus Lst_Remove(); /* Remove an element */
|
||||
ReturnStatus Lst_Replace(); /* Replace a node with a new value */
|
||||
ReturnStatus Lst_Move(); /* Move an element to another place */
|
||||
ReturnStatus Lst_Concat(); /* Concatenate two lists */
|
||||
|
||||
/*
|
||||
* Node-specific functions
|
||||
*/
|
||||
LstNode Lst_First(); /* Return first element in list */
|
||||
LstNode Lst_Last(); /* Return last element in list */
|
||||
LstNode Lst_Succ(); /* Return successor to given element */
|
||||
LstNode Lst_Pred(); /* Return predecessor to given
|
||||
* element */
|
||||
ClientData Lst_Datum(); /* Get datum from LstNode */
|
||||
|
||||
/*
|
||||
* Functions for entire lists
|
||||
*/
|
||||
LstNode Lst_Find(); /* Find an element in a list */
|
||||
LstNode Lst_FindFrom(); /* Find an element starting from
|
||||
* somewhere */
|
||||
LstNode Lst_Member(); /* See if the given datum is on the
|
||||
* list. Returns the LstNode containing
|
||||
* the datum */
|
||||
int Lst_Index(); /* Returns the index of a datum in the
|
||||
* list, starting from 0 */
|
||||
void Lst_ForEach(); /* Apply a function to all elements of
|
||||
* a lst */
|
||||
void Lst_ForEachFrom(); /* Apply a function to all elements of
|
||||
* a lst starting from a certain point.
|
||||
* If the list is circular, the
|
||||
* application will wrap around to the
|
||||
* beginning of the list again. */
|
||||
/*
|
||||
* these functions are for dealing with a list as a table, of sorts.
|
||||
* An idea of the "current element" is kept and used by all the functions
|
||||
* between Lst_Open() and Lst_Close().
|
||||
*/
|
||||
ReturnStatus Lst_Open(); /* Open the list */
|
||||
LstNode Lst_Prev(); /* Previous element */
|
||||
LstNode Lst_Cur(); /* The current element, please */
|
||||
LstNode Lst_Next(); /* Next element please */
|
||||
Boolean Lst_IsAtEnd(); /* Done yet? */
|
||||
void Lst_Close(); /* Finish table access */
|
||||
|
||||
/*
|
||||
* for using the list as a queue
|
||||
*/
|
||||
ReturnStatus Lst_EnQueue(); /* Place an element at tail of queue */
|
||||
ClientData Lst_DeQueue(); /* Remove an element from head of
|
||||
* queue */
|
||||
|
||||
#endif _LST_H_
|
113
usr.bin/make/lst.lib/lstAppend.c
Normal file
113
usr.bin/make/lst.lib/lstAppend.c
Normal file
@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright (c) 1988, 1989, 1990, 1993
|
||||
* The Regents of the University of California. 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.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)lstAppend.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif /* not lint */
|
||||
|
||||
/*-
|
||||
* LstAppend.c --
|
||||
* Add a new node with a new datum after an existing node
|
||||
*/
|
||||
|
||||
#include "lstInt.h"
|
||||
|
||||
/*-
|
||||
*-----------------------------------------------------------------------
|
||||
* Lst_Append --
|
||||
* Create a new node and add it to the given list after the given node.
|
||||
*
|
||||
* Results:
|
||||
* SUCCESS if all went well.
|
||||
*
|
||||
* Side Effects:
|
||||
* A new ListNode is created and linked in to the List. The lastPtr
|
||||
* field of the List will be altered if ln is the last node in the
|
||||
* list. lastPtr and firstPtr will alter if the list was empty and
|
||||
* ln was NILLNODE.
|
||||
*
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
ReturnStatus
|
||||
Lst_Append (l, ln, d)
|
||||
Lst l; /* affected list */
|
||||
LstNode ln; /* node after which to append the datum */
|
||||
ClientData d; /* said datum */
|
||||
{
|
||||
register List list;
|
||||
register ListNode lNode;
|
||||
register ListNode nLNode;
|
||||
|
||||
if (LstValid (l) && (ln == NILLNODE && LstIsEmpty (l))) {
|
||||
goto ok;
|
||||
}
|
||||
|
||||
if (!LstValid (l) || LstIsEmpty (l) || ! LstNodeValid (ln, l)) {
|
||||
return (FAILURE);
|
||||
}
|
||||
ok:
|
||||
|
||||
list = (List)l;
|
||||
lNode = (ListNode)ln;
|
||||
|
||||
PAlloc (nLNode, ListNode);
|
||||
nLNode->datum = d;
|
||||
nLNode->useCount = nLNode->flags = 0;
|
||||
|
||||
if (lNode == NilListNode) {
|
||||
if (list->isCirc) {
|
||||
nLNode->nextPtr = nLNode->prevPtr = nLNode;
|
||||
} else {
|
||||
nLNode->nextPtr = nLNode->prevPtr = NilListNode;
|
||||
}
|
||||
list->firstPtr = list->lastPtr = nLNode;
|
||||
} else {
|
||||
nLNode->prevPtr = lNode;
|
||||
nLNode->nextPtr = lNode->nextPtr;
|
||||
|
||||
lNode->nextPtr = nLNode;
|
||||
if (nLNode->nextPtr != NilListNode) {
|
||||
nLNode->nextPtr->prevPtr = nLNode;
|
||||
}
|
||||
|
||||
if (lNode == list->lastPtr) {
|
||||
list->lastPtr = nLNode;
|
||||
}
|
||||
}
|
||||
|
||||
return (SUCCESS);
|
||||
}
|
||||
|
70
usr.bin/make/lst.lib/lstAtEnd.c
Normal file
70
usr.bin/make/lst.lib/lstAtEnd.c
Normal file
@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright (c) 1988, 1989, 1990, 1993
|
||||
* The Regents of the University of California. 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.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)lstAtEnd.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif /* not lint */
|
||||
|
||||
/*-
|
||||
* LstAtEnd.c --
|
||||
* Add a node at the end of the list
|
||||
*/
|
||||
|
||||
#include "lstInt.h"
|
||||
|
||||
/*-
|
||||
*-----------------------------------------------------------------------
|
||||
* Lst_AtEnd --
|
||||
* Add a node to the end of the given list
|
||||
*
|
||||
* Results:
|
||||
* SUCCESS if life is good.
|
||||
*
|
||||
* Side Effects:
|
||||
* A new ListNode is created and added to the list.
|
||||
*
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
ReturnStatus
|
||||
Lst_AtEnd (l, d)
|
||||
Lst l; /* List to which to add the datum */
|
||||
ClientData d; /* Datum to add */
|
||||
{
|
||||
register LstNode end;
|
||||
|
||||
end = Lst_Last (l);
|
||||
return (Lst_Append (l, end, d));
|
||||
}
|
71
usr.bin/make/lst.lib/lstAtFront.c
Normal file
71
usr.bin/make/lst.lib/lstAtFront.c
Normal file
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright (c) 1988, 1989, 1990, 1993
|
||||
* The Regents of the University of California. 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.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)lstAtFront.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif /* not lint */
|
||||
|
||||
/*-
|
||||
* LstAtFront.c --
|
||||
* Add a node at the front of the list
|
||||
*/
|
||||
|
||||
#include "lstInt.h"
|
||||
|
||||
/*-
|
||||
*-----------------------------------------------------------------------
|
||||
* Lst_AtFront --
|
||||
* Place a piece of data at the front of a list
|
||||
*
|
||||
* Results:
|
||||
* SUCCESS or FAILURE
|
||||
*
|
||||
* Side Effects:
|
||||
* A new ListNode is created and stuck at the front of the list.
|
||||
* hence, firstPtr (and possible lastPtr) in the list are altered.
|
||||
*
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
ReturnStatus
|
||||
Lst_AtFront (l, d)
|
||||
Lst l;
|
||||
ClientData d;
|
||||
{
|
||||
register LstNode front;
|
||||
|
||||
front = Lst_First (l);
|
||||
return (Lst_Insert (l, front, d));
|
||||
}
|
77
usr.bin/make/lst.lib/lstClose.c
Normal file
77
usr.bin/make/lst.lib/lstClose.c
Normal file
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright (c) 1988, 1989, 1990, 1993
|
||||
* The Regents of the University of California. 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.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)lstClose.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif /* not lint */
|
||||
|
||||
/*-
|
||||
* LstClose.c --
|
||||
* Close a list for sequential access.
|
||||
* The sequential functions access the list in a slightly different way.
|
||||
* CurPtr points to their idea of the current node in the list and they
|
||||
* access the list based on it. Because the list is circular, Lst_Next
|
||||
* and Lst_Prev will go around the list forever. Lst_IsAtEnd must be
|
||||
* used to determine when to stop.
|
||||
*/
|
||||
|
||||
#include "lstInt.h"
|
||||
|
||||
/*-
|
||||
*-----------------------------------------------------------------------
|
||||
* Lst_Close --
|
||||
* Close a list which was opened for sequential access.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
*
|
||||
* Side Effects:
|
||||
* The list is closed.
|
||||
*
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
void
|
||||
Lst_Close (l)
|
||||
Lst l; /* The list to close */
|
||||
{
|
||||
register List list = (List) l;
|
||||
|
||||
if (LstValid(l) == TRUE) {
|
||||
list->isOpen = FALSE;
|
||||
list->atEnd = Unknown;
|
||||
}
|
||||
}
|
||||
|
174
usr.bin/make/lst.lib/lstConcat.c
Normal file
174
usr.bin/make/lst.lib/lstConcat.c
Normal file
@ -0,0 +1,174 @@
|
||||
/*
|
||||
* Copyright (c) 1988, 1989, 1990, 1993
|
||||
* The Regents of the University of California. 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.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)lstConcat.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif /* not lint */
|
||||
|
||||
/*-
|
||||
* listConcat.c --
|
||||
* Function to concatentate two lists.
|
||||
*/
|
||||
|
||||
#include "lstInt.h"
|
||||
|
||||
/*-
|
||||
*-----------------------------------------------------------------------
|
||||
* Lst_Concat --
|
||||
* Concatenate two lists. New elements are created to hold the data
|
||||
* elements, if specified, but the elements themselves are not copied.
|
||||
* If the elements should be duplicated to avoid confusion with another
|
||||
* list, the Lst_Duplicate function should be called first.
|
||||
* If LST_CONCLINK is specified, the second list is destroyed since
|
||||
* its pointers have been corrupted and the list is no longer useable.
|
||||
*
|
||||
* Results:
|
||||
* SUCCESS if all went well. FAILURE otherwise.
|
||||
*
|
||||
* Side Effects:
|
||||
* New elements are created and appended the the first list.
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
ReturnStatus
|
||||
Lst_Concat (l1, l2, flags)
|
||||
Lst l1; /* The list to which l2 is to be appended */
|
||||
Lst l2; /* The list to append to l1 */
|
||||
int flags; /* LST_CONCNEW if LstNode's should be duplicated
|
||||
* LST_CONCLINK if should just be relinked */
|
||||
{
|
||||
register ListNode ln; /* original LstNode */
|
||||
register ListNode nln; /* new LstNode */
|
||||
register ListNode last; /* the last element in the list. Keeps
|
||||
* bookkeeping until the end */
|
||||
register List list1 = (List)l1;
|
||||
register List list2 = (List)l2;
|
||||
|
||||
if (!LstValid (l1) || !LstValid (l2)) {
|
||||
return (FAILURE);
|
||||
}
|
||||
|
||||
if (flags == LST_CONCLINK) {
|
||||
if (list2->firstPtr != NilListNode) {
|
||||
/*
|
||||
* We set the nextPtr of the
|
||||
* last element of list two to be NIL to make the loop easier and
|
||||
* so we don't need an extra case should the first list turn
|
||||
* out to be non-circular -- the final element will already point
|
||||
* to NIL space and the first element will be untouched if it
|
||||
* existed before and will also point to NIL space if it didn't.
|
||||
*/
|
||||
list2->lastPtr->nextPtr = NilListNode;
|
||||
/*
|
||||
* So long as the second list isn't empty, we just link the
|
||||
* first element of the second list to the last element of the
|
||||
* first list. If the first list isn't empty, we then link the
|
||||
* last element of the list to the first element of the second list
|
||||
* The last element of the second list, if it exists, then becomes
|
||||
* the last element of the first list.
|
||||
*/
|
||||
list2->firstPtr->prevPtr = list1->lastPtr;
|
||||
if (list1->lastPtr != NilListNode) {
|
||||
list1->lastPtr->nextPtr = list2->firstPtr;
|
||||
}
|
||||
list1->lastPtr = list2->lastPtr;
|
||||
}
|
||||
if (list1->isCirc && list1->firstPtr != NilListNode) {
|
||||
/*
|
||||
* If the first list is supposed to be circular and it is (now)
|
||||
* non-empty, we must make sure it's circular by linking the
|
||||
* first element to the last and vice versa
|
||||
*/
|
||||
list1->firstPtr->prevPtr = list1->lastPtr;
|
||||
list1->lastPtr->nextPtr = list1->firstPtr;
|
||||
}
|
||||
free ((Address)l2);
|
||||
} else if (list2->firstPtr != NilListNode) {
|
||||
/*
|
||||
* We set the nextPtr of the last element of list 2 to be nil to make
|
||||
* the loop less difficult. The loop simply goes through the entire
|
||||
* second list creating new LstNodes and filling in the nextPtr, and
|
||||
* prevPtr to fit into l1 and its datum field from the
|
||||
* datum field of the corresponding element in l2. The 'last' node
|
||||
* follows the last of the new nodes along until the entire l2 has
|
||||
* been appended. Only then does the bookkeeping catch up with the
|
||||
* changes. During the first iteration of the loop, if 'last' is nil,
|
||||
* the first list must have been empty so the newly-created node is
|
||||
* made the first node of the list.
|
||||
*/
|
||||
list2->lastPtr->nextPtr = NilListNode;
|
||||
for (last = list1->lastPtr, ln = list2->firstPtr;
|
||||
ln != NilListNode;
|
||||
ln = ln->nextPtr)
|
||||
{
|
||||
PAlloc (nln, ListNode);
|
||||
nln->datum = ln->datum;
|
||||
if (last != NilListNode) {
|
||||
last->nextPtr = nln;
|
||||
} else {
|
||||
list1->firstPtr = nln;
|
||||
}
|
||||
nln->prevPtr = last;
|
||||
nln->flags = nln->useCount = 0;
|
||||
last = nln;
|
||||
}
|
||||
|
||||
/*
|
||||
* Finish bookkeeping. The last new element becomes the last element
|
||||
* of list one.
|
||||
*/
|
||||
list1->lastPtr = last;
|
||||
|
||||
/*
|
||||
* The circularity of both list one and list two must be corrected
|
||||
* for -- list one because of the new nodes added to it; list two
|
||||
* because of the alteration of list2->lastPtr's nextPtr to ease the
|
||||
* above for loop.
|
||||
*/
|
||||
if (list1->isCirc) {
|
||||
list1->lastPtr->nextPtr = list1->firstPtr;
|
||||
list1->firstPtr->prevPtr = list1->lastPtr;
|
||||
} else {
|
||||
last->nextPtr = NilListNode;
|
||||
}
|
||||
|
||||
if (list2->isCirc) {
|
||||
list2->lastPtr->nextPtr = list2->firstPtr;
|
||||
}
|
||||
}
|
||||
|
||||
return (SUCCESS);
|
||||
}
|
||||
|
71
usr.bin/make/lst.lib/lstDatum.c
Normal file
71
usr.bin/make/lst.lib/lstDatum.c
Normal file
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright (c) 1988, 1989, 1990, 1993
|
||||
* The Regents of the University of California. 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.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)lstDatum.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif /* not lint */
|
||||
|
||||
/*-
|
||||
* LstDatum.c --
|
||||
* Return the datum associated with a list node.
|
||||
*/
|
||||
|
||||
#include "lstInt.h"
|
||||
|
||||
/*-
|
||||
*-----------------------------------------------------------------------
|
||||
* Lst_Datum --
|
||||
* Return the datum stored in the given node.
|
||||
*
|
||||
* Results:
|
||||
* The datum or (ick!) NIL if the node is invalid.
|
||||
*
|
||||
* Side Effects:
|
||||
* None.
|
||||
*
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
ClientData
|
||||
Lst_Datum (ln)
|
||||
LstNode ln;
|
||||
{
|
||||
if (ln != NILLNODE) {
|
||||
return (((ListNode)ln)->datum);
|
||||
} else {
|
||||
return ((ClientData) NIL);
|
||||
}
|
||||
}
|
||||
|
81
usr.bin/make/lst.lib/lstDeQueue.c
Normal file
81
usr.bin/make/lst.lib/lstDeQueue.c
Normal file
@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (c) 1988, 1989, 1990, 1993
|
||||
* The Regents of the University of California. 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.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)lstDeQueue.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif /* not lint */
|
||||
|
||||
/*-
|
||||
* LstDeQueue.c --
|
||||
* Remove the node and return its datum from the head of the list
|
||||
*/
|
||||
|
||||
#include "lstInt.h"
|
||||
|
||||
/*-
|
||||
*-----------------------------------------------------------------------
|
||||
* Lst_DeQueue --
|
||||
* Remove and return the datum at the head of the given list.
|
||||
*
|
||||
* Results:
|
||||
* The datum in the node at the head or (ick) NIL if the list
|
||||
* is empty.
|
||||
*
|
||||
* Side Effects:
|
||||
* The head node is removed from the list.
|
||||
*
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
ClientData
|
||||
Lst_DeQueue (l)
|
||||
Lst l;
|
||||
{
|
||||
ClientData rd;
|
||||
register ListNode tln;
|
||||
|
||||
tln = (ListNode) Lst_First (l);
|
||||
if (tln == NilListNode) {
|
||||
return ((ClientData) NIL);
|
||||
}
|
||||
|
||||
rd = tln->datum;
|
||||
if (Lst_Remove (l, (LstNode)tln) == FAILURE) {
|
||||
return ((ClientData) NIL);
|
||||
} else {
|
||||
return (rd);
|
||||
}
|
||||
}
|
||||
|
98
usr.bin/make/lst.lib/lstDestroy.c
Normal file
98
usr.bin/make/lst.lib/lstDestroy.c
Normal file
@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Copyright (c) 1988, 1989, 1990, 1993
|
||||
* The Regents of the University of California. 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.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)lstDestroy.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif /* not lint */
|
||||
|
||||
/*-
|
||||
* LstDestroy.c --
|
||||
* Nuke a list and all its resources
|
||||
*/
|
||||
|
||||
#include "lstInt.h"
|
||||
|
||||
/*-
|
||||
*-----------------------------------------------------------------------
|
||||
* Lst_Destroy --
|
||||
* Destroy a list and free all its resources. If the freeProc is
|
||||
* given, it is called with the datum from each node in turn before
|
||||
* the node is freed.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
*
|
||||
* Side Effects:
|
||||
* The given list is freed in its entirety.
|
||||
*
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
void
|
||||
Lst_Destroy (l, freeProc)
|
||||
Lst l;
|
||||
register void (*freeProc)();
|
||||
{
|
||||
register ListNode ln;
|
||||
register ListNode tln = NilListNode;
|
||||
register List list = (List)l;
|
||||
|
||||
if (l == NILLST || ! l) {
|
||||
/*
|
||||
* Note the check for l == (Lst)0 to catch uninitialized static Lst's.
|
||||
* Gross, but useful.
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
||||
if (freeProc) {
|
||||
for (ln = list->firstPtr;
|
||||
ln != NilListNode && tln != list->firstPtr;
|
||||
ln = tln) {
|
||||
tln = ln->nextPtr;
|
||||
(*freeProc) (ln->datum);
|
||||
free ((Address)ln);
|
||||
}
|
||||
} else {
|
||||
for (ln = list->firstPtr;
|
||||
ln != NilListNode && tln != list->firstPtr;
|
||||
ln = tln) {
|
||||
tln = ln->nextPtr;
|
||||
free ((Address)ln);
|
||||
}
|
||||
}
|
||||
|
||||
free ((Address)l);
|
||||
}
|
98
usr.bin/make/lst.lib/lstDupl.c
Normal file
98
usr.bin/make/lst.lib/lstDupl.c
Normal file
@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Copyright (c) 1988, 1989, 1990, 1993
|
||||
* The Regents of the University of California. 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.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)lstDupl.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif /* not lint */
|
||||
|
||||
/*-
|
||||
* listDupl.c --
|
||||
* Duplicate a list. This includes duplicating the individual
|
||||
* elements.
|
||||
*/
|
||||
|
||||
#include "lstInt.h"
|
||||
|
||||
/*-
|
||||
*-----------------------------------------------------------------------
|
||||
* Lst_Duplicate --
|
||||
* Duplicate an entire list. If a function to copy a ClientData is
|
||||
* given, the individual client elements will be duplicated as well.
|
||||
*
|
||||
* Results:
|
||||
* The new Lst structure or NILLST if failure.
|
||||
*
|
||||
* Side Effects:
|
||||
* A new list is created.
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
Lst
|
||||
Lst_Duplicate (l, copyProc)
|
||||
Lst l; /* the list to duplicate */
|
||||
ClientData (*copyProc)(); /* A function to duplicate each ClientData */
|
||||
{
|
||||
register Lst nl;
|
||||
register ListNode ln;
|
||||
register List list = (List)l;
|
||||
|
||||
if (!LstValid (l)) {
|
||||
return (NILLST);
|
||||
}
|
||||
|
||||
nl = Lst_Init (list->isCirc);
|
||||
if (nl == NILLST) {
|
||||
return (NILLST);
|
||||
}
|
||||
|
||||
ln = list->firstPtr;
|
||||
while (ln != NilListNode) {
|
||||
if (copyProc != NOCOPY) {
|
||||
if (Lst_AtEnd (nl, (*copyProc) (ln->datum)) == FAILURE) {
|
||||
return (NILLST);
|
||||
}
|
||||
} else if (Lst_AtEnd (nl, ln->datum) == FAILURE) {
|
||||
return (NILLST);
|
||||
}
|
||||
|
||||
if (list->isCirc && ln == list->lastPtr) {
|
||||
ln = NilListNode;
|
||||
} else {
|
||||
ln = ln->nextPtr;
|
||||
}
|
||||
}
|
||||
|
||||
return (nl);
|
||||
}
|
73
usr.bin/make/lst.lib/lstEnQueue.c
Normal file
73
usr.bin/make/lst.lib/lstEnQueue.c
Normal file
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright (c) 1988, 1989, 1990, 1993
|
||||
* The Regents of the University of California. 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.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)lstEnQueue.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif /* not lint */
|
||||
|
||||
/*-
|
||||
* LstEnQueue.c--
|
||||
* Treat the list as a queue and place a datum at its end
|
||||
*/
|
||||
|
||||
#include "lstInt.h"
|
||||
|
||||
/*-
|
||||
*-----------------------------------------------------------------------
|
||||
* Lst_EnQueue --
|
||||
* Add the datum to the tail of the given list.
|
||||
*
|
||||
* Results:
|
||||
* SUCCESS or FAILURE as returned by Lst_Append.
|
||||
*
|
||||
* Side Effects:
|
||||
* the lastPtr field is altered all the time and the firstPtr field
|
||||
* will be altered if the list used to be empty.
|
||||
*
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
ReturnStatus
|
||||
Lst_EnQueue (l, d)
|
||||
Lst l;
|
||||
ClientData d;
|
||||
{
|
||||
if (LstValid (l) == FALSE) {
|
||||
return (FAILURE);
|
||||
}
|
||||
|
||||
return (Lst_Append (l, Lst_Last(l), d));
|
||||
}
|
||||
|
70
usr.bin/make/lst.lib/lstFind.c
Normal file
70
usr.bin/make/lst.lib/lstFind.c
Normal file
@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright (c) 1988, 1989, 1990, 1993
|
||||
* The Regents of the University of California. 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.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)lstFind.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif /* not lint */
|
||||
|
||||
/*-
|
||||
* LstFind.c --
|
||||
* Find a node on a list.
|
||||
*/
|
||||
|
||||
#include "lstInt.h"
|
||||
|
||||
/*-
|
||||
*-----------------------------------------------------------------------
|
||||
* Lst_Find --
|
||||
* Find a node on the given list using the given comparison function
|
||||
* and the given datum.
|
||||
*
|
||||
* Results:
|
||||
* The found node or NILLNODE if none matches.
|
||||
*
|
||||
* Side Effects:
|
||||
* None.
|
||||
*
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
LstNode
|
||||
Lst_Find (l, d, cProc)
|
||||
Lst l;
|
||||
ClientData d;
|
||||
int (*cProc)();
|
||||
{
|
||||
return (Lst_FindFrom (l, Lst_First(l), d, cProc));
|
||||
}
|
||||
|
94
usr.bin/make/lst.lib/lstFindFrom.c
Normal file
94
usr.bin/make/lst.lib/lstFindFrom.c
Normal file
@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright (c) 1988, 1989, 1990, 1993
|
||||
* The Regents of the University of California. 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.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)lstFindFrom.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif /* not lint */
|
||||
|
||||
/*-
|
||||
* LstFindFrom.c --
|
||||
* Find a node on a list from a given starting point. Used by Lst_Find.
|
||||
*/
|
||||
|
||||
#include "lstInt.h"
|
||||
|
||||
/*-
|
||||
*-----------------------------------------------------------------------
|
||||
* Lst_FindFrom --
|
||||
* Search for a node starting and ending with the given one on the
|
||||
* given list using the passed datum and comparison function to
|
||||
* determine when it has been found.
|
||||
*
|
||||
* Results:
|
||||
* The found node or NILLNODE
|
||||
*
|
||||
* Side Effects:
|
||||
* None.
|
||||
*
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
LstNode
|
||||
Lst_FindFrom (l, ln, d, cProc)
|
||||
Lst l;
|
||||
register LstNode ln;
|
||||
register ClientData d;
|
||||
register int (*cProc)();
|
||||
{
|
||||
register ListNode tln;
|
||||
Boolean found = FALSE;
|
||||
|
||||
if (!LstValid (l) || LstIsEmpty (l) || !LstNodeValid (ln, l)) {
|
||||
return (NILLNODE);
|
||||
}
|
||||
|
||||
tln = (ListNode)ln;
|
||||
|
||||
do {
|
||||
if ((*cProc) (tln->datum, d) == 0) {
|
||||
found = TRUE;
|
||||
break;
|
||||
} else {
|
||||
tln = tln->nextPtr;
|
||||
}
|
||||
} while (tln != (ListNode)ln && tln != NilListNode);
|
||||
|
||||
if (found) {
|
||||
return ((LstNode)tln);
|
||||
} else {
|
||||
return (NILLNODE);
|
||||
}
|
||||
}
|
||||
|
71
usr.bin/make/lst.lib/lstFirst.c
Normal file
71
usr.bin/make/lst.lib/lstFirst.c
Normal file
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright (c) 1988, 1989, 1990, 1993
|
||||
* The Regents of the University of California. 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.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)lstFirst.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif /* not lint */
|
||||
|
||||
/*-
|
||||
* LstFirst.c --
|
||||
* Return the first node of a list
|
||||
*/
|
||||
|
||||
#include "lstInt.h"
|
||||
|
||||
/*-
|
||||
*-----------------------------------------------------------------------
|
||||
* Lst_First --
|
||||
* Return the first node on the given list.
|
||||
*
|
||||
* Results:
|
||||
* The first node or NILLNODE if the list is empty.
|
||||
*
|
||||
* Side Effects:
|
||||
* None.
|
||||
*
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
LstNode
|
||||
Lst_First (l)
|
||||
Lst l;
|
||||
{
|
||||
if (!LstValid (l) || LstIsEmpty (l)) {
|
||||
return (NILLNODE);
|
||||
} else {
|
||||
return ((LstNode)((List)l)->firstPtr);
|
||||
}
|
||||
}
|
||||
|
72
usr.bin/make/lst.lib/lstForEach.c
Normal file
72
usr.bin/make/lst.lib/lstForEach.c
Normal file
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (c) 1988, 1989, 1990, 1993
|
||||
* The Regents of the University of California. 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.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)lstForEach.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif /* not lint */
|
||||
|
||||
/*-
|
||||
* LstForeach.c --
|
||||
* Perform a given function on all elements of a list.
|
||||
*/
|
||||
|
||||
#include "lstInt.h"
|
||||
|
||||
/*-
|
||||
*-----------------------------------------------------------------------
|
||||
* Lst_ForEach --
|
||||
* Apply the given function to each element of the given list. The
|
||||
* function should return 0 if Lst_ForEach should continue and non-
|
||||
* zero if it should abort.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
*
|
||||
* Side Effects:
|
||||
* Only those created by the passed-in function.
|
||||
*
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
/*VARARGS2*/
|
||||
void
|
||||
Lst_ForEach (l, proc, d)
|
||||
Lst l;
|
||||
register int (*proc)();
|
||||
register ClientData d;
|
||||
{
|
||||
Lst_ForEachFrom(l, Lst_First(l), proc, d);
|
||||
}
|
||||
|
111
usr.bin/make/lst.lib/lstForEachFrom.c
Normal file
111
usr.bin/make/lst.lib/lstForEachFrom.c
Normal file
@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright (c) 1988, 1989, 1990, 1993
|
||||
* The Regents of the University of California. 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.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)lstForEachFrom.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif /* not lint */
|
||||
|
||||
/*-
|
||||
* lstForEachFrom.c --
|
||||
* Perform a given function on all elements of a list starting from
|
||||
* a given point.
|
||||
*/
|
||||
|
||||
#include "lstInt.h"
|
||||
|
||||
/*-
|
||||
*-----------------------------------------------------------------------
|
||||
* Lst_ForEachFrom --
|
||||
* Apply the given function to each element of the given list. The
|
||||
* function should return 0 if traversal should continue and non-
|
||||
* zero if it should abort.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
*
|
||||
* Side Effects:
|
||||
* Only those created by the passed-in function.
|
||||
*
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
/*VARARGS2*/
|
||||
void
|
||||
Lst_ForEachFrom (l, ln, proc, d)
|
||||
Lst l;
|
||||
LstNode ln;
|
||||
register int (*proc)();
|
||||
register ClientData d;
|
||||
{
|
||||
register ListNode tln = (ListNode)ln;
|
||||
register List list = (List)l;
|
||||
register ListNode next;
|
||||
Boolean done;
|
||||
int result;
|
||||
|
||||
if (!LstValid (list) || LstIsEmpty (list)) {
|
||||
return;
|
||||
}
|
||||
|
||||
do {
|
||||
/*
|
||||
* Take care of having the current element deleted out from under
|
||||
* us.
|
||||
*/
|
||||
|
||||
next = tln->nextPtr;
|
||||
|
||||
(void) tln->useCount++;
|
||||
result = (*proc) (tln->datum, d);
|
||||
(void) tln->useCount--;
|
||||
|
||||
/*
|
||||
* We're done with the traversal if
|
||||
* - nothing's been added after the current node and
|
||||
* - the next node to examine is the first in the queue or
|
||||
* doesn't exist.
|
||||
*/
|
||||
done = (next == tln->nextPtr &&
|
||||
(next == NilListNode || next == list->firstPtr));
|
||||
|
||||
next = tln->nextPtr;
|
||||
|
||||
if (tln->flags & LN_DELETED) {
|
||||
free((char *)tln);
|
||||
}
|
||||
tln = next;
|
||||
} while (!result && !LstIsEmpty(list) && !done);
|
||||
|
||||
}
|
76
usr.bin/make/lst.lib/lstInit.c
Normal file
76
usr.bin/make/lst.lib/lstInit.c
Normal file
@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright (c) 1988, 1989, 1990, 1993
|
||||
* The Regents of the University of California. 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.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)lstInit.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif /* not lint */
|
||||
|
||||
/*-
|
||||
* init.c --
|
||||
* Initialize a new linked list.
|
||||
*/
|
||||
|
||||
#include "lstInt.h"
|
||||
|
||||
/*-
|
||||
*-----------------------------------------------------------------------
|
||||
* Lst_Init --
|
||||
* Create and initialize a new list.
|
||||
*
|
||||
* Results:
|
||||
* The created list.
|
||||
*
|
||||
* Side Effects:
|
||||
* A list is created, what else?
|
||||
*
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
Lst
|
||||
Lst_Init(circ)
|
||||
Boolean circ; /* TRUE if the list should be made circular */
|
||||
{
|
||||
register List nList;
|
||||
|
||||
PAlloc (nList, List);
|
||||
|
||||
nList->firstPtr = NilListNode;
|
||||
nList->lastPtr = NilListNode;
|
||||
nList->isOpen = FALSE;
|
||||
nList->isCirc = circ;
|
||||
nList->atEnd = Unknown;
|
||||
|
||||
return ((Lst)nList);
|
||||
}
|
113
usr.bin/make/lst.lib/lstInsert.c
Normal file
113
usr.bin/make/lst.lib/lstInsert.c
Normal file
@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright (c) 1988, 1989, 1990, 1993
|
||||
* The Regents of the University of California. 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.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)lstInsert.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif /* not lint */
|
||||
|
||||
/*-
|
||||
* LstInsert.c --
|
||||
* Insert a new datum before an old one
|
||||
*/
|
||||
|
||||
#include "lstInt.h"
|
||||
|
||||
/*-
|
||||
*-----------------------------------------------------------------------
|
||||
* Lst_Insert --
|
||||
* Insert a new node with the given piece of data before the given
|
||||
* node in the given list.
|
||||
*
|
||||
* Results:
|
||||
* SUCCESS or FAILURE.
|
||||
*
|
||||
* Side Effects:
|
||||
* the firstPtr field will be changed if ln is the first node in the
|
||||
* list.
|
||||
*
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
ReturnStatus
|
||||
Lst_Insert (l, ln, d)
|
||||
Lst l; /* list to manipulate */
|
||||
LstNode ln; /* node before which to insert d */
|
||||
ClientData d; /* datum to be inserted */
|
||||
{
|
||||
register ListNode nLNode; /* new lnode for d */
|
||||
register ListNode lNode = (ListNode)ln;
|
||||
register List list = (List)l;
|
||||
|
||||
|
||||
/*
|
||||
* check validity of arguments
|
||||
*/
|
||||
if (LstValid (l) && (LstIsEmpty (l) && ln == NILLNODE))
|
||||
goto ok;
|
||||
|
||||
if (!LstValid (l) || LstIsEmpty (l) || !LstNodeValid (ln, l)) {
|
||||
return (FAILURE);
|
||||
}
|
||||
|
||||
ok:
|
||||
PAlloc (nLNode, ListNode);
|
||||
|
||||
nLNode->datum = d;
|
||||
nLNode->useCount = nLNode->flags = 0;
|
||||
|
||||
if (ln == NILLNODE) {
|
||||
if (list->isCirc) {
|
||||
nLNode->prevPtr = nLNode->nextPtr = nLNode;
|
||||
} else {
|
||||
nLNode->prevPtr = nLNode->nextPtr = NilListNode;
|
||||
}
|
||||
list->firstPtr = list->lastPtr = nLNode;
|
||||
} else {
|
||||
nLNode->prevPtr = lNode->prevPtr;
|
||||
nLNode->nextPtr = lNode;
|
||||
|
||||
if (nLNode->prevPtr != NilListNode) {
|
||||
nLNode->prevPtr->nextPtr = nLNode;
|
||||
}
|
||||
lNode->prevPtr = nLNode;
|
||||
|
||||
if (lNode == list->firstPtr) {
|
||||
list->firstPtr = nLNode;
|
||||
}
|
||||
}
|
||||
|
||||
return (SUCCESS);
|
||||
}
|
||||
|
110
usr.bin/make/lst.lib/lstInt.h
Normal file
110
usr.bin/make/lst.lib/lstInt.h
Normal file
@ -0,0 +1,110 @@
|
||||
/*
|
||||
* Copyright (c) 1988, 1989, 1990, 1993
|
||||
* The Regents of the University of California. 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.
|
||||
*
|
||||
* @(#)lstInt.h 8.1 (Berkeley) 6/6/93
|
||||
*/
|
||||
|
||||
/*-
|
||||
* lstInt.h --
|
||||
* Internals for the list library
|
||||
*/
|
||||
#ifndef _LSTINT_H_
|
||||
#define _LSTINT_H_
|
||||
|
||||
#include "lst.h"
|
||||
|
||||
typedef struct ListNode {
|
||||
struct ListNode *prevPtr; /* previous element in list */
|
||||
struct ListNode *nextPtr; /* next in list */
|
||||
short useCount:8, /* Count of functions using the node.
|
||||
* node may not be deleted until count
|
||||
* goes to 0 */
|
||||
flags:8; /* Node status flags */
|
||||
ClientData datum; /* datum associated with this element */
|
||||
} *ListNode;
|
||||
/*
|
||||
* Flags required for synchronization
|
||||
*/
|
||||
#define LN_DELETED 0x0001 /* List node should be removed when done */
|
||||
|
||||
#define NilListNode ((ListNode)-1)
|
||||
|
||||
typedef enum {
|
||||
Head, Middle, Tail, Unknown
|
||||
} Where;
|
||||
|
||||
typedef struct {
|
||||
ListNode firstPtr; /* first node in list */
|
||||
ListNode lastPtr; /* last node in list */
|
||||
Boolean isCirc; /* true if the list should be considered
|
||||
* circular */
|
||||
/*
|
||||
* fields for sequential access
|
||||
*/
|
||||
Where atEnd; /* Where in the list the last access was */
|
||||
Boolean isOpen; /* true if list has been Lst_Open'ed */
|
||||
ListNode curPtr; /* current node, if open. NilListNode if
|
||||
* *just* opened */
|
||||
ListNode prevPtr; /* Previous node, if open. Used by
|
||||
* Lst_Remove */
|
||||
} *List;
|
||||
|
||||
#define NilList ((List)-1)
|
||||
|
||||
/*
|
||||
* PAlloc (var, ptype) --
|
||||
* Allocate a pointer-typedef structure 'ptype' into the variable 'var'
|
||||
*/
|
||||
#define PAlloc(var,ptype) var = (ptype) malloc (sizeof (*var))
|
||||
|
||||
/*
|
||||
* LstValid (l) --
|
||||
* Return TRUE if the list l is valid
|
||||
*/
|
||||
#define LstValid(l) (((Lst)l == NILLST) ? FALSE : TRUE)
|
||||
|
||||
/*
|
||||
* LstNodeValid (ln, l) --
|
||||
* Return TRUE if the LstNode ln is valid with respect to l
|
||||
*/
|
||||
#define LstNodeValid(ln, l) ((((LstNode)ln) == NILLNODE) ? FALSE : TRUE)
|
||||
|
||||
/*
|
||||
* LstIsEmpty (l) --
|
||||
* TRUE if the list l is empty.
|
||||
*/
|
||||
#define LstIsEmpty(l) (((List)l)->firstPtr == NilListNode)
|
||||
|
||||
#endif _LSTINT_H_
|
81
usr.bin/make/lst.lib/lstIsAtEnd.c
Normal file
81
usr.bin/make/lst.lib/lstIsAtEnd.c
Normal file
@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (c) 1988, 1989, 1990, 1993
|
||||
* The Regents of the University of California. 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.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)lstIsAtEnd.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif /* not lint */
|
||||
|
||||
/*-
|
||||
* LstIsAtEnd.c --
|
||||
* Tell if the current node is at the end of the list.
|
||||
* The sequential functions access the list in a slightly different way.
|
||||
* CurPtr points to their idea of the current node in the list and they
|
||||
* access the list based on it. Because the list is circular, Lst_Next
|
||||
* and Lst_Prev will go around the list forever. Lst_IsAtEnd must be
|
||||
* used to determine when to stop.
|
||||
*/
|
||||
|
||||
#include "lstInt.h"
|
||||
|
||||
/*-
|
||||
*-----------------------------------------------------------------------
|
||||
* Lst_IsAtEnd --
|
||||
* Return true if have reached the end of the given list.
|
||||
*
|
||||
* Results:
|
||||
* TRUE if at the end of the list (this includes the list not being
|
||||
* open or being invalid) or FALSE if not. We return TRUE if the list
|
||||
* is invalid or unopend so as to cause the caller to exit its loop
|
||||
* asap, the assumption being that the loop is of the form
|
||||
* while (!Lst_IsAtEnd (l)) {
|
||||
* ...
|
||||
* }
|
||||
*
|
||||
* Side Effects:
|
||||
* None.
|
||||
*
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
Boolean
|
||||
Lst_IsAtEnd (l)
|
||||
Lst l;
|
||||
{
|
||||
register List list = (List) l;
|
||||
|
||||
return (!LstValid (l) || !list->isOpen ||
|
||||
(list->atEnd == Head) || (list->atEnd == Tail));
|
||||
}
|
||||
|
69
usr.bin/make/lst.lib/lstIsEmpty.c
Normal file
69
usr.bin/make/lst.lib/lstIsEmpty.c
Normal file
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (c) 1988, 1989, 1990, 1993
|
||||
* The Regents of the University of California. 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.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)lstIsEmpty.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif /* not lint */
|
||||
|
||||
/*-
|
||||
* LstIsEmpty.c --
|
||||
* A single function to decide if a list is empty
|
||||
*/
|
||||
|
||||
#include "lstInt.h"
|
||||
|
||||
/*-
|
||||
*-----------------------------------------------------------------------
|
||||
* Lst_IsEmpty --
|
||||
* Return TRUE if the given list is empty.
|
||||
*
|
||||
* Results:
|
||||
* TRUE if the list is empty, FALSE otherwise.
|
||||
*
|
||||
* Side Effects:
|
||||
* None.
|
||||
*
|
||||
* A list is considered empty if its firstPtr == NilListNode (or if
|
||||
* the list itself is NILLIST).
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
Boolean
|
||||
Lst_IsEmpty (l)
|
||||
Lst l;
|
||||
{
|
||||
return ( ! LstValid (l) || LstIsEmpty(l));
|
||||
}
|
||||
|
71
usr.bin/make/lst.lib/lstLast.c
Normal file
71
usr.bin/make/lst.lib/lstLast.c
Normal file
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright (c) 1988, 1989, 1990, 1993
|
||||
* The Regents of the University of California. 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.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)lstLast.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif /* not lint */
|
||||
|
||||
/*-
|
||||
* LstLast.c --
|
||||
* Return the last element of a list
|
||||
*/
|
||||
|
||||
#include "lstInt.h"
|
||||
|
||||
/*-
|
||||
*-----------------------------------------------------------------------
|
||||
* Lst_Last --
|
||||
* Return the last node on the list l.
|
||||
*
|
||||
* Results:
|
||||
* The requested node or NILLNODE if the list is empty.
|
||||
*
|
||||
* Side Effects:
|
||||
* None.
|
||||
*
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
LstNode
|
||||
Lst_Last (l)
|
||||
Lst l;
|
||||
{
|
||||
if (!LstValid(l) || LstIsEmpty (l)) {
|
||||
return (NILLNODE);
|
||||
} else {
|
||||
return ((LstNode)((List)l)->lastPtr);
|
||||
}
|
||||
}
|
||||
|
69
usr.bin/make/lst.lib/lstMember.c
Normal file
69
usr.bin/make/lst.lib/lstMember.c
Normal file
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (c) 1988, 1989, 1990, 1993
|
||||
* The Regents of the University of California. 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.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)lstMember.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif /* not lint */
|
||||
|
||||
/*-
|
||||
* lstMember.c --
|
||||
* See if a given datum is on a given list.
|
||||
*/
|
||||
|
||||
#include "lstInt.h"
|
||||
|
||||
LstNode
|
||||
Lst_Member (l, d)
|
||||
Lst l;
|
||||
ClientData d;
|
||||
{
|
||||
List list = (List) l;
|
||||
register ListNode lNode;
|
||||
|
||||
lNode = list->firstPtr;
|
||||
if (lNode == NilListNode) {
|
||||
return NILLNODE;
|
||||
}
|
||||
|
||||
do {
|
||||
if (lNode->datum == d) {
|
||||
return (LstNode)lNode;
|
||||
}
|
||||
lNode = lNode->nextPtr;
|
||||
} while (lNode != NilListNode && lNode != list->firstPtr);
|
||||
|
||||
return NILLNODE;
|
||||
}
|
114
usr.bin/make/lst.lib/lstNext.c
Normal file
114
usr.bin/make/lst.lib/lstNext.c
Normal file
@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright (c) 1988, 1989, 1990, 1993
|
||||
* The Regents of the University of California. 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.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)lstNext.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif /* not lint */
|
||||
|
||||
/*-
|
||||
* LstNext.c --
|
||||
* Return the next node for a list.
|
||||
* The sequential functions access the list in a slightly different way.
|
||||
* CurPtr points to their idea of the current node in the list and they
|
||||
* access the list based on it. Because the list is circular, Lst_Next
|
||||
* and Lst_Prev will go around the list forever. Lst_IsAtEnd must be
|
||||
* used to determine when to stop.
|
||||
*/
|
||||
|
||||
#include "lstInt.h"
|
||||
|
||||
/*-
|
||||
*-----------------------------------------------------------------------
|
||||
* Lst_Next --
|
||||
* Return the next node for the given list.
|
||||
*
|
||||
* Results:
|
||||
* The next node or NILLNODE if the list has yet to be opened. Also
|
||||
* if the list is non-circular and the end has been reached, NILLNODE
|
||||
* is returned.
|
||||
*
|
||||
* Side Effects:
|
||||
* the curPtr field is updated.
|
||||
*
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
LstNode
|
||||
Lst_Next (l)
|
||||
Lst l;
|
||||
{
|
||||
register ListNode tln;
|
||||
register List list = (List)l;
|
||||
|
||||
if ((LstValid (l) == FALSE) ||
|
||||
(list->isOpen == FALSE)) {
|
||||
return (NILLNODE);
|
||||
}
|
||||
|
||||
list->prevPtr = list->curPtr;
|
||||
|
||||
if (list->curPtr == NilListNode) {
|
||||
if (list->atEnd == Unknown) {
|
||||
/*
|
||||
* If we're just starting out, atEnd will be Unknown.
|
||||
* Then we want to start this thing off in the right
|
||||
* direction -- at the start with atEnd being Middle.
|
||||
*/
|
||||
list->curPtr = tln = list->firstPtr;
|
||||
list->atEnd = Middle;
|
||||
} else {
|
||||
tln = NilListNode;
|
||||
list->atEnd = Tail;
|
||||
}
|
||||
} else {
|
||||
tln = list->curPtr->nextPtr;
|
||||
list->curPtr = tln;
|
||||
|
||||
if (tln == list->firstPtr || tln == NilListNode) {
|
||||
/*
|
||||
* If back at the front, then we've hit the end...
|
||||
*/
|
||||
list->atEnd = Tail;
|
||||
} else {
|
||||
/*
|
||||
* Reset to Middle if gone past first.
|
||||
*/
|
||||
list->atEnd = Middle;
|
||||
}
|
||||
}
|
||||
|
||||
return ((LstNode)tln);
|
||||
}
|
||||
|
81
usr.bin/make/lst.lib/lstOpen.c
Normal file
81
usr.bin/make/lst.lib/lstOpen.c
Normal file
@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (c) 1988, 1989, 1990, 1993
|
||||
* The Regents of the University of California. 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.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)lstOpen.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif /* not lint */
|
||||
|
||||
/*-
|
||||
* LstOpen.c --
|
||||
* Open a list for sequential access. The sequential functions access the
|
||||
* list in a slightly different way. CurPtr points to their idea of the
|
||||
* current node in the list and they access the list based on it.
|
||||
* If the list is circular, Lst_Next and Lst_Prev will go around
|
||||
* the list forever. Lst_IsAtEnd must be used to determine when to stop.
|
||||
*/
|
||||
|
||||
#include "lstInt.h"
|
||||
|
||||
/*-
|
||||
*-----------------------------------------------------------------------
|
||||
* Lst_Open --
|
||||
* Open a list for sequential access. A list can still be searched,
|
||||
* etc., without confusing these functions.
|
||||
*
|
||||
* Results:
|
||||
* SUCCESS or FAILURE.
|
||||
*
|
||||
* Side Effects:
|
||||
* isOpen is set TRUE and curPtr is set to NilListNode so the
|
||||
* other sequential functions no it was just opened and can choose
|
||||
* the first element accessed based on this.
|
||||
*
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
ReturnStatus
|
||||
Lst_Open (l)
|
||||
register Lst l;
|
||||
{
|
||||
if (LstValid (l) == FALSE) {
|
||||
return (FAILURE);
|
||||
}
|
||||
((List) l)->isOpen = TRUE;
|
||||
((List) l)->atEnd = LstIsEmpty (l) ? Head : Unknown;
|
||||
((List) l)->curPtr = NilListNode;
|
||||
|
||||
return (SUCCESS);
|
||||
}
|
||||
|
131
usr.bin/make/lst.lib/lstRemove.c
Normal file
131
usr.bin/make/lst.lib/lstRemove.c
Normal file
@ -0,0 +1,131 @@
|
||||
/*
|
||||
* Copyright (c) 1988, 1989, 1990, 1993
|
||||
* The Regents of the University of California. 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.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)lstRemove.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif /* not lint */
|
||||
|
||||
/*-
|
||||
* LstRemove.c --
|
||||
* Remove an element from a list
|
||||
*/
|
||||
|
||||
#include "lstInt.h"
|
||||
|
||||
/*-
|
||||
*-----------------------------------------------------------------------
|
||||
* Lst_Remove --
|
||||
* Remove the given node from the given list.
|
||||
*
|
||||
* Results:
|
||||
* SUCCESS or FAILURE.
|
||||
*
|
||||
* Side Effects:
|
||||
* The list's firstPtr will be set to NilListNode if ln is the last
|
||||
* node on the list. firsPtr and lastPtr will be altered if ln is
|
||||
* either the first or last node, respectively, on the list.
|
||||
*
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
ReturnStatus
|
||||
Lst_Remove (l, ln)
|
||||
Lst l;
|
||||
LstNode ln;
|
||||
{
|
||||
register List list = (List) l;
|
||||
register ListNode lNode = (ListNode) ln;
|
||||
|
||||
if (!LstValid (l) ||
|
||||
!LstNodeValid (ln, l)) {
|
||||
return (FAILURE);
|
||||
}
|
||||
|
||||
/*
|
||||
* unlink it from the list
|
||||
*/
|
||||
if (lNode->nextPtr != NilListNode) {
|
||||
lNode->nextPtr->prevPtr = lNode->prevPtr;
|
||||
}
|
||||
if (lNode->prevPtr != NilListNode) {
|
||||
lNode->prevPtr->nextPtr = lNode->nextPtr;
|
||||
}
|
||||
|
||||
/*
|
||||
* if either the firstPtr or lastPtr of the list point to this node,
|
||||
* adjust them accordingly
|
||||
*/
|
||||
if (list->firstPtr == lNode) {
|
||||
list->firstPtr = lNode->nextPtr;
|
||||
}
|
||||
if (list->lastPtr == lNode) {
|
||||
list->lastPtr = lNode->prevPtr;
|
||||
}
|
||||
|
||||
/*
|
||||
* Sequential access stuff. If the node we're removing is the current
|
||||
* node in the list, reset the current node to the previous one. If the
|
||||
* previous one was non-existent (prevPtr == NilListNode), we set the
|
||||
* end to be Unknown, since it is.
|
||||
*/
|
||||
if (list->isOpen && (list->curPtr == lNode)) {
|
||||
list->curPtr = list->prevPtr;
|
||||
if (list->curPtr == NilListNode) {
|
||||
list->atEnd = Unknown;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* the only way firstPtr can still point to ln is if ln is the last
|
||||
* node on the list (the list is circular, so lNode->nextptr == lNode in
|
||||
* this case). The list is, therefore, empty and is marked as such
|
||||
*/
|
||||
if (list->firstPtr == lNode) {
|
||||
list->firstPtr = NilListNode;
|
||||
}
|
||||
|
||||
/*
|
||||
* note that the datum is unmolested. The caller must free it as
|
||||
* necessary and as expected.
|
||||
*/
|
||||
if (lNode->useCount == 0) {
|
||||
free ((Address)ln);
|
||||
} else {
|
||||
lNode->flags |= LN_DELETED;
|
||||
}
|
||||
|
||||
return (SUCCESS);
|
||||
}
|
||||
|
73
usr.bin/make/lst.lib/lstReplace.c
Normal file
73
usr.bin/make/lst.lib/lstReplace.c
Normal file
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright (c) 1988, 1989, 1990, 1993
|
||||
* The Regents of the University of California. 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.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)lstReplace.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif /* not lint */
|
||||
|
||||
/*-
|
||||
* LstReplace.c --
|
||||
* Replace the datum in a node with a new datum
|
||||
*/
|
||||
|
||||
#include "lstInt.h"
|
||||
|
||||
/*-
|
||||
*-----------------------------------------------------------------------
|
||||
* Lst_Replace --
|
||||
* Replace the datum in the given node with the new datum
|
||||
*
|
||||
* Results:
|
||||
* SUCCESS or FAILURE.
|
||||
*
|
||||
* Side Effects:
|
||||
* The datum field fo the node is altered.
|
||||
*
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
ReturnStatus
|
||||
Lst_Replace (ln, d)
|
||||
register LstNode ln;
|
||||
ClientData d;
|
||||
{
|
||||
if (ln == NILLNODE) {
|
||||
return (FAILURE);
|
||||
} else {
|
||||
((ListNode) ln)->datum = d;
|
||||
return (SUCCESS);
|
||||
}
|
||||
}
|
||||
|
73
usr.bin/make/lst.lib/lstSucc.c
Normal file
73
usr.bin/make/lst.lib/lstSucc.c
Normal file
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright (c) 1988, 1989, 1990, 1993
|
||||
* The Regents of the University of California. 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.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)lstSucc.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif /* not lint */
|
||||
|
||||
/*-
|
||||
* LstSucc.c --
|
||||
* return the successor to a given node
|
||||
*/
|
||||
|
||||
#include "lstInt.h"
|
||||
|
||||
/*-
|
||||
*-----------------------------------------------------------------------
|
||||
* Lst_Succ --
|
||||
* Return the sucessor to the given node on its list.
|
||||
*
|
||||
* Results:
|
||||
* The successor of the node, if it exists (note that on a circular
|
||||
* list, if the node is the only one in the list, it is its own
|
||||
* successor).
|
||||
*
|
||||
* Side Effects:
|
||||
* None.
|
||||
*
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
LstNode
|
||||
Lst_Succ (ln)
|
||||
LstNode ln;
|
||||
{
|
||||
if (ln == NILLNODE) {
|
||||
return (NILLNODE);
|
||||
} else {
|
||||
return ((LstNode) ((ListNode) ln)->nextPtr);
|
||||
}
|
||||
}
|
||||
|
911
usr.bin/make/main.c
Normal file
911
usr.bin/make/main.c
Normal file
@ -0,0 +1,911 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char copyright[] =
|
||||
"@(#) Copyright (c) 1988, 1989, 1990, 1993\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)main.c 8.3 (Berkeley) 3/19/94";
|
||||
#endif /* not lint */
|
||||
|
||||
/*-
|
||||
* main.c --
|
||||
* The main file for this entire program. Exit routines etc
|
||||
* reside here.
|
||||
*
|
||||
* Utility functions defined in this file:
|
||||
* Main_ParseArgLine Takes a line of arguments, breaks them and
|
||||
* treats them as if they were given when first
|
||||
* invoked. Used by the parse module to implement
|
||||
* the .MFLAGS target.
|
||||
*
|
||||
* Error Print a tagged error message. The global
|
||||
* MAKE variable must have been defined. This
|
||||
* takes a format string and two optional
|
||||
* arguments for it.
|
||||
*
|
||||
* Fatal Print an error message and exit. Also takes
|
||||
* a format string and two arguments.
|
||||
*
|
||||
* Punt Aborts all jobs and exits with a message. Also
|
||||
* takes a format string and two arguments.
|
||||
*
|
||||
* Finish Finish things up by printing the number of
|
||||
* errors which occured, as passed to it, and
|
||||
* exiting.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/signal.h>
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#if __STDC__
|
||||
#include <stdarg.h>
|
||||
#else
|
||||
#include <varargs.h>
|
||||
#endif
|
||||
#include "make.h"
|
||||
#include "hash.h"
|
||||
#include "dir.h"
|
||||
#include "job.h"
|
||||
#include "pathnames.h"
|
||||
|
||||
#ifndef DEFMAXLOCAL
|
||||
#define DEFMAXLOCAL DEFMAXJOBS
|
||||
#endif DEFMAXLOCAL
|
||||
|
||||
#define MAKEFLAGS ".MAKEFLAGS"
|
||||
|
||||
Lst create; /* Targets to be made */
|
||||
time_t now; /* Time at start of make */
|
||||
GNode *DEFAULT; /* .DEFAULT node */
|
||||
Boolean allPrecious; /* .PRECIOUS given on line by itself */
|
||||
|
||||
static Boolean noBuiltins; /* -r flag */
|
||||
static Lst makefiles; /* ordered list of makefiles to read */
|
||||
int maxJobs; /* -J argument */
|
||||
static int maxLocal; /* -L argument */
|
||||
Boolean compatMake; /* -B argument */
|
||||
Boolean debug; /* -d flag */
|
||||
Boolean noExecute; /* -n flag */
|
||||
Boolean keepgoing; /* -k flag */
|
||||
Boolean queryFlag; /* -q flag */
|
||||
Boolean touchFlag; /* -t flag */
|
||||
Boolean usePipes; /* !-P flag */
|
||||
Boolean ignoreErrors; /* -i flag */
|
||||
Boolean beSilent; /* -s flag */
|
||||
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 char *curdir; /* startup directory */
|
||||
static char *objdir; /* where we chdir'ed to */
|
||||
|
||||
/*-
|
||||
* MainParseArgs --
|
||||
* Parse a given argument vector. Called from main() and from
|
||||
* Main_ParseArgLine() when the .MAKEFLAGS target is used.
|
||||
*
|
||||
* XXX: Deal with command line overriding .MAKEFLAGS in makefile
|
||||
*
|
||||
* Results:
|
||||
* None
|
||||
*
|
||||
* Side Effects:
|
||||
* Various global and local flags will be set depending on the flags
|
||||
* given
|
||||
*/
|
||||
static void
|
||||
MainParseArgs(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
extern int optind;
|
||||
extern char *optarg;
|
||||
char c;
|
||||
|
||||
optind = 1; /* since we're called more than once */
|
||||
#ifdef notyet
|
||||
# define OPTFLAGS "BD:I:L:PSd:ef:ij:knqrst"
|
||||
#else
|
||||
# define OPTFLAGS "D:I:d:ef:ij:knqrst"
|
||||
#endif
|
||||
rearg: while ((c = getopt(argc, argv, OPTFLAGS)) != EOF) {
|
||||
switch(c) {
|
||||
case 'D':
|
||||
Var_Set(optarg, "1", VAR_GLOBAL);
|
||||
Var_Append(MAKEFLAGS, "-D", VAR_GLOBAL);
|
||||
Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
|
||||
break;
|
||||
case 'I':
|
||||
Parse_AddIncludeDir(optarg);
|
||||
Var_Append(MAKEFLAGS, "-I", VAR_GLOBAL);
|
||||
Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
|
||||
break;
|
||||
#ifdef notyet
|
||||
case 'B':
|
||||
compatMake = TRUE;
|
||||
break;
|
||||
case 'L':
|
||||
maxLocal = atoi(optarg);
|
||||
Var_Append(MAKEFLAGS, "-L", VAR_GLOBAL);
|
||||
Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
|
||||
break;
|
||||
case 'P':
|
||||
usePipes = FALSE;
|
||||
Var_Append(MAKEFLAGS, "-P", VAR_GLOBAL);
|
||||
break;
|
||||
case 'S':
|
||||
keepgoing = FALSE;
|
||||
Var_Append(MAKEFLAGS, "-S", VAR_GLOBAL);
|
||||
break;
|
||||
#endif
|
||||
case 'd': {
|
||||
char *modules = optarg;
|
||||
|
||||
for (; *modules; ++modules)
|
||||
switch (*modules) {
|
||||
case 'A':
|
||||
debug = ~0;
|
||||
break;
|
||||
case 'a':
|
||||
debug |= DEBUG_ARCH;
|
||||
break;
|
||||
case 'c':
|
||||
debug |= DEBUG_COND;
|
||||
break;
|
||||
case 'd':
|
||||
debug |= DEBUG_DIR;
|
||||
break;
|
||||
case 'f':
|
||||
debug |= DEBUG_FOR;
|
||||
break;
|
||||
case 'g':
|
||||
if (modules[1] == '1') {
|
||||
debug |= DEBUG_GRAPH1;
|
||||
++modules;
|
||||
}
|
||||
else if (modules[1] == '2') {
|
||||
debug |= DEBUG_GRAPH2;
|
||||
++modules;
|
||||
}
|
||||
break;
|
||||
case 'j':
|
||||
debug |= DEBUG_JOB;
|
||||
break;
|
||||
case 'm':
|
||||
debug |= DEBUG_MAKE;
|
||||
break;
|
||||
case 's':
|
||||
debug |= DEBUG_SUFF;
|
||||
break;
|
||||
case 't':
|
||||
debug |= DEBUG_TARG;
|
||||
break;
|
||||
case 'v':
|
||||
debug |= DEBUG_VAR;
|
||||
break;
|
||||
default:
|
||||
(void)fprintf(stderr,
|
||||
"make: illegal argument to d option -- %c\n",
|
||||
*modules);
|
||||
usage();
|
||||
}
|
||||
Var_Append(MAKEFLAGS, "-d", VAR_GLOBAL);
|
||||
Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
|
||||
break;
|
||||
}
|
||||
case 'e':
|
||||
checkEnvFirst = TRUE;
|
||||
Var_Append(MAKEFLAGS, "-e", VAR_GLOBAL);
|
||||
break;
|
||||
case 'f':
|
||||
(void)Lst_AtEnd(makefiles, (ClientData)optarg);
|
||||
break;
|
||||
case 'i':
|
||||
ignoreErrors = TRUE;
|
||||
Var_Append(MAKEFLAGS, "-i", VAR_GLOBAL);
|
||||
break;
|
||||
case 'j':
|
||||
maxJobs = atoi(optarg);
|
||||
Var_Append(MAKEFLAGS, "-j", VAR_GLOBAL);
|
||||
Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
|
||||
break;
|
||||
case 'k':
|
||||
keepgoing = TRUE;
|
||||
Var_Append(MAKEFLAGS, "-k", VAR_GLOBAL);
|
||||
break;
|
||||
case 'n':
|
||||
noExecute = TRUE;
|
||||
Var_Append(MAKEFLAGS, "-n", VAR_GLOBAL);
|
||||
break;
|
||||
case 'q':
|
||||
queryFlag = TRUE;
|
||||
/* Kind of nonsensical, wot? */
|
||||
Var_Append(MAKEFLAGS, "-q", VAR_GLOBAL);
|
||||
break;
|
||||
case 'r':
|
||||
noBuiltins = TRUE;
|
||||
Var_Append(MAKEFLAGS, "-r", VAR_GLOBAL);
|
||||
break;
|
||||
case 's':
|
||||
beSilent = TRUE;
|
||||
Var_Append(MAKEFLAGS, "-s", VAR_GLOBAL);
|
||||
break;
|
||||
case 't':
|
||||
touchFlag = TRUE;
|
||||
Var_Append(MAKEFLAGS, "-t", VAR_GLOBAL);
|
||||
break;
|
||||
default:
|
||||
case '?':
|
||||
usage();
|
||||
}
|
||||
}
|
||||
|
||||
oldVars = TRUE;
|
||||
|
||||
/*
|
||||
* See if the rest of the arguments are variable assignments and
|
||||
* perform them if so. Else take them to be targets and stuff them
|
||||
* on the end of the "create" list.
|
||||
*/
|
||||
for (argv += optind, argc -= optind; *argv; ++argv, --argc)
|
||||
if (Parse_IsVar(*argv))
|
||||
Parse_DoVar(*argv, VAR_CMD);
|
||||
else {
|
||||
if (!**argv)
|
||||
Punt("illegal (null) argument.");
|
||||
if (**argv == '-') {
|
||||
if ((*argv)[1])
|
||||
optind = 0; /* -flag... */
|
||||
else
|
||||
optind = 1; /* - */
|
||||
goto rearg;
|
||||
}
|
||||
(void)Lst_AtEnd(create, (ClientData)*argv);
|
||||
}
|
||||
}
|
||||
|
||||
/*-
|
||||
* Main_ParseArgLine --
|
||||
* Used by the parse module when a .MFLAGS or .MAKEFLAGS target
|
||||
* is encountered and by main() when reading the .MAKEFLAGS envariable.
|
||||
* Takes a line of arguments and breaks it into its
|
||||
* component words and passes those words and the number of them to the
|
||||
* MainParseArgs function.
|
||||
* The line should have all its leading whitespace removed.
|
||||
*
|
||||
* Results:
|
||||
* None
|
||||
*
|
||||
* Side Effects:
|
||||
* Only those that come from the various arguments.
|
||||
*/
|
||||
void
|
||||
Main_ParseArgLine(line)
|
||||
char *line; /* Line to fracture */
|
||||
{
|
||||
char **argv; /* Manufactured argument vector */
|
||||
int argc; /* Number of arguments in argv */
|
||||
|
||||
if (line == NULL)
|
||||
return;
|
||||
for (; *line == ' '; ++line)
|
||||
continue;
|
||||
if (!*line)
|
||||
return;
|
||||
|
||||
argv = brk_string(line, &argc);
|
||||
MainParseArgs(argc, argv);
|
||||
}
|
||||
|
||||
/*-
|
||||
* main --
|
||||
* The main function, for obvious reasons. Initializes variables
|
||||
* and a few modules, then parses the arguments give it in the
|
||||
* environment and on the command line. Reads the system makefile
|
||||
* followed by either Makefile, makefile or the file given by the
|
||||
* -f argument. Sets the .MAKEFLAGS PMake variable based on all the
|
||||
* flags it has received by then uses either the Make or the Compat
|
||||
* module to create the initial list of targets.
|
||||
*
|
||||
* Results:
|
||||
* If -q was given, exits -1 if anything was out-of-date. Else it exits
|
||||
* 0.
|
||||
*
|
||||
* Side Effects:
|
||||
* The program exits when done. Targets are created. etc. etc. etc.
|
||||
*/
|
||||
int
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char **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, *path, *pwd, *getenv(), *getwd();
|
||||
char mdpath[MAXPATHLEN + 1];
|
||||
char obpath[MAXPATHLEN + 1];
|
||||
char cdpath[MAXPATHLEN + 1];
|
||||
|
||||
/*
|
||||
* 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
|
||||
* on a different machine with pmake.
|
||||
*/
|
||||
curdir = cdpath;
|
||||
if (getwd(curdir) == NULL) {
|
||||
(void)fprintf(stderr, "make: %s.\n", curdir);
|
||||
exit(2);
|
||||
}
|
||||
|
||||
if (stat(curdir, &sa) == -1) {
|
||||
(void)fprintf(stderr, "make: %s: %s.\n",
|
||||
curdir, strerror(errno));
|
||||
exit(2);
|
||||
}
|
||||
|
||||
if ((pwd = getenv("PWD")) != NULL) {
|
||||
if (stat(pwd, &sb) == 0 && sa.st_ino == sb.st_ino &&
|
||||
sa.st_dev == sb.st_dev)
|
||||
(void) strcpy(curdir, pwd);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* if the MAKEOBJDIR (or by default, the _PATH_OBJDIR) directory
|
||||
* exists, change into it and build there. Once things are
|
||||
* initted, have to add the original directory to the search path,
|
||||
* and modify the paths for the Makefiles apropriately. The
|
||||
* current directory is also placed as a variable for make scripts.
|
||||
*/
|
||||
if (!(path = getenv("MAKEOBJDIR"))) {
|
||||
path = _PATH_OBJDIR;
|
||||
(void) sprintf(mdpath, "%s.%s", path, MACHINE);
|
||||
}
|
||||
else
|
||||
(void) strncpy(mdpath, path, MAXPATHLEN + 1);
|
||||
|
||||
if (stat(mdpath, &sb) == 0 && S_ISDIR(sb.st_mode)) {
|
||||
|
||||
if (chdir(mdpath)) {
|
||||
(void)fprintf(stderr, "make warning: %s: %s.\n",
|
||||
mdpath, strerror(errno));
|
||||
objdir = curdir;
|
||||
}
|
||||
else {
|
||||
if (mdpath[0] != '/') {
|
||||
(void) sprintf(obpath, "%s/%s", curdir, mdpath);
|
||||
objdir = obpath;
|
||||
}
|
||||
else
|
||||
objdir = mdpath;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)) {
|
||||
|
||||
if (chdir(path)) {
|
||||
(void)fprintf(stderr, "make warning: %s: %s.\n",
|
||||
path, strerror(errno));
|
||||
objdir = curdir;
|
||||
}
|
||||
else {
|
||||
if (path[0] != '/') {
|
||||
(void) sprintf(obpath, "%s/%s", curdir,
|
||||
path);
|
||||
objdir = obpath;
|
||||
}
|
||||
else
|
||||
objdir = obpath;
|
||||
}
|
||||
}
|
||||
else
|
||||
objdir = curdir;
|
||||
}
|
||||
|
||||
setenv("PWD", objdir, 1);
|
||||
|
||||
create = Lst_Init(FALSE);
|
||||
makefiles = Lst_Init(FALSE);
|
||||
beSilent = FALSE; /* Print commands as executed */
|
||||
ignoreErrors = FALSE; /* Pay attention to non-zero returns */
|
||||
noExecute = FALSE; /* Execute all commands */
|
||||
keepgoing = FALSE; /* Stop on error */
|
||||
allPrecious = FALSE; /* Remove targets when interrupted */
|
||||
queryFlag = FALSE; /* This is not just a check-run */
|
||||
noBuiltins = FALSE; /* Read the built-in rules */
|
||||
touchFlag = FALSE; /* Actually update targets */
|
||||
usePipes = TRUE; /* Catch child output in pipes */
|
||||
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 */
|
||||
#else
|
||||
compatMake = TRUE; /* No compat mode */
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Initialize the parsing, directory and variable modules to prepare
|
||||
* for the reading of inclusion paths and variable settings on the
|
||||
* command line
|
||||
*/
|
||||
Dir_Init(); /* Initialize directory structures so -I flags
|
||||
* can be processed correctly */
|
||||
Parse_Init(); /* Need to initialize the paths of #include
|
||||
* directories */
|
||||
Var_Init(); /* As well as the lists of variables for
|
||||
* parsing arguments */
|
||||
if (objdir != curdir)
|
||||
Dir_AddDir(dirSearchPath, curdir);
|
||||
Var_Set(".CURDIR", curdir, VAR_GLOBAL);
|
||||
Var_Set(".OBJDIR", objdir, VAR_GLOBAL);
|
||||
|
||||
/*
|
||||
* Initialize various variables.
|
||||
* MAKE also gets this name, for compatibility
|
||||
* .MAKEFLAGS gets set to the empty string just in case.
|
||||
* MFLAGS also gets initialized empty, for compatibility.
|
||||
*/
|
||||
Var_Set("MAKE", argv[0], VAR_GLOBAL);
|
||||
Var_Set(MAKEFLAGS, "", VAR_GLOBAL);
|
||||
Var_Set("MFLAGS", "", VAR_GLOBAL);
|
||||
#ifdef MACHINE
|
||||
Var_Set("MACHINE", MACHINE, VAR_GLOBAL);
|
||||
#endif
|
||||
#ifdef MACHINE_ARCH
|
||||
Var_Set("MACHINE_ARCH", MACHINE_ARCH, VAR_GLOBAL);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* First snag any flags out of the MAKE environment variable.
|
||||
* (Note this is *not* MAKEFLAGS since /bin/make uses that and it's
|
||||
* in a different format).
|
||||
*/
|
||||
#ifdef POSIX
|
||||
Main_ParseArgLine(getenv("MAKEFLAGS"));
|
||||
#else
|
||||
Main_ParseArgLine(getenv("MAKE"));
|
||||
#endif
|
||||
|
||||
MainParseArgs(argc, argv);
|
||||
|
||||
/*
|
||||
* Initialize archive, target and suffix modules in preparation for
|
||||
* parsing the makefile(s)
|
||||
*/
|
||||
Arch_Init();
|
||||
Targ_Init();
|
||||
Suff_Init();
|
||||
|
||||
DEFAULT = NILGNODE;
|
||||
(void)time(&now);
|
||||
|
||||
/*
|
||||
* Set up the .TARGETS variable to contain the list of targets to be
|
||||
* created. If none specified, make the variable empty -- the parser
|
||||
* will fill the thing in with the default or .MAIN target.
|
||||
*/
|
||||
if (!Lst_IsEmpty(create)) {
|
||||
LstNode ln;
|
||||
|
||||
for (ln = Lst_First(create); ln != NILLNODE;
|
||||
ln = Lst_Succ(ln)) {
|
||||
char *name = (char *)Lst_Datum(ln);
|
||||
|
||||
Var_Append(".TARGETS", name, VAR_GLOBAL);
|
||||
}
|
||||
} 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 (!noBuiltins && !ReadMakefile(_PATH_DEFSYSMK))
|
||||
Fatal("make: no system rules (%s).", _PATH_DEFSYSMK);
|
||||
|
||||
if (!Lst_IsEmpty(makefiles)) {
|
||||
LstNode ln;
|
||||
|
||||
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");
|
||||
|
||||
(void)ReadMakefile(".depend");
|
||||
|
||||
Var_Append("MFLAGS", Var_Value(MAKEFLAGS, VAR_GLOBAL), VAR_GLOBAL);
|
||||
|
||||
/* Install all the flags into the MAKE envariable. */
|
||||
if (((p = Var_Value(MAKEFLAGS, VAR_GLOBAL)) != NULL) && *p)
|
||||
#ifdef POSIX
|
||||
setenv("MAKEFLAGS", p, 1);
|
||||
#else
|
||||
setenv("MAKE", p, 1);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* For compatibility, look at the directories in the VPATH variable
|
||||
* and add them to the search path, if the variable is defined. The
|
||||
* variable's value is in the same format as the PATH envariable, i.e.
|
||||
* <directory>:<directory>:<directory>...
|
||||
*/
|
||||
if (Var_Exists("VPATH", VAR_CMD)) {
|
||||
char *vpath, *path, *cp, savec;
|
||||
/*
|
||||
* GCC stores string constants in read-only memory, but
|
||||
* Var_Subst will want to write this thing, so store it
|
||||
* in an array
|
||||
*/
|
||||
static char VPATH[] = "${VPATH}";
|
||||
|
||||
vpath = Var_Subst(NULL, VPATH, VAR_CMD, FALSE);
|
||||
path = vpath;
|
||||
do {
|
||||
/* skip to end of directory */
|
||||
for (cp = path; *cp != ':' && *cp != '\0'; cp++)
|
||||
continue;
|
||||
/* Save terminator character so know when to stop */
|
||||
savec = *cp;
|
||||
*cp = '\0';
|
||||
/* Add directory to search path */
|
||||
Dir_AddDir(dirSearchPath, path);
|
||||
*cp = savec;
|
||||
path = cp + 1;
|
||||
} while (savec == ':');
|
||||
(void)free((Address)vpath);
|
||||
}
|
||||
|
||||
/*
|
||||
* Now that all search paths have been read for suffixes et al, it's
|
||||
* time to add the default search path to their lists...
|
||||
*/
|
||||
Suff_DoPaths();
|
||||
|
||||
/* print the initial graph, if the user requested it */
|
||||
if (DEBUG(GRAPH1))
|
||||
Targ_PrintGraph(1);
|
||||
|
||||
/*
|
||||
* Have now read the entire graph and need to make a list of targets
|
||||
* to create. If none was given on the command line, we consult the
|
||||
* parsing module to find the main target(s) to create.
|
||||
*/
|
||||
if (Lst_IsEmpty(create))
|
||||
targs = Parse_MainName();
|
||||
else
|
||||
targs = Targ_FindList(create, TARG_CREATE);
|
||||
|
||||
/*
|
||||
* this was original amMake -- want to allow parallelism, so put this
|
||||
* back in, eventually.
|
||||
*/
|
||||
if (!compatMake) {
|
||||
/*
|
||||
* Initialize job module before traversing the graph, now that
|
||||
* any .BEGIN and .END targets have been read. This is done
|
||||
* only if the -q flag wasn't given (to prevent the .BEGIN from
|
||||
* being executed should it exist).
|
||||
*/
|
||||
if (!queryFlag) {
|
||||
if (maxLocal == -1)
|
||||
maxLocal = maxJobs;
|
||||
Job_Init(maxJobs, maxLocal);
|
||||
jobsRunning = TRUE;
|
||||
}
|
||||
|
||||
/* Traverse the graph, checking on all the targets */
|
||||
outOfDate = Make_Run(targs);
|
||||
} else
|
||||
/*
|
||||
* Compat_Init will take care of creating all the targets as
|
||||
* well as initializing the module.
|
||||
*/
|
||||
Compat_Run(targs);
|
||||
|
||||
/* print the graph now it's been processed if the user requested it */
|
||||
if (DEBUG(GRAPH2))
|
||||
Targ_PrintGraph(2);
|
||||
|
||||
if (queryFlag && outOfDate)
|
||||
return(1);
|
||||
else
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*-
|
||||
* ReadMakefile --
|
||||
* Open and parse the given makefile.
|
||||
*
|
||||
* Results:
|
||||
* TRUE if ok. FALSE if couldn't open file.
|
||||
*
|
||||
* Side Effects:
|
||||
* lots
|
||||
*/
|
||||
static Boolean
|
||||
ReadMakefile(fname)
|
||||
char *fname; /* makefile to read */
|
||||
{
|
||||
extern Lst parseIncPath, sysIncPath;
|
||||
FILE *stream;
|
||||
char *name, path[MAXPATHLEN + 1];
|
||||
|
||||
if (!strcmp(fname, "-")) {
|
||||
Parse_File("(stdin)", stdin);
|
||||
Var_Set("MAKEFILE", "", VAR_GLOBAL);
|
||||
} else {
|
||||
if ((stream = fopen(fname, "r")) != NULL)
|
||||
goto found;
|
||||
/* if we've chdir'd, rebuild the path name */
|
||||
if (curdir != objdir && *fname != '/') {
|
||||
(void)sprintf(path, "%s/%s", curdir, fname);
|
||||
if ((stream = fopen(path, "r")) != NULL) {
|
||||
fname = path;
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
/* look in -I and system include directories. */
|
||||
name = Dir_FindFile(fname, parseIncPath);
|
||||
if (!name)
|
||||
name = Dir_FindFile(fname, sysIncPath);
|
||||
if (!name || !(stream = fopen(name, "r")))
|
||||
return(FALSE);
|
||||
fname = name;
|
||||
/*
|
||||
* set the MAKEFILE variable desired by System V fans -- the
|
||||
* placement of the setting here means it gets set to the last
|
||||
* makefile specified, as it is set by SysV make.
|
||||
*/
|
||||
found: Var_Set("MAKEFILE", fname, VAR_GLOBAL);
|
||||
Parse_File(fname, stream);
|
||||
(void)fclose(stream);
|
||||
}
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/*-
|
||||
* Error --
|
||||
* Print an error message given its format.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
*
|
||||
* Side Effects:
|
||||
* The message is printed.
|
||||
*/
|
||||
/* VARARGS */
|
||||
void
|
||||
#if __STDC__
|
||||
Error(const char *fmt, ...)
|
||||
#else
|
||||
Error(va_alist)
|
||||
va_dcl
|
||||
#endif
|
||||
{
|
||||
va_list ap;
|
||||
#if __STDC__
|
||||
va_start(ap, fmt);
|
||||
#else
|
||||
char *fmt;
|
||||
|
||||
va_start(ap);
|
||||
fmt = va_arg(ap, char *);
|
||||
#endif
|
||||
(void)vfprintf(stderr, fmt, ap);
|
||||
va_end(ap);
|
||||
(void)fprintf(stderr, "\n");
|
||||
(void)fflush(stderr);
|
||||
}
|
||||
|
||||
/*-
|
||||
* Fatal --
|
||||
* Produce a Fatal error message. If jobs are running, waits for them
|
||||
* to finish.
|
||||
*
|
||||
* Results:
|
||||
* None
|
||||
*
|
||||
* Side Effects:
|
||||
* The program exits
|
||||
*/
|
||||
/* VARARGS */
|
||||
void
|
||||
#if __STDC__
|
||||
Fatal(const char *fmt, ...)
|
||||
#else
|
||||
Fatal(va_alist)
|
||||
va_dcl
|
||||
#endif
|
||||
{
|
||||
va_list ap;
|
||||
#if __STDC__
|
||||
va_start(ap, fmt);
|
||||
#else
|
||||
char *fmt;
|
||||
|
||||
va_start(ap);
|
||||
fmt = va_arg(ap, char *);
|
||||
#endif
|
||||
if (jobsRunning)
|
||||
Job_Wait();
|
||||
|
||||
(void)vfprintf(stderr, fmt, ap);
|
||||
va_end(ap);
|
||||
(void)fprintf(stderr, "\n");
|
||||
(void)fflush(stderr);
|
||||
|
||||
if (DEBUG(GRAPH2))
|
||||
Targ_PrintGraph(2);
|
||||
exit(2); /* Not 1 so -q can distinguish error */
|
||||
}
|
||||
|
||||
/*
|
||||
* Punt --
|
||||
* Major exception once jobs are being created. Kills all jobs, prints
|
||||
* a message and exits.
|
||||
*
|
||||
* Results:
|
||||
* None
|
||||
*
|
||||
* Side Effects:
|
||||
* All children are killed indiscriminately and the program Lib_Exits
|
||||
*/
|
||||
/* VARARGS */
|
||||
void
|
||||
#if __STDC__
|
||||
Punt(const char *fmt, ...)
|
||||
#else
|
||||
Punt(va_alist)
|
||||
va_dcl
|
||||
#endif
|
||||
{
|
||||
va_list ap;
|
||||
#if __STDC__
|
||||
va_start(ap, fmt);
|
||||
#else
|
||||
char *fmt;
|
||||
|
||||
va_start(ap);
|
||||
fmt = va_arg(ap, char *);
|
||||
#endif
|
||||
|
||||
(void)fprintf(stderr, "make: ");
|
||||
(void)vfprintf(stderr, fmt, ap);
|
||||
va_end(ap);
|
||||
(void)fprintf(stderr, "\n");
|
||||
(void)fflush(stderr);
|
||||
|
||||
DieHorribly();
|
||||
}
|
||||
|
||||
/*-
|
||||
* DieHorribly --
|
||||
* Exit without giving a message.
|
||||
*
|
||||
* Results:
|
||||
* None
|
||||
*
|
||||
* Side Effects:
|
||||
* A big one...
|
||||
*/
|
||||
void
|
||||
DieHorribly()
|
||||
{
|
||||
if (jobsRunning)
|
||||
Job_AbortAll();
|
||||
if (DEBUG(GRAPH2))
|
||||
Targ_PrintGraph(2);
|
||||
exit(2); /* Not 1, so -q can distinguish error */
|
||||
}
|
||||
|
||||
/*
|
||||
* Finish --
|
||||
* Called when aborting due to errors in child shell to signal
|
||||
* abnormal exit.
|
||||
*
|
||||
* Results:
|
||||
* None
|
||||
*
|
||||
* Side Effects:
|
||||
* The program exits
|
||||
*/
|
||||
void
|
||||
Finish(errors)
|
||||
int errors; /* number of errors encountered in Make_Make */
|
||||
{
|
||||
Fatal("%d error%s", errors, errors == 1 ? "" : "s");
|
||||
}
|
||||
|
||||
/*
|
||||
* emalloc --
|
||||
* malloc, but die on error.
|
||||
*/
|
||||
char *
|
||||
emalloc(len)
|
||||
u_int len;
|
||||
{
|
||||
char *p;
|
||||
|
||||
if (!(p = malloc(len)))
|
||||
enomem();
|
||||
return(p);
|
||||
}
|
||||
|
||||
/*
|
||||
* enomem --
|
||||
* die when out of memory.
|
||||
*/
|
||||
void
|
||||
enomem()
|
||||
{
|
||||
(void)fprintf(stderr, "make: %s.\n", strerror(errno));
|
||||
exit(2);
|
||||
}
|
||||
|
||||
/*
|
||||
* usage --
|
||||
* exit with usage message
|
||||
*/
|
||||
static void
|
||||
usage()
|
||||
{
|
||||
(void)fprintf(stderr,
|
||||
"usage: make [-eiknqrst] [-D variable] [-d flags] [-f makefile ]\n\
|
||||
[-I directory] [-j max_jobs] [variable=value]\n");
|
||||
exit(2);
|
||||
}
|
883
usr.bin/make/make.1
Normal file
883
usr.bin/make/make.1
Normal file
@ -0,0 +1,883 @@
|
||||
.\" Copyright (c) 1990, 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
.\"
|
||||
.\" 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.
|
||||
.\"
|
||||
.\" @(#)make.1 8.4 (Berkeley) 3/19/94
|
||||
.\"
|
||||
.Dd March 19, 1994
|
||||
.Dt MAKE 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm make
|
||||
.Nd maintain program dependencies
|
||||
.Sh SYNOPSIS
|
||||
.Nm make
|
||||
.Op Fl eiknqrstv
|
||||
.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
|
||||
.Ek
|
||||
.Op Ar variable=value
|
||||
.Op Ar target ...
|
||||
.Sh DESCRIPTION
|
||||
.Nm Make
|
||||
is a program designed to simplify the maintenance of other programs.
|
||||
Its input is a list of specifications as to the files upon which programs
|
||||
and other files depend.
|
||||
If the file
|
||||
.Ql Pa makefile
|
||||
exists, it is read for this list of specifications.
|
||||
If it does not exist, the file
|
||||
.Ql Pa Makefile
|
||||
is read.
|
||||
If the file
|
||||
.Ql Pa .depend
|
||||
exists, it is read (see
|
||||
.Xr mkdep 1) .
|
||||
.Pp
|
||||
This manual page is intended as a reference document only.
|
||||
For a more thorough description of
|
||||
.Nm make
|
||||
and makefiles, please refer to
|
||||
.%T "Make \- A Tutorial" .
|
||||
.Pp
|
||||
The options are as follows:
|
||||
.Bl -tag -width Ds
|
||||
.It Fl D Ar variable
|
||||
Define Ar variable
|
||||
to be 1, in the global context.
|
||||
.It Fl d Ar flags
|
||||
Turn on debugging, and specify which portions of
|
||||
.Nm make
|
||||
are to print debugging information.
|
||||
.Ar Flags
|
||||
is one or more of the following:
|
||||
.Bl -tag -width Ds
|
||||
.It Ar A
|
||||
Print all possible debugging information;
|
||||
equivalent to specifying all of the debugging flags.
|
||||
.It Ar a
|
||||
Print debugging information about archive searching and caching.
|
||||
.It Ar c
|
||||
Print debugging information about conditional evaluation.
|
||||
.It Ar d
|
||||
Print debugging information about directory searching and caching.
|
||||
.It Ar "g1"
|
||||
Print the input graph before making anything.
|
||||
.It Ar "g2"
|
||||
Print the input graph after making everything, or before exiting
|
||||
on error.
|
||||
.It Ar j
|
||||
Print debugging information about running multiple shells.
|
||||
.It Ar m
|
||||
Print debugging information about making targets, including modification
|
||||
dates.
|
||||
.It Ar s
|
||||
Print debugging information about suffix-transformation rules.
|
||||
.It Ar t
|
||||
Print debugging information about target list maintenance.
|
||||
.It Ar v
|
||||
Print debugging information about variable assignment.
|
||||
.El
|
||||
.It Fl e
|
||||
Specify that environmental variables override macro assignments within
|
||||
makefiles.
|
||||
.It Fl f Ar makefile
|
||||
Specify a makefile to read instead of the default
|
||||
.Ql Pa makefile
|
||||
and
|
||||
.Ql Pa Makefile .
|
||||
If
|
||||
.Ar makefile
|
||||
is
|
||||
.Ql Fl ,
|
||||
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.
|
||||
.It Fl i
|
||||
Ignore non-zero exit of shell commands in the makefile.
|
||||
Equivalent to specifying
|
||||
.Ql Fl
|
||||
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.
|
||||
.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 n
|
||||
Display the commands that would have been executed, but do not actually
|
||||
execute them.
|
||||
.It Fl q
|
||||
Do not execute any commands, but exit 0 if the specified targets are
|
||||
up-to-date and 1, otherwise.
|
||||
.It Fl r
|
||||
Do not use the built-in rules specified in the system makefile.
|
||||
.It Fl s
|
||||
Do not echo any commands as they are executed.
|
||||
Equivalent to specifying
|
||||
.Ql Ic @
|
||||
before each command line in the makefile.
|
||||
.It Fl t
|
||||
Rather than re-building a target as specified in the makefile, create it
|
||||
or update its modification time to make it appear up-to-date.
|
||||
.It Ar variable=value
|
||||
Set the value of the variable
|
||||
.Ar variable
|
||||
to
|
||||
.Ar value .
|
||||
.El
|
||||
.Pp
|
||||
There are seven different types of lines in a makefile: file dependency
|
||||
specifications, shell commands, variable assignments, include statements,
|
||||
conditional directives, for loops, and comments.
|
||||
.Pp
|
||||
In general, lines may be continued from one line to the next by ending
|
||||
them with a backslash
|
||||
.Pq Ql \e .
|
||||
The trailing newline character and initial whitespace on the following
|
||||
line are compressed into a single space.
|
||||
.Sh FILE DEPENDENCY SPECIFICATIONS
|
||||
Dependency lines consist of one or more targets, an operator, and zero
|
||||
or more sources.
|
||||
This creates a relationship where the targets ``depend'' on the sources
|
||||
and are usually created from them.
|
||||
The exact relationship between the target and the source is determined
|
||||
by the operator that separates them.
|
||||
The three operators are as follows:
|
||||
.Bl -tag -width flag
|
||||
.It Ic \&:
|
||||
A target is considered out-of-date if its modification time is less than
|
||||
those of any of its sources.
|
||||
Sources for a target accumulate over dependency lines when this operator
|
||||
is used.
|
||||
The target is removed if
|
||||
.Nm make
|
||||
is interrupted.
|
||||
.It Ic \&!
|
||||
Targets are always re-created, but not until all sources have been
|
||||
examined and re-created as necessary.
|
||||
Sources for a target accumulate over dependency lines when this operator
|
||||
is used.
|
||||
The target is removed if
|
||||
.Nm make
|
||||
is interrupted.
|
||||
.It Ic \&::
|
||||
If no sources are specified, the target is always re-created.
|
||||
Otherwise, a target is considered out-of-date if any of its sources has
|
||||
been modified more recently than the target.
|
||||
Sources for a target do not accumulate over dependency lines when this
|
||||
operator is used.
|
||||
The target will not be removed if
|
||||
.Nm make
|
||||
is interrupted.
|
||||
.El
|
||||
.Pp
|
||||
Targets and sources may contain the shell wildcard values
|
||||
.Ql ? ,
|
||||
.Ql * ,
|
||||
.Ql []
|
||||
and
|
||||
.Ql {} .
|
||||
The values
|
||||
.Ql ? ,
|
||||
.Ql *
|
||||
and
|
||||
.Ql []
|
||||
may only be used as part of the final
|
||||
component of the target or source, and must be used to describe existing
|
||||
files.
|
||||
The value
|
||||
.Ql {}
|
||||
need not necessarily be used to describe existing files.
|
||||
Expansion is in directory order, not alphabetically as done in the shell.
|
||||
.Sh SHELL COMMANDS
|
||||
Each target may have associated with it a series of shell commands, normally
|
||||
used to create the target.
|
||||
Each of the commands in this script
|
||||
.Em must
|
||||
be preceded by a tab.
|
||||
While any target may appear on a dependency line, only one of these
|
||||
dependencies may be followed by a creation script, unless the
|
||||
.Ql Ic ::
|
||||
operator is used.
|
||||
.Pp
|
||||
If the first or first two characters of the command line are
|
||||
.Ql Ic @
|
||||
and/or
|
||||
.Ql Ic \- ,
|
||||
the command is treated specially.
|
||||
A
|
||||
.Ql Ic @
|
||||
causes the command not to be echoed before it is executed.
|
||||
A
|
||||
.Ql Ic \-
|
||||
causes any non-zero exit status of the command line to be ignored.
|
||||
.Sh VARIABLE ASSIGNMENTS
|
||||
Variables in make are much like variables in the shell, and, by tradition,
|
||||
consist of all upper-case letters.
|
||||
The five operators that can be used to assign values to variables are as
|
||||
follows:
|
||||
.Bl -tag -width Ds
|
||||
.It Ic \&=
|
||||
Assign the value to the variable.
|
||||
Any previous value is overridden.
|
||||
.It Ic \&+=
|
||||
Append the value to the current value of the variable.
|
||||
.It Ic \&?=
|
||||
Assign the value to the variable if it is not already defined.
|
||||
.It Ic \&:=
|
||||
Assign with expansion, i.e. expand the value before assigning it
|
||||
to the variable.
|
||||
Normally, expansion is not done until the variable is referenced.
|
||||
.It Ic \&!=
|
||||
Expand the value and pass it to the shell for execution and assign
|
||||
the result to the variable.
|
||||
Any newlines in the result are replaced with spaces.
|
||||
.El
|
||||
.Pp
|
||||
Any white-space before the assigned
|
||||
.Ar value
|
||||
is removed; if the value is being appended, a single space is inserted
|
||||
between the previous contents of the variable and the appended value.
|
||||
.Pp
|
||||
Variables are expanded by surrounding the variable name with either
|
||||
curly braces
|
||||
.Pq Ql {}
|
||||
or parenthesis
|
||||
.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.
|
||||
This shorter form is not recommended.
|
||||
.Pp
|
||||
Variable substitution occurs at two distinct times, depending on where
|
||||
the variable is being used.
|
||||
Variables in dependency lines are expanded as the line is read.
|
||||
Variables in shell commands are expanded when the shell command is
|
||||
executed.
|
||||
.Pp
|
||||
The four different classes of variables (in order of increasing precedence)
|
||||
are:
|
||||
.Bl -tag -width Ds
|
||||
.It Environment variables
|
||||
Variables defined as part of
|
||||
.Nm make Ns 's
|
||||
environment.
|
||||
.It Global variables
|
||||
Variables defined in the makefile or in included makefiles.
|
||||
.It Command line variables
|
||||
Variables defined as part of the command line.
|
||||
.It Local variables
|
||||
Variables that are defined specific to a certain target.
|
||||
The seven local variables are as follows:
|
||||
.Bl -tag -width ".ARCHIVE"
|
||||
.It Va .ALLSRC
|
||||
The list of all sources for this target; also known as
|
||||
.Ql Va \&> .
|
||||
.It Va .ARCHIVE
|
||||
The name of the archive file.
|
||||
.It Va .IMPSRC
|
||||
The name/path of the source from which the target is to be transformed
|
||||
(the ``implied'' source); also known as
|
||||
.Ql Va \&< .
|
||||
.It Va .MEMBER
|
||||
The name of the archive member.
|
||||
.It Va .OODATE
|
||||
The list of sources for this target that were deemed out-of-date; also
|
||||
known as
|
||||
.Ql Va \&? .
|
||||
.It Va .PREFIX
|
||||
The file prefix of the file, containing only the file portion, no suffix
|
||||
or preceding directory components; also known as
|
||||
.Ql Va * .
|
||||
.It Va .TARGET
|
||||
The name of the target; also known as
|
||||
.Ql Va @ .
|
||||
.El
|
||||
.Pp
|
||||
The shorter forms
|
||||
.Ql Va @ ,
|
||||
.Ql Va ? ,
|
||||
.Ql Va \&>
|
||||
and
|
||||
.Ql Va *
|
||||
are permitted for backward
|
||||
compatibility with historical makefiles and are not recommended.
|
||||
The six variables
|
||||
.Ql Va "@F" ,
|
||||
.Ql Va "@D" ,
|
||||
.Ql Va "<F" ,
|
||||
.Ql Va "<D" ,
|
||||
.Ql Va "*F"
|
||||
and
|
||||
.Ql Va "*D"
|
||||
are
|
||||
permitted for compatibility with
|
||||
.At V
|
||||
makefiles and are not recommended.
|
||||
.Pp
|
||||
Four of the local variables may be used in sources on dependency lines
|
||||
because they expand to the proper value for each target on the line.
|
||||
These variables are
|
||||
.Ql Va .TARGET ,
|
||||
.Ql Va .PREFIX ,
|
||||
.Ql Va .ARCHIVE ,
|
||||
and
|
||||
.Ql Va .MEMBER .
|
||||
.Pp
|
||||
In addition,
|
||||
.Nm make
|
||||
sets or knows about the following variables:
|
||||
.Bl -tag -width MAKEFLAGS
|
||||
.It Va \&$
|
||||
A single dollar sign
|
||||
.Ql \&$ ,
|
||||
i.e.
|
||||
.Ql \&$$
|
||||
expands to a single dollar
|
||||
sign.
|
||||
.It Va .MAKE
|
||||
The name that
|
||||
.Nm make
|
||||
was executed with
|
||||
.Pq Va argv Op 0
|
||||
.It Va .CURDIR
|
||||
A path to the directory where
|
||||
.Nm make
|
||||
was executed.
|
||||
.It Va .OBJDIR
|
||||
A path to the directory where the targets are built.
|
||||
.It Ev MAKEFLAGS
|
||||
The environment variable
|
||||
.Ql Ev MAKEFLAGS
|
||||
may contain anything that
|
||||
may be specified on
|
||||
.Nm make Ns 's
|
||||
command line.
|
||||
Anything specified on
|
||||
.Nm make Ns 's
|
||||
command line is appended to the
|
||||
.Ql Ev MAKEFLAGS
|
||||
variable which is then
|
||||
entered into the environment for all programs which
|
||||
.Nm make
|
||||
executes.
|
||||
.El
|
||||
.Pp
|
||||
Variable expansion may be modified to select or modify each word of the
|
||||
variable (where a ``word'' is white-space delimited sequence of characters).
|
||||
The general format of a variable expansion is as follows:
|
||||
.Pp
|
||||
.Dl {variable[:modifier[:...]]}
|
||||
.Pp
|
||||
Each modifier begins with a colon and one of the following
|
||||
special characters.
|
||||
The colon may be escaped with a backslash
|
||||
.Pq Ql \e .
|
||||
.Bl -tag -width Cm E\&
|
||||
.It Cm E
|
||||
Replaces each word in the variable with its suffix.
|
||||
.It Cm H
|
||||
Replaces each word in the variable with everything but the last component.
|
||||
.It Cm M Ns Ar pattern
|
||||
Select only those words that match the rest of the modifier.
|
||||
The standard shell wildcard characters
|
||||
.Pf ( Ql * ,
|
||||
.Ql ? ,
|
||||
and
|
||||
.Ql Op )
|
||||
may
|
||||
be used.
|
||||
The wildcard characters may be escaped with a backslash
|
||||
.Pq Ql \e .
|
||||
.It Cm N Ns Ar pattern
|
||||
This is identical to
|
||||
.Ql Cm M ,
|
||||
but selects all words which do not match
|
||||
the rest of the modifier.
|
||||
.It Cm R
|
||||
Replaces each word in the variable with everything but its suffix.
|
||||
.Sm off
|
||||
.It Cm S No \&/ Ar old_pattern Xo
|
||||
.No \&/ Ar new_pattern
|
||||
.No \&/ Op Cm g
|
||||
.Xc
|
||||
.Sm on
|
||||
Modify the first occurrence of
|
||||
.Ar old_pattern
|
||||
in each word to be replaced with
|
||||
.Ar new_pattern .
|
||||
If a
|
||||
.Ql g
|
||||
is appended to the last slash of the pattern, all occurrences
|
||||
in each word are replaced.
|
||||
If
|
||||
.Ar old_pattern
|
||||
begins with a carat
|
||||
.Pq Ql ^ ,
|
||||
.Ar old_pattern
|
||||
is anchored at the beginning of each word.
|
||||
If
|
||||
.Ar old_pattern
|
||||
ends with a dollar sign
|
||||
.Pq Ql \&$ ,
|
||||
it is anchored at the end of each word.
|
||||
Inside
|
||||
.Ar new_string ,
|
||||
an ampersand
|
||||
.Pq Ql &
|
||||
is replaced by
|
||||
.Ar old_pattern .
|
||||
Any character may be used as a delimiter for the parts of the modifier
|
||||
string.
|
||||
The anchoring, ampersand and delimiter characters may be escaped with a
|
||||
backslash
|
||||
.Pq Ql \e .
|
||||
.Pp
|
||||
Variable expansion occurs in the normal fashion inside both
|
||||
.Ar old_string
|
||||
and
|
||||
.Ar new_string
|
||||
with the single exception that a backslash is used to prevent the expansion
|
||||
of a dollar sign
|
||||
.Pq Ql \&$
|
||||
not a preceding dollar sign as is usual.
|
||||
.It Cm T
|
||||
Replaces each word in the variable with its last component.
|
||||
.It Ar old_string=new_string
|
||||
This is the
|
||||
.At V
|
||||
style variable substitution.
|
||||
It must be the last modifier specified.
|
||||
If
|
||||
.Ar old_string
|
||||
or
|
||||
.Ar new_string
|
||||
do not contain the pattern matching character
|
||||
.Ar %
|
||||
then it is assumed that they are
|
||||
anchored at the end of each word, so only suffixes or entire
|
||||
words may be replaced. Otherwise
|
||||
.Ar %
|
||||
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
|
||||
of the C programming language are provided in
|
||||
.Nm make .
|
||||
All such structures are identified by a line beginning with a single
|
||||
dot
|
||||
.Pq Ql \&.
|
||||
character.
|
||||
Files are included with either
|
||||
.Ql .include <file>
|
||||
or
|
||||
.Ql .include \*qfile\*q .
|
||||
Variables between the angle brackets or double quotes are expanded
|
||||
to form the file name.
|
||||
If angle brackets are used, the included makefile is expected to be in
|
||||
the system makefile directory.
|
||||
If double quotes are used, the including makefile's directory and any
|
||||
directories specified using the
|
||||
.Fl I
|
||||
option are searched before the system
|
||||
makefile directory.
|
||||
.Pp
|
||||
Conditional expressions are also preceded by a single dot as the first
|
||||
character of a line.
|
||||
The possible conditionals are as follows:
|
||||
.Bl -tag -width Ds
|
||||
.It Ic .undef Ar variable
|
||||
Un-define the specified global variable.
|
||||
Only global variables may be un-defined.
|
||||
.It Xo
|
||||
.Ic \&.if
|
||||
.Oo \&! Oc Ns Ar expression
|
||||
.Op Ar operator expression ...
|
||||
.Xc
|
||||
Test the value of an expression.
|
||||
.It Xo
|
||||
.Ic .ifdef
|
||||
.Oo \&! Oc Ns Ar variable
|
||||
.Op Ar operator variable ...
|
||||
.Xc
|
||||
Test the value of a variable.
|
||||
.It Xo
|
||||
.Ic .ifndef
|
||||
.Oo \&! Oc Ns Ar variable
|
||||
.Op Ar operator variable ...
|
||||
.Xc
|
||||
Test the value of a variable.
|
||||
.It Xo
|
||||
.Ic .ifmake
|
||||
.Oo \&! Oc Ns Ar target
|
||||
.Op Ar operator target ...
|
||||
.Xc
|
||||
Test the the target being built.
|
||||
.It Xo
|
||||
.Ic .ifnmake
|
||||
.Oo \&! Oc Ar target
|
||||
.Op Ar operator target ...
|
||||
.Xc
|
||||
Test the target being built.
|
||||
.It Ic .else
|
||||
Reverse the sense of the last conditional.
|
||||
.It Xo
|
||||
.Ic .elif
|
||||
.Oo \&! Oc Ar expression
|
||||
.Op Ar operator expression ...
|
||||
.Xc
|
||||
A combination of
|
||||
.Ql Ic .else
|
||||
followed by
|
||||
.Ql Ic .if .
|
||||
.It Xo
|
||||
.Ic .elifdef
|
||||
.Oo \&! Oc Ns Ar variable
|
||||
.Op Ar operator variable ...
|
||||
.Xc
|
||||
A combination of
|
||||
.Ql Ic .else
|
||||
followed by
|
||||
.Ql Ic .ifdef .
|
||||
.It Xo
|
||||
.Ic .elifndef
|
||||
.Oo \&! Oc Ns Ar variable
|
||||
.Op Ar operator variable ...
|
||||
.Xc
|
||||
A combination of
|
||||
.Ql Ic .else
|
||||
followed by
|
||||
.Ql Ic .ifndef .
|
||||
.It Xo
|
||||
.Ic .elifmake
|
||||
.Oo \&! Oc Ns Ar target
|
||||
.Op Ar operator target ...
|
||||
.Xc
|
||||
A combination of
|
||||
.Ql Ic .else
|
||||
followed by
|
||||
.Ql Ic .ifmake .
|
||||
.It Xo
|
||||
.Ic .elifnmake
|
||||
.Oo \&! Oc Ns Ar target
|
||||
.Op Ar operator target ...
|
||||
.Xc
|
||||
A combination of
|
||||
.Ql Ic .else
|
||||
followed by
|
||||
.Ql Ic .ifnmake .
|
||||
.It Ic .endif
|
||||
End the body of the conditional.
|
||||
.El
|
||||
.Pp
|
||||
The
|
||||
.Ar operator
|
||||
may be any one of the following:
|
||||
.Bl -tag -width "Cm XX"
|
||||
.It Cm \&|\&|
|
||||
logical OR
|
||||
.It Cm \&&&
|
||||
Logical
|
||||
.Tn AND ;
|
||||
of higher precedence than
|
||||
.Dq .
|
||||
.El
|
||||
.Pp
|
||||
As in C,
|
||||
.Nm make
|
||||
will only evaluate a conditional as far as is necessary to determine
|
||||
its value.
|
||||
Parentheses may be used to change the order of evaluation.
|
||||
The boolean operator
|
||||
.Ql Ic \&!
|
||||
may be used to logically negate an entire
|
||||
conditional.
|
||||
It is of higher precedence than
|
||||
.Ql Ic \&&& .
|
||||
.Pp
|
||||
The value of
|
||||
.Ar expression
|
||||
may be any of the following:
|
||||
.Bl -tag -width Ic defined
|
||||
.It Ic defined
|
||||
Takes a variable name as an argument and evaluates to true if the variable
|
||||
has been defined.
|
||||
.It Ic make
|
||||
Takes a target name as an argument and evaluates to true if the target
|
||||
was specified as part of
|
||||
.Nm make Ns 's
|
||||
command line or was declared the default target (either implicitly or
|
||||
explicitly, see
|
||||
.Va .MAIN )
|
||||
before the line containing the conditional.
|
||||
.It Ic empty
|
||||
Takes a variable, with possible modifiers, and evaluates to true if
|
||||
the expansion of the variable would result in an empty string.
|
||||
.It Ic exists
|
||||
Takes a file name as an argument and evaluates to true if the file exists.
|
||||
The file is searched for on the system search path (see
|
||||
.Va .PATH ) .
|
||||
.It Ic target
|
||||
Takes a target name as an argument and evaluates to true if the target
|
||||
has been defined.
|
||||
.El
|
||||
.Pp
|
||||
.Ar Expression
|
||||
may also be an arithmetic or string comparison. Variable expansion is
|
||||
performed on both sides of the comparison, after which the integral
|
||||
values are compared. A value is interpreted as hexadecimal if it is
|
||||
preceded by 0x, otherwise it is decimal; octal numbers are not supported.
|
||||
The standard C relational operators are all supported. If after
|
||||
variable expansion, either the left or right hand side of a
|
||||
.Ql Ic ==
|
||||
or
|
||||
.Ql Ic "!="
|
||||
operator is not an integral value, then
|
||||
string comparison is performed between the expanded
|
||||
variables.
|
||||
If no relational operator is given, it is assumed that the expanded
|
||||
variable is being compared against 0.
|
||||
.Pp
|
||||
When
|
||||
.Nm make
|
||||
is evaluating one of these conditional expression, and it encounters
|
||||
a word it doesn't recognize, either the ``make'' or ``defined''
|
||||
expression is applied to it, depending on the form of the conditional.
|
||||
If the form is
|
||||
.Ql Ic .ifdef
|
||||
or
|
||||
.Ql Ic .ifndef ,
|
||||
the ``defined'' expression
|
||||
is applied.
|
||||
Similarly, if the form is
|
||||
.Ql Ic .ifmake
|
||||
or
|
||||
.Ql Ic .ifnmake , the ``make''
|
||||
expression is applied.
|
||||
.Pp
|
||||
If the conditional evaluates to true the parsing of the makefile continues
|
||||
as before.
|
||||
If it evaluates to false, the following lines are skipped.
|
||||
In both cases this continues until a
|
||||
.Ql Ic .else
|
||||
or
|
||||
.Ql Ic .endif
|
||||
is found.
|
||||
.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 expression
|
||||
.Xc
|
||||
.It Xo
|
||||
<make-rules>
|
||||
.Xc
|
||||
.It Xo
|
||||
.Ic \&.endfor
|
||||
.Xc
|
||||
.El
|
||||
After the for
|
||||
.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
|
||||
inside the body of the for loop.
|
||||
.Sh COMMENTS
|
||||
Comments begin with a hash
|
||||
.Pq Ql \&#
|
||||
character, anywhere but in a shell
|
||||
command line, and continue to the end of the line.
|
||||
.Sh SPECIAL SOURCES
|
||||
.Bl -tag -width Ic .IGNORE
|
||||
.It Ic .IGNORE
|
||||
Ignore any errors from the commands associated with this target, exactly
|
||||
as if they all were preceded by a dash
|
||||
.Pq Ql \- .
|
||||
.It Ic .MAKE
|
||||
Execute the commands associated with this target even if the
|
||||
.Fl n
|
||||
or
|
||||
.Fl t
|
||||
options were specified.
|
||||
Normally used to mark recursive
|
||||
.Nm make Ns 's .
|
||||
.It Ic .NOTMAIN
|
||||
Normally
|
||||
.Nm make
|
||||
selects the first target it encounters as the default target to be built
|
||||
if no target was specified.
|
||||
This source prevents this target from being selected.
|
||||
.It Ic .OPTIONAL
|
||||
If a target is marked with this attribute and
|
||||
.Nm make
|
||||
can't figure out how to create it, it will ignore this fact and assume
|
||||
the file isn't needed or already exists.
|
||||
.It Ic .PRECIOUS
|
||||
When
|
||||
.Nm make
|
||||
is interrupted, it removes any partially made targets.
|
||||
This source prevents the target from being removed.
|
||||
.It Ic .SILENT
|
||||
Do not echo any of the commands associated with this target, exactly
|
||||
as if they all were preceded by an at sign
|
||||
.Pq Ql @ .
|
||||
.It Ic .USE
|
||||
Turn the target into
|
||||
.Nm make Ns 's .
|
||||
version of a macro.
|
||||
When the target is used as a source for another target, the other target
|
||||
acquires the commands, sources, and attributes (except for
|
||||
.Ic .USE )
|
||||
of the
|
||||
source.
|
||||
If the target already has commands, the
|
||||
.Ic .USE
|
||||
target's commands are appended
|
||||
to them.
|
||||
.El
|
||||
.Sh "SPECIAL TARGETS"
|
||||
Special targets may not be included with other targets, i.e. they must be
|
||||
the only target specified.
|
||||
.Bl -tag -width Ic .BEGIN
|
||||
.It Ic .BEGIN
|
||||
Any command lines attached to this target are executed before anything
|
||||
else is done.
|
||||
.It Ic .DEFAULT
|
||||
This is sort of a
|
||||
.Ic .USE
|
||||
rule for any target (that was used only as a
|
||||
source) that
|
||||
.Nm make
|
||||
can't figure out any other way to create.
|
||||
Only the shell script is used.
|
||||
The
|
||||
.Ic .IMPSRC
|
||||
variable of a target that inherits
|
||||
.Ic .DEFAULT Ns 's
|
||||
commands is set
|
||||
to the target's own name.
|
||||
.It Ic .END
|
||||
Any command lines attached to this target are executed after everything
|
||||
else is done.
|
||||
.It Ic .IGNORE
|
||||
Mark each of the sources with the
|
||||
.Ic .IGNORE
|
||||
attribute.
|
||||
If no sources are specified, this is the equivalent of specifying the
|
||||
.Fl i
|
||||
option.
|
||||
.It Ic .INTERRUPT
|
||||
If
|
||||
.Nm make
|
||||
is interrupted, the commands for this target will be executed.
|
||||
.It Ic .MAIN
|
||||
If no target is specified when
|
||||
.Nm make
|
||||
is invoked, this target will be built.
|
||||
.It Ic .MAKEFLAGS
|
||||
This target provides a way to specify flags for
|
||||
.Nm make
|
||||
when the makefile is used.
|
||||
The flags are as if typed to the shell, though the
|
||||
.Fl f
|
||||
option will have
|
||||
no effect.
|
||||
.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 .PRECIOUS
|
||||
Apply the
|
||||
.Ic .PRECIOUS
|
||||
attribute to any specified sources.
|
||||
If no sources are specified, the
|
||||
.Ic .PRECIOUS
|
||||
attribute is applied to every
|
||||
target in the file.
|
||||
.It Ic .SILENT
|
||||
Apply the
|
||||
.Ic .SILENT
|
||||
attribute to any specified sources.
|
||||
If no sources are specified, the
|
||||
.Ic .SILENT
|
||||
attribute is applied to every
|
||||
command in the file.
|
||||
.It Ic .SUFFIXES
|
||||
Each source specifies a suffix to
|
||||
.Nm make .
|
||||
If no sources are specified, any previous specified suffices are deleted.
|
||||
.Sh ENVIRONMENT
|
||||
.Nm Make
|
||||
utilizes the following environment variables, if they exist:
|
||||
.Ev MAKE ,
|
||||
.Ev MAKEFLAGS
|
||||
and
|
||||
.Ev MAKEOBJDIR .
|
||||
.Sh FILES
|
||||
.Bl -tag -width /usr/share/mk -compact
|
||||
.It .depend
|
||||
list of dependencies
|
||||
.It Makefile
|
||||
list of dependencies
|
||||
.It makefile
|
||||
list of dependencies
|
||||
.It sys.mk
|
||||
system makefile
|
||||
.It /usr/share/mk
|
||||
system makefile directory
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr mkdep 1
|
||||
.Sh HISTORY
|
||||
A
|
||||
.Nm Make
|
||||
command appeared in
|
||||
.At v7 .
|
859
usr.bin/make/make.c
Normal file
859
usr.bin/make/make.c
Normal file
@ -0,0 +1,859 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)make.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif /* not lint */
|
||||
|
||||
/*-
|
||||
* make.c --
|
||||
* The functions which perform the examination of targets and
|
||||
* their suitability for creation
|
||||
*
|
||||
* Interface:
|
||||
* Make_Run Initialize things for the module and recreate
|
||||
* whatever needs recreating. Returns TRUE if
|
||||
* work was (or would have been) done and FALSE
|
||||
* otherwise.
|
||||
*
|
||||
* Make_Update Update all parents of a given child. Performs
|
||||
* various bookkeeping chores like the updating
|
||||
* of the cmtime field of the parent, filling
|
||||
* of the IMPSRC context variable, etc. It will
|
||||
* place the parent on the toBeMade queue if it
|
||||
* should be.
|
||||
*
|
||||
* Make_TimeStamp Function to set the parent's cmtime field
|
||||
* based on a child's modification time.
|
||||
*
|
||||
* Make_DoAllVar Set up the various local variables for a
|
||||
* target, including the .ALLSRC variable, making
|
||||
* sure that any variable that needs to exist
|
||||
* at the very least has the empty value.
|
||||
*
|
||||
* Make_OODate Determine if a target is out-of-date.
|
||||
*
|
||||
* Make_HandleUse See if a child is a .USE node for a parent
|
||||
* and perform the .USE actions if so.
|
||||
*/
|
||||
|
||||
#include "make.h"
|
||||
#include "hash.h"
|
||||
#include "dir.h"
|
||||
#include "job.h"
|
||||
|
||||
static Lst toBeMade; /* The current fringe of the graph. These
|
||||
* are nodes which await examination by
|
||||
* MakeOODate. It is added to by
|
||||
* Make_Update and subtracted from by
|
||||
* MakeStartJobs */
|
||||
static int numNodes; /* Number of nodes to be processed. If this
|
||||
* is non-zero when Job_Empty() returns
|
||||
* TRUE, there's a cycle in the graph */
|
||||
|
||||
static int MakeAddChild __P((GNode *, Lst));
|
||||
static int MakeAddAllSrc __P((GNode *, GNode *));
|
||||
static Boolean MakeStartJobs __P((void));
|
||||
static int MakePrintStatus __P((GNode *, Boolean));
|
||||
/*-
|
||||
*-----------------------------------------------------------------------
|
||||
* Make_TimeStamp --
|
||||
* Set the cmtime field of a parent node based on the mtime stamp in its
|
||||
* child. Called from MakeOODate via Lst_ForEach.
|
||||
*
|
||||
* Results:
|
||||
* Always returns 0.
|
||||
*
|
||||
* Side Effects:
|
||||
* The cmtime of the parent node will be changed if the mtime
|
||||
* field of the child is greater than it.
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
int
|
||||
Make_TimeStamp (pgn, cgn)
|
||||
register GNode *pgn; /* the current parent */
|
||||
register GNode *cgn; /* the child we've just examined */
|
||||
{
|
||||
if (cgn->mtime > pgn->cmtime) {
|
||||
pgn->cmtime = cgn->mtime;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*-
|
||||
*-----------------------------------------------------------------------
|
||||
* Make_OODate --
|
||||
* See if a given node is out of date with respect to its sources.
|
||||
* Used by Make_Run when deciding which nodes to place on the
|
||||
* toBeMade queue initially and by Make_Update to screen out USE and
|
||||
* EXEC nodes. In the latter case, however, any other sort of node
|
||||
* must be considered out-of-date since at least one of its children
|
||||
* will have been recreated.
|
||||
*
|
||||
* Results:
|
||||
* TRUE if the node is out of date. FALSE otherwise.
|
||||
*
|
||||
* Side Effects:
|
||||
* The mtime field of the node and the cmtime field of its parents
|
||||
* will/may be changed.
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
Boolean
|
||||
Make_OODate (gn)
|
||||
register GNode *gn; /* the node to check */
|
||||
{
|
||||
Boolean oodate;
|
||||
|
||||
/*
|
||||
* Certain types of targets needn't even be sought as their datedness
|
||||
* doesn't depend on their modification time...
|
||||
*/
|
||||
if ((gn->type & (OP_JOIN|OP_USE|OP_EXEC)) == 0) {
|
||||
(void) Dir_MTime (gn);
|
||||
if (DEBUG(MAKE)) {
|
||||
if (gn->mtime != 0) {
|
||||
printf ("modified %s...", Targ_FmtTime(gn->mtime));
|
||||
} else {
|
||||
printf ("non-existent...");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* A target is remade in one of the following circumstances:
|
||||
* its modification time is smaller than that of its youngest child
|
||||
* and it would actually be run (has commands or type OP_NOP)
|
||||
* it's the object of a force operator
|
||||
* it has no children, was on the lhs of an operator and doesn't exist
|
||||
* already.
|
||||
*
|
||||
* Libraries are only considered out-of-date if the archive module says
|
||||
* they are.
|
||||
*
|
||||
* These weird rules are brought to you by Backward-Compatability and
|
||||
* the strange people who wrote 'Make'.
|
||||
*/
|
||||
if (gn->type & OP_USE) {
|
||||
/*
|
||||
* If the node is a USE node it is *never* out of date
|
||||
* no matter *what*.
|
||||
*/
|
||||
if (DEBUG(MAKE)) {
|
||||
printf(".USE node...");
|
||||
}
|
||||
oodate = FALSE;
|
||||
} else if (gn->type & OP_LIB) {
|
||||
if (DEBUG(MAKE)) {
|
||||
printf("library...");
|
||||
}
|
||||
oodate = Arch_LibOODate (gn);
|
||||
} else if (gn->type & OP_JOIN) {
|
||||
/*
|
||||
* A target with the .JOIN attribute is only considered
|
||||
* out-of-date if any of its children was out-of-date.
|
||||
*/
|
||||
if (DEBUG(MAKE)) {
|
||||
printf(".JOIN node...");
|
||||
}
|
||||
oodate = gn->childMade;
|
||||
} else if (gn->type & (OP_FORCE|OP_EXEC)) {
|
||||
/*
|
||||
* A node which is the object of the force (!) operator or which has
|
||||
* the .EXEC attribute is always considered out-of-date.
|
||||
*/
|
||||
if (DEBUG(MAKE)) {
|
||||
if (gn->type & OP_FORCE) {
|
||||
printf("! operator...");
|
||||
} else {
|
||||
printf(".EXEC node...");
|
||||
}
|
||||
}
|
||||
oodate = TRUE;
|
||||
} else if ((gn->mtime < gn->cmtime) ||
|
||||
((gn->cmtime == 0) &&
|
||||
((gn->mtime==0) || (gn->type & OP_DOUBLEDEP))))
|
||||
{
|
||||
/*
|
||||
* A node whose modification time is less than that of its
|
||||
* youngest child or that has no children (cmtime == 0) and
|
||||
* either doesn't exist (mtime == 0) or was the object of a
|
||||
* :: operator is out-of-date. Why? Because that's the way Make does
|
||||
* it.
|
||||
*/
|
||||
if (DEBUG(MAKE)) {
|
||||
if (gn->mtime < gn->cmtime) {
|
||||
printf("modified before source...");
|
||||
} else if (gn->mtime == 0) {
|
||||
printf("non-existent and no sources...");
|
||||
} else {
|
||||
printf(":: operator and no sources...");
|
||||
}
|
||||
}
|
||||
oodate = TRUE;
|
||||
} else {
|
||||
#if 0
|
||||
/* WHY? */
|
||||
if (DEBUG(MAKE)) {
|
||||
printf("source %smade...", gn->childMade ? "" : "not ");
|
||||
}
|
||||
oodate = gn->childMade;
|
||||
#else
|
||||
oodate = FALSE;
|
||||
#endif /* 0 */
|
||||
}
|
||||
|
||||
/*
|
||||
* If the target isn't out-of-date, the parents need to know its
|
||||
* modification time. Note that targets that appear to be out-of-date
|
||||
* but aren't, because they have no commands and aren't of type OP_NOP,
|
||||
* have their mtime stay below their children's mtime to keep parents from
|
||||
* thinking they're out-of-date.
|
||||
*/
|
||||
if (!oodate) {
|
||||
Lst_ForEach (gn->parents, Make_TimeStamp, (ClientData)gn);
|
||||
}
|
||||
|
||||
return (oodate);
|
||||
}
|
||||
|
||||
/*-
|
||||
*-----------------------------------------------------------------------
|
||||
* MakeAddChild --
|
||||
* Function used by Make_Run to add a child to the list l.
|
||||
* It will only add the child if its make field is FALSE.
|
||||
*
|
||||
* Results:
|
||||
* Always returns 0
|
||||
*
|
||||
* Side Effects:
|
||||
* The given list is extended
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
static int
|
||||
MakeAddChild (gn, l)
|
||||
GNode *gn; /* the node to add */
|
||||
Lst l; /* the list to which to add it */
|
||||
{
|
||||
if (!gn->make && !(gn->type & OP_USE)) {
|
||||
(void)Lst_EnQueue (l, (ClientData)gn);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*-
|
||||
*-----------------------------------------------------------------------
|
||||
* Make_HandleUse --
|
||||
* Function called by Make_Run and SuffApplyTransform on the downward
|
||||
* pass to handle .USE and transformation nodes. A callback function
|
||||
* for Lst_ForEach, it implements the .USE and transformation
|
||||
* functionality by copying the node's commands, type flags
|
||||
* and children to the parent node. Should be called before the
|
||||
* children are enqueued to be looked at by MakeAddChild.
|
||||
*
|
||||
* A .USE node is much like an explicit transformation rule, except
|
||||
* its commands are always added to the target node, even if the
|
||||
* target already has commands.
|
||||
*
|
||||
* Results:
|
||||
* returns 0.
|
||||
*
|
||||
* Side Effects:
|
||||
* Children and commands may be added to the parent and the parent's
|
||||
* type may be changed.
|
||||
*
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
int
|
||||
Make_HandleUse (cgn, pgn)
|
||||
register GNode *cgn; /* The .USE node */
|
||||
register GNode *pgn; /* The target of the .USE node */
|
||||
{
|
||||
register GNode *gn; /* A child of the .USE node */
|
||||
register LstNode ln; /* An element in the children list */
|
||||
|
||||
if (cgn->type & (OP_USE|OP_TRANSFORM)) {
|
||||
if ((cgn->type & OP_USE) || Lst_IsEmpty(pgn->commands)) {
|
||||
/*
|
||||
* .USE or transformation and target has no commands -- append
|
||||
* the child's commands to the parent.
|
||||
*/
|
||||
(void) Lst_Concat (pgn->commands, cgn->commands, LST_CONCNEW);
|
||||
}
|
||||
|
||||
if (Lst_Open (cgn->children) == SUCCESS) {
|
||||
while ((ln = Lst_Next (cgn->children)) != NILLNODE) {
|
||||
gn = (GNode *)Lst_Datum (ln);
|
||||
|
||||
if (Lst_Member (pgn->children, gn) == NILLNODE) {
|
||||
(void) Lst_AtEnd (pgn->children, gn);
|
||||
(void) Lst_AtEnd (gn->parents, pgn);
|
||||
pgn->unmade += 1;
|
||||
}
|
||||
}
|
||||
Lst_Close (cgn->children);
|
||||
}
|
||||
|
||||
pgn->type |= cgn->type & ~(OP_OPMASK|OP_USE|OP_TRANSFORM);
|
||||
|
||||
/*
|
||||
* This child node is now "made", so we decrement the count of
|
||||
* unmade children in the parent... We also remove the child
|
||||
* from the parent's list to accurately reflect the number of decent
|
||||
* children the parent has. This is used by Make_Run to decide
|
||||
* whether to queue the parent or examine its children...
|
||||
*/
|
||||
if (cgn->type & OP_USE) {
|
||||
pgn->unmade -= 1;
|
||||
}
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*-
|
||||
*-----------------------------------------------------------------------
|
||||
* Make_Update --
|
||||
* Perform update on the parents of a node. Used by JobFinish once
|
||||
* a node has been dealt with and by MakeStartJobs if it finds an
|
||||
* up-to-date node.
|
||||
*
|
||||
* Results:
|
||||
* Always returns 0
|
||||
*
|
||||
* Side Effects:
|
||||
* The unmade field of pgn is decremented and pgn may be placed on
|
||||
* the toBeMade queue if this field becomes 0.
|
||||
*
|
||||
* If the child was made, the parent's childMade field will be set true
|
||||
* and its cmtime set to now.
|
||||
*
|
||||
* If the child wasn't made, the cmtime field of the parent will be
|
||||
* altered if the child's mtime is big enough.
|
||||
*
|
||||
* Finally, if the child is the implied source for the parent, the
|
||||
* parent's IMPSRC variable is set appropriately.
|
||||
*
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
void
|
||||
Make_Update (cgn)
|
||||
register GNode *cgn; /* the child node */
|
||||
{
|
||||
register GNode *pgn; /* the parent node */
|
||||
register char *cname; /* the child's name */
|
||||
register LstNode ln; /* Element in parents and iParents lists */
|
||||
|
||||
cname = Var_Value (TARGET, cgn);
|
||||
|
||||
/*
|
||||
* If the child was actually made, see what its modification time is
|
||||
* now -- some rules won't actually update the file. If the file still
|
||||
* doesn't exist, make its mtime now.
|
||||
*/
|
||||
if (cgn->made != UPTODATE) {
|
||||
#ifndef RECHECK
|
||||
/*
|
||||
* We can't re-stat the thing, but we can at least take care of rules
|
||||
* where a target depends on a source that actually creates the
|
||||
* target, but only if it has changed, e.g.
|
||||
*
|
||||
* parse.h : parse.o
|
||||
*
|
||||
* parse.o : parse.y
|
||||
* yacc -d parse.y
|
||||
* cc -c y.tab.c
|
||||
* mv y.tab.o parse.o
|
||||
* cmp -s y.tab.h parse.h || mv y.tab.h parse.h
|
||||
*
|
||||
* In this case, if the definitions produced by yacc haven't changed
|
||||
* from before, parse.h won't have been updated and cgn->mtime will
|
||||
* reflect the current modification time for parse.h. This is
|
||||
* something of a kludge, I admit, but it's a useful one..
|
||||
* XXX: People like to use a rule like
|
||||
*
|
||||
* FRC:
|
||||
*
|
||||
* To force things that depend on FRC to be made, so we have to
|
||||
* check for gn->children being empty as well...
|
||||
*/
|
||||
if (!Lst_IsEmpty(cgn->commands) || Lst_IsEmpty(cgn->children)) {
|
||||
cgn->mtime = now;
|
||||
}
|
||||
#else
|
||||
/*
|
||||
* This is what Make does and it's actually a good thing, as it
|
||||
* allows rules like
|
||||
*
|
||||
* cmp -s y.tab.h parse.h || cp y.tab.h parse.h
|
||||
*
|
||||
* to function as intended. Unfortunately, thanks to the stateless
|
||||
* nature of NFS (by which I mean the loose coupling of two clients
|
||||
* using the same file from a common server), there are times
|
||||
* when the modification time of a file created on a remote
|
||||
* machine will not be modified before the local stat() implied by
|
||||
* the Dir_MTime occurs, thus leading us to believe that the file
|
||||
* is unchanged, wreaking havoc with files that depend on this one.
|
||||
*
|
||||
* I have decided it is better to make too much than to make too
|
||||
* little, so this stuff is commented out unless you're sure it's ok.
|
||||
* -- ardeb 1/12/88
|
||||
*/
|
||||
/*
|
||||
* Christos, 4/9/92: If we are saving commands pretend that
|
||||
* the target is made now. Otherwise archives with ... rules
|
||||
* don't work!
|
||||
*/
|
||||
if (noExecute || (cgn->type & OP_SAVE_CMDS) || Dir_MTime(cgn) == 0) {
|
||||
cgn->mtime = now;
|
||||
}
|
||||
if (DEBUG(MAKE)) {
|
||||
printf("update time: %s\n", Targ_FmtTime(cgn->mtime));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (Lst_Open (cgn->parents) == SUCCESS) {
|
||||
while ((ln = Lst_Next (cgn->parents)) != NILLNODE) {
|
||||
pgn = (GNode *)Lst_Datum (ln);
|
||||
if (pgn->make) {
|
||||
pgn->unmade -= 1;
|
||||
|
||||
if ( ! (cgn->type & (OP_EXEC|OP_USE))) {
|
||||
if (cgn->made == MADE) {
|
||||
pgn->childMade = TRUE;
|
||||
if (pgn->cmtime < cgn->mtime) {
|
||||
pgn->cmtime = cgn->mtime;
|
||||
}
|
||||
} else {
|
||||
(void)Make_TimeStamp (pgn, cgn);
|
||||
}
|
||||
}
|
||||
if (pgn->unmade == 0) {
|
||||
/*
|
||||
* Queue the node up -- any unmade predecessors will
|
||||
* be dealt with in MakeStartJobs.
|
||||
*/
|
||||
(void)Lst_EnQueue (toBeMade, (ClientData)pgn);
|
||||
} else if (pgn->unmade < 0) {
|
||||
Error ("Graph cycles through %s", pgn->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
Lst_Close (cgn->parents);
|
||||
}
|
||||
/*
|
||||
* Deal with successor nodes. If any is marked for making and has an unmade
|
||||
* count of 0, has not been made and isn't in the examination queue,
|
||||
* it means we need to place it in the queue as it restrained itself
|
||||
* before.
|
||||
*/
|
||||
for (ln = Lst_First(cgn->successors); ln != NILLNODE; ln = Lst_Succ(ln)) {
|
||||
GNode *succ = (GNode *)Lst_Datum(ln);
|
||||
|
||||
if (succ->make && succ->unmade == 0 && succ->made == UNMADE &&
|
||||
Lst_Member(toBeMade, (ClientData)succ) == NILLNODE)
|
||||
{
|
||||
(void)Lst_EnQueue(toBeMade, (ClientData)succ);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the .PREFIX and .IMPSRC variables for all the implied parents
|
||||
* of this node.
|
||||
*/
|
||||
if (Lst_Open (cgn->iParents) == SUCCESS) {
|
||||
char *cpref = Var_Value(PREFIX, cgn);
|
||||
|
||||
while ((ln = Lst_Next (cgn->iParents)) != NILLNODE) {
|
||||
pgn = (GNode *)Lst_Datum (ln);
|
||||
if (pgn->make) {
|
||||
Var_Set (IMPSRC, cname, pgn);
|
||||
Var_Set (PREFIX, cpref, pgn);
|
||||
}
|
||||
}
|
||||
Lst_Close (cgn->iParents);
|
||||
}
|
||||
}
|
||||
|
||||
/*-
|
||||
*-----------------------------------------------------------------------
|
||||
* MakeAddAllSrc --
|
||||
* Add a child's name to the ALLSRC and OODATE variables of the given
|
||||
* node. Called from Make_DoAllVar via Lst_ForEach. A child is added only
|
||||
* if it has not been given the .EXEC, .USE or .INVISIBLE attributes.
|
||||
* .EXEC and .USE children are very rarely going to be files, so...
|
||||
* A child is added to the OODATE variable if its modification time is
|
||||
* later than that of its parent, as defined by Make, except if the
|
||||
* parent is a .JOIN node. In that case, it is only added to the OODATE
|
||||
* variable if it was actually made (since .JOIN nodes don't have
|
||||
* modification times, the comparison is rather unfair...)..
|
||||
*
|
||||
* Results:
|
||||
* Always returns 0
|
||||
*
|
||||
* Side Effects:
|
||||
* The ALLSRC variable for the given node is extended.
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
static int
|
||||
MakeAddAllSrc (cgn, pgn)
|
||||
GNode *cgn; /* The child to add */
|
||||
GNode *pgn; /* The parent to whose ALLSRC variable it should be */
|
||||
/* added */
|
||||
{
|
||||
if ((cgn->type & (OP_EXEC|OP_USE|OP_INVISIBLE)) == 0) {
|
||||
register char *child;
|
||||
|
||||
child = Var_Value(TARGET, cgn);
|
||||
Var_Append (ALLSRC, child, pgn);
|
||||
if (pgn->type & OP_JOIN) {
|
||||
if (cgn->made == MADE) {
|
||||
Var_Append(OODATE, child, pgn);
|
||||
}
|
||||
} else if ((pgn->mtime < cgn->mtime) ||
|
||||
(cgn->mtime >= now && cgn->made == MADE))
|
||||
{
|
||||
/*
|
||||
* It goes in the OODATE variable if the parent is younger than the
|
||||
* child or if the child has been modified more recently than
|
||||
* the start of the make. This is to keep pmake from getting
|
||||
* confused if something else updates the parent after the
|
||||
* make starts (shouldn't happen, I know, but sometimes it
|
||||
* does). In such a case, if we've updated the kid, the parent
|
||||
* is likely to have a modification time later than that of
|
||||
* the kid and anything that relies on the OODATE variable will
|
||||
* be hosed.
|
||||
*
|
||||
* XXX: This will cause all made children to go in the OODATE
|
||||
* variable, even if they're not touched, if RECHECK isn't defined,
|
||||
* since cgn->mtime is set to now in Make_Update. According to
|
||||
* some people, this is good...
|
||||
*/
|
||||
Var_Append(OODATE, child, pgn);
|
||||
}
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*-
|
||||
*-----------------------------------------------------------------------
|
||||
* Make_DoAllVar --
|
||||
* Set up the ALLSRC and OODATE variables. Sad to say, it must be
|
||||
* done separately, rather than while traversing the graph. This is
|
||||
* because Make defined OODATE to contain all sources whose modification
|
||||
* times were later than that of the target, *not* those sources that
|
||||
* were out-of-date. Since in both compatibility and native modes,
|
||||
* the modification time of the parent isn't found until the child
|
||||
* has been dealt with, we have to wait until now to fill in the
|
||||
* variable. As for ALLSRC, the ordering is important and not
|
||||
* guaranteed when in native mode, so it must be set here, too.
|
||||
*
|
||||
* Results:
|
||||
* None
|
||||
*
|
||||
* Side Effects:
|
||||
* The ALLSRC and OODATE variables of the given node is filled in.
|
||||
* If the node is a .JOIN node, its TARGET variable will be set to
|
||||
* match its ALLSRC variable.
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
void
|
||||
Make_DoAllVar (gn)
|
||||
GNode *gn;
|
||||
{
|
||||
Lst_ForEach (gn->children, MakeAddAllSrc, gn);
|
||||
|
||||
if (!Var_Exists (OODATE, gn)) {
|
||||
Var_Set (OODATE, "", gn);
|
||||
}
|
||||
if (!Var_Exists (ALLSRC, gn)) {
|
||||
Var_Set (ALLSRC, "", gn);
|
||||
}
|
||||
|
||||
if (gn->type & OP_JOIN) {
|
||||
Var_Set (TARGET, Var_Value (ALLSRC, gn), gn);
|
||||
}
|
||||
}
|
||||
|
||||
/*-
|
||||
*-----------------------------------------------------------------------
|
||||
* MakeStartJobs --
|
||||
* Start as many jobs as possible.
|
||||
*
|
||||
* Results:
|
||||
* If the query flag was given to pmake, no job will be started,
|
||||
* but as soon as an out-of-date target is found, this function
|
||||
* returns TRUE. At all other times, this function returns FALSE.
|
||||
*
|
||||
* Side Effects:
|
||||
* Nodes are removed from the toBeMade queue and job table slots
|
||||
* are filled.
|
||||
*
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
static Boolean
|
||||
MakeStartJobs ()
|
||||
{
|
||||
register GNode *gn;
|
||||
|
||||
while (!Job_Full() && !Lst_IsEmpty (toBeMade)) {
|
||||
gn = (GNode *) Lst_DeQueue (toBeMade);
|
||||
if (DEBUG(MAKE)) {
|
||||
printf ("Examining %s...", gn->name);
|
||||
}
|
||||
/*
|
||||
* Make sure any and all predecessors that are going to be made,
|
||||
* have been.
|
||||
*/
|
||||
if (!Lst_IsEmpty(gn->preds)) {
|
||||
LstNode ln;
|
||||
|
||||
for (ln = Lst_First(gn->preds); ln != NILLNODE; ln = Lst_Succ(ln)){
|
||||
GNode *pgn = (GNode *)Lst_Datum(ln);
|
||||
|
||||
if (pgn->make && pgn->made == UNMADE) {
|
||||
if (DEBUG(MAKE)) {
|
||||
printf("predecessor %s not made yet.\n", pgn->name);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* If ln isn't nil, there's a predecessor as yet unmade, so we
|
||||
* just drop this node on the floor. When the node in question
|
||||
* has been made, it will notice this node as being ready to
|
||||
* make but as yet unmade and will place the node on the queue.
|
||||
*/
|
||||
if (ln != NILLNODE) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
numNodes--;
|
||||
if (Make_OODate (gn)) {
|
||||
if (DEBUG(MAKE)) {
|
||||
printf ("out-of-date\n");
|
||||
}
|
||||
if (queryFlag) {
|
||||
return (TRUE);
|
||||
}
|
||||
Make_DoAllVar (gn);
|
||||
Job_Make (gn);
|
||||
} else {
|
||||
if (DEBUG(MAKE)) {
|
||||
printf ("up-to-date\n");
|
||||
}
|
||||
gn->made = UPTODATE;
|
||||
if (gn->type & OP_JOIN) {
|
||||
/*
|
||||
* Even for an up-to-date .JOIN node, we need it to have its
|
||||
* context variables so references to it get the correct
|
||||
* value for .TARGET when building up the context variables
|
||||
* of its parent(s)...
|
||||
*/
|
||||
Make_DoAllVar (gn);
|
||||
}
|
||||
|
||||
Make_Update (gn);
|
||||
}
|
||||
}
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
/*-
|
||||
*-----------------------------------------------------------------------
|
||||
* MakePrintStatus --
|
||||
* Print the status of a top-level node, viz. it being up-to-date
|
||||
* already or not created due to an error in a lower level.
|
||||
* Callback function for Make_Run via Lst_ForEach.
|
||||
*
|
||||
* Results:
|
||||
* Always returns 0.
|
||||
*
|
||||
* Side Effects:
|
||||
* A message may be printed.
|
||||
*
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
static int
|
||||
MakePrintStatus(gn, cycle)
|
||||
GNode *gn; /* Node to examine */
|
||||
Boolean cycle; /* True if gn->unmade being non-zero implies
|
||||
* a cycle in the graph, not an error in an
|
||||
* inferior */
|
||||
{
|
||||
if (gn->made == UPTODATE) {
|
||||
printf ("`%s' is up to date.\n", gn->name);
|
||||
} else if (gn->unmade != 0) {
|
||||
if (cycle) {
|
||||
/*
|
||||
* If printing cycles and came to one that has unmade children,
|
||||
* print out the cycle by recursing on its children. Note a
|
||||
* cycle like:
|
||||
* a : b
|
||||
* b : c
|
||||
* c : b
|
||||
* will cause this to erroneously complain about a being in
|
||||
* the cycle, but this is a good approximation.
|
||||
*/
|
||||
if (gn->made == CYCLE) {
|
||||
Error("Graph cycles through `%s'", gn->name);
|
||||
gn->made = ENDCYCLE;
|
||||
Lst_ForEach(gn->children, MakePrintStatus, (ClientData)TRUE);
|
||||
gn->made = UNMADE;
|
||||
} else if (gn->made != ENDCYCLE) {
|
||||
gn->made = CYCLE;
|
||||
Lst_ForEach(gn->children, MakePrintStatus, (ClientData)TRUE);
|
||||
}
|
||||
} else {
|
||||
printf ("`%s' not remade because of errors.\n", gn->name);
|
||||
}
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*-
|
||||
*-----------------------------------------------------------------------
|
||||
* Make_Run --
|
||||
* Initialize the nodes to remake and the list of nodes which are
|
||||
* ready to be made by doing a breadth-first traversal of the graph
|
||||
* starting from the nodes in the given list. Once this traversal
|
||||
* is finished, all the 'leaves' of the graph are in the toBeMade
|
||||
* queue.
|
||||
* Using this queue and the Job module, work back up the graph,
|
||||
* calling on MakeStartJobs to keep the job table as full as
|
||||
* possible.
|
||||
*
|
||||
* Results:
|
||||
* TRUE if work was done. FALSE otherwise.
|
||||
*
|
||||
* Side Effects:
|
||||
* The make field of all nodes involved in the creation of the given
|
||||
* targets is set to 1. The toBeMade list is set to contain all the
|
||||
* 'leaves' of these subgraphs.
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
Boolean
|
||||
Make_Run (targs)
|
||||
Lst targs; /* the initial list of targets */
|
||||
{
|
||||
register GNode *gn; /* a temporary pointer */
|
||||
register Lst examine; /* List of targets to examine */
|
||||
int errors; /* Number of errors the Job module reports */
|
||||
|
||||
toBeMade = Lst_Init (FALSE);
|
||||
|
||||
examine = Lst_Duplicate(targs, NOCOPY);
|
||||
numNodes = 0;
|
||||
|
||||
/*
|
||||
* Make an initial downward pass over the graph, marking nodes to be made
|
||||
* as we go down. We call Suff_FindDeps to find where a node is and
|
||||
* to get some children for it if it has none and also has no commands.
|
||||
* If the node is a leaf, we stick it on the toBeMade queue to
|
||||
* be looked at in a minute, otherwise we add its children to our queue
|
||||
* and go on about our business.
|
||||
*/
|
||||
while (!Lst_IsEmpty (examine)) {
|
||||
gn = (GNode *) Lst_DeQueue (examine);
|
||||
|
||||
if (!gn->make) {
|
||||
gn->make = TRUE;
|
||||
numNodes++;
|
||||
|
||||
/*
|
||||
* Apply any .USE rules before looking for implicit dependencies
|
||||
* to make sure everything has commands that should...
|
||||
*/
|
||||
Lst_ForEach (gn->children, Make_HandleUse, (ClientData)gn);
|
||||
Suff_FindDeps (gn);
|
||||
|
||||
if (gn->unmade != 0) {
|
||||
Lst_ForEach (gn->children, MakeAddChild, (ClientData)examine);
|
||||
} else {
|
||||
(void)Lst_EnQueue (toBeMade, (ClientData)gn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Lst_Destroy (examine, NOFREE);
|
||||
|
||||
if (queryFlag) {
|
||||
/*
|
||||
* We wouldn't do any work unless we could start some jobs in the
|
||||
* next loop... (we won't actually start any, of course, this is just
|
||||
* to see if any of the targets was out of date)
|
||||
*/
|
||||
return (MakeStartJobs());
|
||||
} else {
|
||||
/*
|
||||
* Initialization. At the moment, no jobs are running and until some
|
||||
* get started, nothing will happen since the remaining upward
|
||||
* traversal of the graph is performed by the routines in job.c upon
|
||||
* the finishing of a job. So we fill the Job table as much as we can
|
||||
* before going into our loop.
|
||||
*/
|
||||
(void) MakeStartJobs();
|
||||
}
|
||||
|
||||
/*
|
||||
* Main Loop: The idea here is that the ending of jobs will take
|
||||
* care of the maintenance of data structures and the waiting for output
|
||||
* will cause us to be idle most of the time while our children run as
|
||||
* much as possible. Because the job table is kept as full as possible,
|
||||
* the only time when it will be empty is when all the jobs which need
|
||||
* running have been run, so that is the end condition of this loop.
|
||||
* Note that the Job module will exit if there were any errors unless the
|
||||
* keepgoing flag was given.
|
||||
*/
|
||||
while (!Job_Empty ()) {
|
||||
Job_CatchOutput ();
|
||||
Job_CatchChildren (!usePipes);
|
||||
(void)MakeStartJobs();
|
||||
}
|
||||
|
||||
errors = Job_End();
|
||||
|
||||
/*
|
||||
* Print the final status of each target. E.g. if it wasn't made
|
||||
* because some inferior reported an error.
|
||||
*/
|
||||
Lst_ForEach(targs, MakePrintStatus,
|
||||
(ClientData)((errors == 0) && (numNodes != 0)));
|
||||
|
||||
return (TRUE);
|
||||
}
|
357
usr.bin/make/make.h
Normal file
357
usr.bin/make/make.h
Normal file
@ -0,0 +1,357 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* @(#)make.h 8.1 (Berkeley) 6/6/93
|
||||
*/
|
||||
|
||||
/*-
|
||||
* make.h --
|
||||
* The global definitions for pmake
|
||||
*/
|
||||
|
||||
#ifndef _MAKE_H_
|
||||
#define _MAKE_H_
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <sys/cdefs.h>
|
||||
#if __STDC__
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include "sprite.h"
|
||||
#include "lst.h"
|
||||
#include "config.h"
|
||||
#include "buf.h"
|
||||
|
||||
/*-
|
||||
* The structure for an individual graph node. Each node has several
|
||||
* pieces of data associated with it.
|
||||
* 1) the name of the target it describes
|
||||
* 2) the location of the target file in the file system.
|
||||
* 3) the type of operator used to define its sources (qv. parse.c)
|
||||
* 4) whether it is involved in this invocation of make
|
||||
* 5) whether the target has been remade
|
||||
* 6) whether any of its children has been remade
|
||||
* 7) the number of its children that are, as yet, unmade
|
||||
* 8) its modification time
|
||||
* 9) the modification time of its youngest child (qv. make.c)
|
||||
* 10) a list of nodes for which this is a source
|
||||
* 11) a list of nodes on which this depends
|
||||
* 12) a list of nodes that depend on this, as gleaned from the
|
||||
* transformation rules.
|
||||
* 13) a list of nodes of the same name created by the :: operator
|
||||
* 14) a list of nodes that must be made (if they're made) before
|
||||
* this node can be, but that do no enter into the datedness of
|
||||
* this node.
|
||||
* 15) a list of nodes that must be made (if they're made) after
|
||||
* this node is, but that do not depend on this node, in the
|
||||
* normal sense.
|
||||
* 16) a Lst of ``local'' variables that are specific to this target
|
||||
* and this target only (qv. var.c [$@ $< $?, etc.])
|
||||
* 17) a Lst of strings that are commands to be given to a shell
|
||||
* to create this target.
|
||||
*/
|
||||
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) */
|
||||
|
||||
Boolean make; /* TRUE if this target needs to be remade */
|
||||
enum {
|
||||
UNMADE, BEINGMADE, MADE, UPTODATE, ERROR, ABORTED,
|
||||
CYCLE, ENDCYCLE,
|
||||
} made; /* Set to reflect the state of processing
|
||||
* on this node:
|
||||
* UNMADE - Not examined yet
|
||||
* BEINGMADE - Target is already being made.
|
||||
* Indicates a cycle in the graph. (compat
|
||||
* mode only)
|
||||
* MADE - Was out-of-date and has been made
|
||||
* UPTODATE - Was already up-to-date
|
||||
* ERROR - An error occured while it was being
|
||||
* made (used only in compat mode)
|
||||
* ABORTED - The target was aborted due to
|
||||
* an error making an inferior (compat).
|
||||
* CYCLE - Marked as potentially being part of
|
||||
* a graph cycle. If we come back to a
|
||||
* node marked this way, it is printed
|
||||
* and 'made' is changed to ENDCYCLE.
|
||||
* ENDCYCLE - the cycle has been completely
|
||||
* printed. Go back and unmark all its
|
||||
* members.
|
||||
*/
|
||||
Boolean childMade; /* TRUE if one of this target's children was
|
||||
* made */
|
||||
int unmade; /* The number of unmade children */
|
||||
|
||||
int mtime; /* Its modification time */
|
||||
int cmtime; /* The modification time of its youngest
|
||||
* child */
|
||||
|
||||
Lst iParents; /* Links to parents for which this is an
|
||||
* implied source, if any */
|
||||
Lst cohorts; /* Other nodes for the :: operator */
|
||||
Lst parents; /* Nodes that depend on this one */
|
||||
Lst children; /* Nodes on which this one depends */
|
||||
Lst successors; /* Nodes that must be made after this one */
|
||||
Lst preds; /* Nodes that must be made before this one */
|
||||
|
||||
Lst context; /* The local variables */
|
||||
Lst commands; /* Creation commands */
|
||||
|
||||
struct _Suff *suffix; /* Suffix for the node (determined by
|
||||
* Suff_FindDeps and opaque to everyone
|
||||
* but the Suff module) */
|
||||
} GNode;
|
||||
|
||||
/*
|
||||
* Manifest constants
|
||||
*/
|
||||
#define NILGNODE ((GNode *) NIL)
|
||||
|
||||
/*
|
||||
* The OP_ constants are used when parsing a dependency line as a way of
|
||||
* communicating to other parts of the program the way in which a target
|
||||
* should be made. These constants are bitwise-OR'ed together and
|
||||
* placed in the 'type' field of each node. Any node that has
|
||||
* a 'type' field which satisfies the OP_NOP function was never never on
|
||||
* the lefthand side of an operator, though it may have been on the
|
||||
* righthand side...
|
||||
*/
|
||||
#define OP_DEPENDS 0x00000001 /* Execution of commands depends on
|
||||
* kids (:) */
|
||||
#define OP_FORCE 0x00000002 /* Always execute commands (!) */
|
||||
#define OP_DOUBLEDEP 0x00000004 /* Execution of commands depends on kids
|
||||
* per line (::) */
|
||||
#define OP_OPMASK (OP_DEPENDS|OP_FORCE|OP_DOUBLEDEP)
|
||||
|
||||
#define OP_OPTIONAL 0x00000008 /* Don't care if the target doesn't
|
||||
* exist and can't be created */
|
||||
#define OP_USE 0x00000010 /* Use associated commands for parents */
|
||||
#define OP_EXEC 0x00000020 /* Target is never out of date, but always
|
||||
* execute commands anyway. Its time
|
||||
* doesn't matter, so it has none...sort
|
||||
* of */
|
||||
#define OP_IGNORE 0x00000040 /* Ignore errors when creating the node */
|
||||
#define OP_PRECIOUS 0x00000080 /* Don't remove the target when
|
||||
* interrupted */
|
||||
#define OP_SILENT 0x00000100 /* Don't echo commands when executed */
|
||||
#define OP_MAKE 0x00000200 /* Target is a recurrsive make so its
|
||||
* commands should always be executed when
|
||||
* it is out of date, regardless of the
|
||||
* state of the -n or -t flags */
|
||||
#define OP_JOIN 0x00000400 /* Target is out-of-date only if any of its
|
||||
* children was out-of-date */
|
||||
#define OP_INVISIBLE 0x00004000 /* The node is invisible to its parents.
|
||||
* I.e. it doesn't show up in the parents's
|
||||
* local variables. */
|
||||
#define OP_NOTMAIN 0x00008000 /* The node is exempt from normal 'main
|
||||
* target' processing in parse.c */
|
||||
/* 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 */
|
||||
#define OP_LIB 0x20000000 /* Target is a library */
|
||||
#define OP_ARCHV 0x10000000 /* Target is an archive construct */
|
||||
#define OP_HAS_COMMANDS 0x08000000 /* Target has all the commands it should.
|
||||
* Used when parsing to catch multiple
|
||||
* commands for a target */
|
||||
#define OP_SAVE_CMDS 0x04000000 /* Saving commands on .END (Compat) */
|
||||
#define OP_DEPS_FOUND 0x02000000 /* Already processed by Suff_FindDeps */
|
||||
|
||||
/*
|
||||
* OP_NOP will return TRUE if the node with the given type was not the
|
||||
* object of a dependency operator
|
||||
*/
|
||||
#define OP_NOP(t) (((t) & OP_OPMASK) == 0x00000000)
|
||||
|
||||
/*
|
||||
* The TARG_ constants are used when calling the Targ_FindNode and
|
||||
* Targ_FindList functions in targ.c. They simply tell the functions what to
|
||||
* do if the desired node(s) is (are) not found. If the TARG_CREATE constant
|
||||
* is given, a new, empty node will be created for the target, placed in the
|
||||
* table of all targets and its address returned. If TARG_NOCREATE is given,
|
||||
* a NIL pointer will be returned.
|
||||
*/
|
||||
#define TARG_CREATE 0x01 /* create node if not found */
|
||||
#define TARG_NOCREATE 0x00 /* don't create it */
|
||||
|
||||
/*
|
||||
* There are several places where expandable buffers are used (parse.c and
|
||||
* var.c). This constant is merely the starting point for those buffers. If
|
||||
* lines tend to be much shorter than this, it would be best to reduce BSIZE.
|
||||
* If longer, it should be increased. Reducing it will cause more copying to
|
||||
* be done for longer lines, but will save space for shorter ones. In any
|
||||
* case, it ought to be a power of two simply because most storage allocation
|
||||
* schemes allocate in powers of two.
|
||||
*/
|
||||
#define MAKE_BSIZE 256 /* starting size for expandable buffers */
|
||||
|
||||
/*
|
||||
* These constants are all used by the Str_Concat function to decide how the
|
||||
* final string should look. If STR_ADDSPACE is given, a space will be
|
||||
* placed between the two strings. If STR_ADDSLASH is given, a '/' will
|
||||
* be used instead of a space. If neither is given, no intervening characters
|
||||
* will be placed between the two strings in the final output. If the
|
||||
* STR_DOFREE bit is set, the two input strings will be freed before
|
||||
* Str_Concat returns.
|
||||
*/
|
||||
#define STR_ADDSPACE 0x01 /* add a space when Str_Concat'ing */
|
||||
#define STR_DOFREE 0x02 /* free source strings after concatenation */
|
||||
#define STR_ADDSLASH 0x04 /* add a slash when Str_Concat'ing */
|
||||
|
||||
/*
|
||||
* Error levels for parsing. PARSE_FATAL means the process cannot continue
|
||||
* once the makefile has been parsed. PARSE_WARNING means it can. Passed
|
||||
* as the first argument to Parse_Error.
|
||||
*/
|
||||
#define PARSE_WARNING 2
|
||||
#define PARSE_FATAL 1
|
||||
|
||||
/*
|
||||
* Values returned by Cond_Eval.
|
||||
*/
|
||||
#define COND_PARSE 0 /* Parse the next lines */
|
||||
#define COND_SKIP 1 /* Skip the next lines */
|
||||
#define COND_INVALID 2 /* Not a conditional statement */
|
||||
|
||||
/*
|
||||
* Definitions for the "local" variables. Used only for clarity.
|
||||
*/
|
||||
#define TARGET "@" /* Target of dependency */
|
||||
#define OODATE "?" /* All out-of-date sources */
|
||||
#define ALLSRC ">" /* All sources */
|
||||
#define IMPSRC "<" /* Source implied by transformation */
|
||||
#define PREFIX "*" /* Common prefix */
|
||||
#define ARCHIVE "!" /* Archive in "archive(member)" syntax */
|
||||
#define MEMBER "%" /* Member in "archive(member)" syntax */
|
||||
|
||||
#define FTARGET "@F" /* file part of TARGET */
|
||||
#define DTARGET "@D" /* directory part of TARGET */
|
||||
#define FIMPSRC "<F" /* file part of IMPSRC */
|
||||
#define DIMPSRC "<D" /* directory part of IMPSRC */
|
||||
#define FPREFIX "*F" /* file part of PREFIX */
|
||||
#define DPREFIX "*D" /* directory part of PREFIX */
|
||||
|
||||
/*
|
||||
* Global Variables
|
||||
*/
|
||||
extern Lst create; /* The list of target names specified on the
|
||||
* command line. used to resolve #if
|
||||
* make(...) statements */
|
||||
extern Lst dirSearchPath; /* The list of directories to search when
|
||||
* looking for targets */
|
||||
|
||||
extern Boolean compatMake; /* True if we are make compatible */
|
||||
extern Boolean ignoreErrors; /* True if should ignore all errors */
|
||||
extern Boolean beSilent; /* True if should print no commands */
|
||||
extern Boolean noExecute; /* True if should execute nothing */
|
||||
extern Boolean allPrecious; /* True if every target is precious */
|
||||
extern Boolean keepgoing; /* True if should continue on unaffected
|
||||
* portions of the graph when have an error
|
||||
* in one portion */
|
||||
extern Boolean touchFlag; /* TRUE if targets should just be 'touched'
|
||||
* if out of date. Set by the -t flag */
|
||||
extern Boolean usePipes; /* TRUE if should capture the output of
|
||||
* subshells by means of pipes. Otherwise it
|
||||
* is routed to temporary files from which it
|
||||
* is retrieved when the shell exits */
|
||||
extern Boolean queryFlag; /* TRUE if we aren't supposed to really make
|
||||
* anything, just see if the targets are out-
|
||||
* of-date */
|
||||
|
||||
extern Boolean checkEnvFirst; /* TRUE if environment should be searched for
|
||||
* variables before the global context */
|
||||
|
||||
extern GNode *DEFAULT; /* .DEFAULT rule */
|
||||
|
||||
extern GNode *VAR_GLOBAL; /* Variables defined in a global context, e.g
|
||||
* in the Makefile itself */
|
||||
extern GNode *VAR_CMD; /* Variables defined on the command line */
|
||||
extern char var_Error[]; /* Value returned by Var_Parse when an error
|
||||
* is encountered. It actually points to
|
||||
* an empty string, so naive callers needn't
|
||||
* worry about it. */
|
||||
|
||||
extern time_t now; /* The time at the start of this whole
|
||||
* process */
|
||||
|
||||
extern Boolean oldVars; /* Do old-style variable substitution */
|
||||
|
||||
/*
|
||||
* debug control:
|
||||
* There is one bit per module. It is up to the module what debug
|
||||
* information to print.
|
||||
*/
|
||||
extern int debug;
|
||||
#define DEBUG_ARCH 0x0001
|
||||
#define DEBUG_COND 0x0002
|
||||
#define DEBUG_DIR 0x0004
|
||||
#define DEBUG_GRAPH1 0x0008
|
||||
#define DEBUG_GRAPH2 0x0010
|
||||
#define DEBUG_JOB 0x0020
|
||||
#define DEBUG_MAKE 0x0040
|
||||
#define DEBUG_SUFF 0x0080
|
||||
#define DEBUG_TARG 0x0100
|
||||
#define DEBUG_VAR 0x0200
|
||||
#define DEBUG_FOR 0x0400
|
||||
|
||||
#ifdef __STDC__
|
||||
#define CONCAT(a,b) a##b
|
||||
#else
|
||||
#define I(a) a
|
||||
#define CONCAT(a,b) I(a)b
|
||||
#endif /* __STDC__ */
|
||||
|
||||
#define DEBUG(module) (debug & CONCAT(DEBUG_,module))
|
||||
|
||||
/*
|
||||
* Since there are so many, all functions that return non-integer values are
|
||||
* extracted by means of a sed script or two and stuck in the file "nonints.h"
|
||||
*/
|
||||
#include "nonints.h"
|
||||
|
||||
void Make_DoAllVar __P((GNode *));
|
||||
int Make_HandleUse __P((GNode *, GNode *));
|
||||
Boolean Make_OODate __P((GNode *));
|
||||
Boolean Make_Run __P((Lst));
|
||||
int Make_TimeStamp __P((GNode *, GNode *));
|
||||
void Make_Update __P((GNode *));
|
||||
|
||||
#endif /* _MAKE_H_ */
|
132
usr.bin/make/nonints.h
Normal file
132
usr.bin/make/nonints.h
Normal file
@ -0,0 +1,132 @@
|
||||
/*-
|
||||
* 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.
|
||||
*
|
||||
* @(#)nonints.h 8.3 (Berkeley) 3/19/94
|
||||
*/
|
||||
|
||||
/* arch.c */
|
||||
ReturnStatus Arch_ParseArchive __P((char **, Lst, GNode *));
|
||||
void Arch_Touch __P((GNode *));
|
||||
void Arch_TouchLib __P((GNode *));
|
||||
int Arch_MTime __P((GNode *));
|
||||
int Arch_MemMTime __P((GNode *));
|
||||
void Arch_FindLib __P((GNode *, Lst));
|
||||
Boolean Arch_LibOODate __P((GNode *));
|
||||
void Arch_Init __P((void));
|
||||
|
||||
/* compat.c */
|
||||
void Compat_Run __P((Lst));
|
||||
|
||||
/* cond.c */
|
||||
int Cond_Eval __P((char *));
|
||||
void Cond_End __P((void));
|
||||
|
||||
/* for.c */
|
||||
int For_Eval __P((char *));
|
||||
void For_Run __P((void));
|
||||
|
||||
/* main.c */
|
||||
void Main_ParseArgLine __P((char *));
|
||||
int main __P((int, char **));
|
||||
void Error __P((const char *, ...));
|
||||
void Fatal __P((const char *, ...));
|
||||
void Punt __P((const char *, ...));
|
||||
void DieHorribly __P((void));
|
||||
void Finish __P((int));
|
||||
char *emalloc __P((u_int));
|
||||
void enomem __P((void));
|
||||
|
||||
/* parse.c */
|
||||
void Parse_Error __P((int, const char *, ...));
|
||||
Boolean Parse_AnyExport __P((void));
|
||||
Boolean Parse_IsVar __P((char *));
|
||||
void Parse_DoVar __P((char *, GNode *));
|
||||
void Parse_AddIncludeDir __P((char *));
|
||||
void Parse_File __P((char *, FILE *));
|
||||
void Parse_Init __P((void));
|
||||
void Parse_FromString __P((char *));
|
||||
Lst Parse_MainName __P((void));
|
||||
|
||||
/* str.c */
|
||||
char *str_concat __P((char *, char *, int));
|
||||
char **brk_string __P((char *, int *));
|
||||
char *Str_FindSubstring __P((char *, char *));
|
||||
int Str_Match __P((char *, char *));
|
||||
char *Str_SYSVMatch __P((char *, char *, int *len));
|
||||
void Str_SYSVSubst __P((Buffer, char *, char *, int));
|
||||
|
||||
/* suff.c */
|
||||
void Suff_ClearSuffixes __P((void));
|
||||
Boolean Suff_IsTransform __P((char *));
|
||||
GNode *Suff_AddTransform __P((char *));
|
||||
int Suff_EndTransform __P((GNode *));
|
||||
void Suff_AddSuffix __P((char *));
|
||||
Lst Suff_GetPath __P((char *));
|
||||
void Suff_DoPaths __P((void));
|
||||
void Suff_AddInclude __P((char *));
|
||||
void Suff_AddLib __P((char *));
|
||||
void Suff_FindDeps __P((GNode *));
|
||||
void Suff_SetNull __P((char *));
|
||||
void Suff_Init __P((void));
|
||||
void Suff_PrintAll __P((void));
|
||||
|
||||
/* targ.c */
|
||||
void Targ_Init __P((void));
|
||||
GNode *Targ_NewGN __P((char *));
|
||||
GNode *Targ_FindNode __P((char *, int));
|
||||
Lst Targ_FindList __P((Lst, int));
|
||||
Boolean Targ_Ignore __P((GNode *));
|
||||
Boolean Targ_Silent __P((GNode *));
|
||||
Boolean Targ_Precious __P((GNode *));
|
||||
void Targ_SetMain __P((GNode *));
|
||||
int Targ_PrintCmd __P((char *));
|
||||
char *Targ_FmtTime __P((time_t));
|
||||
void Targ_PrintType __P((int));
|
||||
void Targ_PrintGraph __P((int));
|
||||
|
||||
/* var.c */
|
||||
void Var_Delete __P((char *, GNode *));
|
||||
void Var_Set __P((char *, char *, GNode *));
|
||||
void Var_Append __P((char *, char *, GNode *));
|
||||
Boolean Var_Exists __P((char *, GNode *));
|
||||
char *Var_Value __P((char *, GNode *));
|
||||
char *Var_Parse __P((char *, GNode *, Boolean, int *, Boolean *));
|
||||
char *Var_Subst __P((char *, char *, GNode *, Boolean));
|
||||
char *Var_GetTail __P((char *));
|
||||
char *Var_GetHead __P((char *));
|
||||
void Var_Init __P((void));
|
||||
void Var_Dump __P((GNode *));
|
2566
usr.bin/make/parse.c
Normal file
2566
usr.bin/make/parse.c
Normal file
File diff suppressed because it is too large
Load Diff
39
usr.bin/make/pathnames.h
Normal file
39
usr.bin/make/pathnames.h
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) 1990, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* @(#)pathnames.h 8.1 (Berkeley) 6/6/93
|
||||
*/
|
||||
|
||||
#define _PATH_OBJDIR "obj"
|
||||
#define _PATH_DEFSHELLDIR "/bin"
|
||||
#define _PATH_DEFSYSMK "sys.mk"
|
||||
#define _PATH_DEFSYSPATH "/usr/share/mk"
|
114
usr.bin/make/sprite.h
Normal file
114
usr.bin/make/sprite.h
Normal file
@ -0,0 +1,114 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* @(#)sprite.h 8.1 (Berkeley) 6/6/93
|
||||
*/
|
||||
|
||||
/*
|
||||
* sprite.h --
|
||||
*
|
||||
* Common constants and type declarations for Sprite.
|
||||
*/
|
||||
|
||||
#ifndef _SPRITE
|
||||
#define _SPRITE
|
||||
|
||||
|
||||
/*
|
||||
* A boolean type is defined as an integer, not an enum. This allows a
|
||||
* boolean argument to be an expression that isn't strictly 0 or 1 valued.
|
||||
*/
|
||||
|
||||
typedef int Boolean;
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#endif TRUE
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif FALSE
|
||||
|
||||
/*
|
||||
* Functions that must return a status can return a ReturnStatus to
|
||||
* indicate success or type of failure.
|
||||
*/
|
||||
|
||||
typedef int ReturnStatus;
|
||||
|
||||
/*
|
||||
* The following statuses overlap with the first 2 generic statuses
|
||||
* defined in status.h:
|
||||
*
|
||||
* SUCCESS There was no error.
|
||||
* FAILURE There was a general error.
|
||||
*/
|
||||
|
||||
#define SUCCESS 0x00000000
|
||||
#define FAILURE 0x00000001
|
||||
|
||||
|
||||
/*
|
||||
* A nil pointer must be something that will cause an exception if
|
||||
* referenced. There are two nils: the kernels nil and the nil used
|
||||
* by user processes.
|
||||
*/
|
||||
|
||||
#define NIL (~0)
|
||||
#define USER_NIL 0
|
||||
#ifndef NULL
|
||||
#define NULL 0
|
||||
#endif NULL
|
||||
|
||||
/*
|
||||
* An address is just a pointer in C. It is defined as a character pointer
|
||||
* so that address arithmetic will work properly, a byte at a time.
|
||||
*/
|
||||
|
||||
typedef char *Address;
|
||||
|
||||
/*
|
||||
* ClientData is an uninterpreted word. It is defined as an int so that
|
||||
* kdbx will not interpret client data as a string. Unlike an "Address",
|
||||
* client data will generally not be used in arithmetic.
|
||||
*/
|
||||
|
||||
typedef int *ClientData;
|
||||
|
||||
#ifdef notdef
|
||||
#include "status.h"
|
||||
#endif
|
||||
|
||||
#endif _SPRITE
|
439
usr.bin/make/str.c
Normal file
439
usr.bin/make/str.c
Normal file
@ -0,0 +1,439 @@
|
||||
/*-
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)str.c 8.4 (Berkeley) 3/21/94";
|
||||
#endif /* not lint */
|
||||
|
||||
#include "make.h"
|
||||
|
||||
/*-
|
||||
* str_concat --
|
||||
* concatenate the two strings, inserting a space or slash between them,
|
||||
* freeing them if requested.
|
||||
*
|
||||
* returns --
|
||||
* the resulting string in allocated space.
|
||||
*/
|
||||
char *
|
||||
str_concat(s1, s2, flags)
|
||||
char *s1, *s2;
|
||||
int flags;
|
||||
{
|
||||
register int len1, len2;
|
||||
register char *result;
|
||||
|
||||
/* get the length of both strings */
|
||||
len1 = strlen(s1);
|
||||
len2 = strlen(s2);
|
||||
|
||||
/* allocate length plus separator plus EOS */
|
||||
result = emalloc((u_int)(len1 + len2 + 2));
|
||||
|
||||
/* copy first string into place */
|
||||
memcpy(result, s1, len1);
|
||||
|
||||
/* add separator character */
|
||||
if (flags & STR_ADDSPACE) {
|
||||
result[len1] = ' ';
|
||||
++len1;
|
||||
} else if (flags & STR_ADDSLASH) {
|
||||
result[len1] = '/';
|
||||
++len1;
|
||||
}
|
||||
|
||||
/* copy second string plus EOS into place */
|
||||
memcpy(result + len1, s2, len2 + 1);
|
||||
|
||||
/* free original strings */
|
||||
if (flags & STR_DOFREE) {
|
||||
(void)free(s1);
|
||||
(void)free(s2);
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
/*-
|
||||
* brk_string --
|
||||
* Fracture a string into an array of words (as delineated by tabs or
|
||||
* spaces) taking quotation marks into account. Leading tabs/spaces
|
||||
* are ignored.
|
||||
*
|
||||
* returns --
|
||||
* Pointer to the array of pointers to the words. To make life easier,
|
||||
* the first word is always the value of the .MAKE variable.
|
||||
*/
|
||||
char **
|
||||
brk_string(str, store_argc)
|
||||
register char *str;
|
||||
int *store_argc;
|
||||
{
|
||||
static int argmax, curlen;
|
||||
static char **argv, *buf;
|
||||
register int argc, ch;
|
||||
register char inquote, *p, *start, *t;
|
||||
int len;
|
||||
|
||||
/* save off pmake variable */
|
||||
if (!argv) {
|
||||
argv = (char **)emalloc((argmax = 50) * sizeof(char *));
|
||||
argv[0] = Var_Value(".MAKE", VAR_GLOBAL);
|
||||
}
|
||||
|
||||
/* skip leading space chars. */
|
||||
for (; *str == ' ' || *str == '\t'; ++str)
|
||||
continue;
|
||||
|
||||
/* allocate room for a copy of the string */
|
||||
if ((len = strlen(str) + 1) > curlen)
|
||||
buf = emalloc(curlen = len);
|
||||
|
||||
/*
|
||||
* copy the string; at the same time, parse backslashes,
|
||||
* quotes and build the argument list.
|
||||
*/
|
||||
argc = 1;
|
||||
inquote = '\0';
|
||||
for (p = str, start = t = buf;; ++p) {
|
||||
switch(ch = *p) {
|
||||
case '"':
|
||||
case '\'':
|
||||
if (inquote)
|
||||
if (inquote == ch)
|
||||
inquote = '\0';
|
||||
else
|
||||
break;
|
||||
else
|
||||
inquote = (char) ch;
|
||||
continue;
|
||||
case ' ':
|
||||
case '\t':
|
||||
if (inquote)
|
||||
break;
|
||||
if (!start)
|
||||
continue;
|
||||
/* FALLTHROUGH */
|
||||
case '\n':
|
||||
case '\0':
|
||||
/*
|
||||
* end of a token -- make sure there's enough argv
|
||||
* space and save off a pointer.
|
||||
*/
|
||||
*t++ = '\0';
|
||||
if (argc == argmax) {
|
||||
argmax *= 2; /* ramp up fast */
|
||||
if (!(argv = (char **)realloc(argv,
|
||||
argmax * sizeof(char *))))
|
||||
enomem();
|
||||
}
|
||||
argv[argc++] = start;
|
||||
start = (char *)NULL;
|
||||
if (ch == '\n' || ch == '\0')
|
||||
goto done;
|
||||
continue;
|
||||
case '\\':
|
||||
switch (ch = *++p) {
|
||||
case '\0':
|
||||
case '\n':
|
||||
/* hmmm; fix it up as best we can */
|
||||
ch = '\\';
|
||||
--p;
|
||||
break;
|
||||
case 'b':
|
||||
ch = '\b';
|
||||
break;
|
||||
case 'f':
|
||||
ch = '\f';
|
||||
break;
|
||||
case 'n':
|
||||
ch = '\n';
|
||||
break;
|
||||
case 'r':
|
||||
ch = '\r';
|
||||
break;
|
||||
case 't':
|
||||
ch = '\t';
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (!start)
|
||||
start = t;
|
||||
*t++ = (char) ch;
|
||||
}
|
||||
done: argv[argc] = (char *)NULL;
|
||||
*store_argc = argc;
|
||||
return(argv);
|
||||
}
|
||||
|
||||
/*
|
||||
* Str_FindSubstring -- See if a string contains a particular substring.
|
||||
*
|
||||
* Results: If string contains substring, the return value is the location of
|
||||
* the first matching instance of substring in string. If string doesn't
|
||||
* contain substring, the return value is NULL. Matching is done on an exact
|
||||
* character-for-character basis with no wildcards or special characters.
|
||||
*
|
||||
* Side effects: None.
|
||||
*/
|
||||
char *
|
||||
Str_FindSubstring(string, substring)
|
||||
register char *string; /* String to search. */
|
||||
char *substring; /* Substring to find in string */
|
||||
{
|
||||
register char *a, *b;
|
||||
|
||||
/*
|
||||
* First scan quickly through the two strings looking for a single-
|
||||
* character match. When it's found, then compare the rest of the
|
||||
* substring.
|
||||
*/
|
||||
|
||||
for (b = substring; *string != 0; string += 1) {
|
||||
if (*string != *b)
|
||||
continue;
|
||||
a = string;
|
||||
for (;;) {
|
||||
if (*b == 0)
|
||||
return(string);
|
||||
if (*a++ != *b++)
|
||||
break;
|
||||
}
|
||||
b = substring;
|
||||
}
|
||||
return((char *) NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Str_Match --
|
||||
*
|
||||
* See if a particular string matches a particular pattern.
|
||||
*
|
||||
* Results: Non-zero is returned if string matches pattern, 0 otherwise. The
|
||||
* matching operation permits the following special characters in the
|
||||
* pattern: *?\[] (see the man page for details on what these mean).
|
||||
*
|
||||
* Side effects: None.
|
||||
*/
|
||||
int
|
||||
Str_Match(string, pattern)
|
||||
register char *string; /* String */
|
||||
register char *pattern; /* Pattern */
|
||||
{
|
||||
char c2;
|
||||
|
||||
for (;;) {
|
||||
/*
|
||||
* See if we're at the end of both the pattern and the
|
||||
* string. If, we succeeded. If we're at the end of the
|
||||
* pattern but not at the end of the string, we failed.
|
||||
*/
|
||||
if (*pattern == 0)
|
||||
return(!*string);
|
||||
if (*string == 0 && *pattern != '*')
|
||||
return(0);
|
||||
/*
|
||||
* Check for a "*" as the next pattern character. It matches
|
||||
* any substring. We handle this by calling ourselves
|
||||
* recursively for each postfix of string, until either we
|
||||
* match or we reach the end of the string.
|
||||
*/
|
||||
if (*pattern == '*') {
|
||||
pattern += 1;
|
||||
if (*pattern == 0)
|
||||
return(1);
|
||||
while (*string != 0) {
|
||||
if (Str_Match(string, pattern))
|
||||
return(1);
|
||||
++string;
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
/*
|
||||
* Check for a "?" as the next pattern character. It matches
|
||||
* any single character.
|
||||
*/
|
||||
if (*pattern == '?')
|
||||
goto thisCharOK;
|
||||
/*
|
||||
* Check for a "[" as the next pattern character. It is
|
||||
* followed by a list of characters that are acceptable, or
|
||||
* by a range (two characters separated by "-").
|
||||
*/
|
||||
if (*pattern == '[') {
|
||||
++pattern;
|
||||
for (;;) {
|
||||
if ((*pattern == ']') || (*pattern == 0))
|
||||
return(0);
|
||||
if (*pattern == *string)
|
||||
break;
|
||||
if (pattern[1] == '-') {
|
||||
c2 = pattern[2];
|
||||
if (c2 == 0)
|
||||
return(0);
|
||||
if ((*pattern <= *string) &&
|
||||
(c2 >= *string))
|
||||
break;
|
||||
if ((*pattern >= *string) &&
|
||||
(c2 <= *string))
|
||||
break;
|
||||
pattern += 2;
|
||||
}
|
||||
++pattern;
|
||||
}
|
||||
while ((*pattern != ']') && (*pattern != 0))
|
||||
++pattern;
|
||||
goto thisCharOK;
|
||||
}
|
||||
/*
|
||||
* If the next pattern character is '/', just strip off the
|
||||
* '/' so we do exact matching on the character that follows.
|
||||
*/
|
||||
if (*pattern == '\\') {
|
||||
++pattern;
|
||||
if (*pattern == 0)
|
||||
return(0);
|
||||
}
|
||||
/*
|
||||
* There's no special character. Just make sure that the
|
||||
* next characters of each string match.
|
||||
*/
|
||||
if (*pattern != *string)
|
||||
return(0);
|
||||
thisCharOK: ++pattern;
|
||||
++string;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*-
|
||||
*-----------------------------------------------------------------------
|
||||
* Str_SYSVMatch --
|
||||
* Check word against pattern for a match (% is wild),
|
||||
*
|
||||
* Results:
|
||||
* Returns the beginning position of a match or null. The number
|
||||
* of characters matched is returned in len.
|
||||
*
|
||||
* Side Effects:
|
||||
* None
|
||||
*
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
char *
|
||||
Str_SYSVMatch(word, pattern, len)
|
||||
char *word; /* Word to examine */
|
||||
char *pattern; /* Pattern to examine against */
|
||||
int *len; /* Number of characters to substitute */
|
||||
{
|
||||
char *p = pattern;
|
||||
char *w = word;
|
||||
char *m;
|
||||
|
||||
if (*p == '\0') {
|
||||
/* Null pattern is the whole string */
|
||||
*len = strlen(w);
|
||||
return w;
|
||||
}
|
||||
|
||||
if ((m = strchr(p, '%')) != NULL) {
|
||||
/* check that the prefix matches */
|
||||
for (; p != m && *w && *w == *p; w++, p++)
|
||||
continue;
|
||||
|
||||
if (p != m)
|
||||
return NULL; /* No match */
|
||||
|
||||
if (*++p == '\0') {
|
||||
/* No more pattern, return the rest of the string */
|
||||
*len = strlen(w);
|
||||
return w;
|
||||
}
|
||||
}
|
||||
|
||||
m = w;
|
||||
|
||||
/* Find a matching tail */
|
||||
do
|
||||
if (strcmp(p, w) == 0) {
|
||||
*len = w - m;
|
||||
return m;
|
||||
}
|
||||
while (*w++ != '\0');
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/*-
|
||||
*-----------------------------------------------------------------------
|
||||
* Str_SYSVSubst --
|
||||
* Substitute '%' on the pattern with len characters from src.
|
||||
* If the pattern does not contain a '%' prepend len characters
|
||||
* from src.
|
||||
*
|
||||
* Results:
|
||||
* None
|
||||
*
|
||||
* Side Effects:
|
||||
* Places result on buf
|
||||
*
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
void
|
||||
Str_SYSVSubst(buf, pat, src, len)
|
||||
Buffer buf;
|
||||
char *pat;
|
||||
char *src;
|
||||
int len;
|
||||
{
|
||||
char *m;
|
||||
|
||||
if ((m = strchr(pat, '%')) != NULL) {
|
||||
/* Copy the prefix */
|
||||
Buf_AddBytes(buf, m - pat, (Byte *) pat);
|
||||
/* skip the % */
|
||||
pat = m + 1;
|
||||
}
|
||||
|
||||
/* Copy the pattern */
|
||||
Buf_AddBytes(buf, len, (Byte *) src);
|
||||
|
||||
/* append the rest */
|
||||
Buf_AddBytes(buf, strlen(pat), (Byte *) pat);
|
||||
}
|
2218
usr.bin/make/suff.c
Normal file
2218
usr.bin/make/suff.c
Normal file
File diff suppressed because it is too large
Load Diff
585
usr.bin/make/targ.c
Normal file
585
usr.bin/make/targ.c
Normal file
@ -0,0 +1,585 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)targ.c 8.2 (Berkeley) 3/19/94";
|
||||
#endif /* not lint */
|
||||
|
||||
/*-
|
||||
* targ.c --
|
||||
* Functions for maintaining the Lst allTargets. Target nodes are
|
||||
* kept in two structures: a Lst, maintained by the list library, and a
|
||||
* hash table, maintained by the hash library.
|
||||
*
|
||||
* Interface:
|
||||
* Targ_Init Initialization procedure.
|
||||
*
|
||||
* Targ_NewGN Create a new GNode for the passed target
|
||||
* (string). The node is *not* placed in the
|
||||
* hash table, though all its fields are
|
||||
* initialized.
|
||||
*
|
||||
* Targ_FindNode Find the node for a given target, creating
|
||||
* and storing it if it doesn't exist and the
|
||||
* flags are right (TARG_CREATE)
|
||||
*
|
||||
* Targ_FindList Given a list of names, find nodes for all
|
||||
* of them. If a name doesn't exist and the
|
||||
* TARG_NOCREATE flag was given, an error message
|
||||
* is printed. Else, if a name doesn't exist,
|
||||
* its node is created.
|
||||
*
|
||||
* Targ_Ignore Return TRUE if errors should be ignored when
|
||||
* creating the given target.
|
||||
*
|
||||
* Targ_Silent Return TRUE if we should be silent when
|
||||
* creating the given target.
|
||||
*
|
||||
* Targ_Precious Return TRUE if the target is precious and
|
||||
* should not be removed if we are interrupted.
|
||||
*
|
||||
* Debugging:
|
||||
* Targ_PrintGraph Print out the entire graphm all variables
|
||||
* and statistics for the directory cache. Should
|
||||
* print something for suffixes, too, but...
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include "make.h"
|
||||
#include "hash.h"
|
||||
#include "dir.h"
|
||||
|
||||
static Lst allTargets; /* the list of all targets found so far */
|
||||
static Hash_Table targets; /* a hash table of same */
|
||||
|
||||
#define HTSIZE 191 /* initial size of hash table */
|
||||
|
||||
/*-
|
||||
*-----------------------------------------------------------------------
|
||||
* Targ_Init --
|
||||
* Initialize this module
|
||||
*
|
||||
* Results:
|
||||
* None
|
||||
*
|
||||
* Side Effects:
|
||||
* The allTargets list and the targets hash table are initialized
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
void
|
||||
Targ_Init ()
|
||||
{
|
||||
allTargets = Lst_Init (FALSE);
|
||||
Hash_InitTable (&targets, HTSIZE);
|
||||
}
|
||||
|
||||
/*-
|
||||
*-----------------------------------------------------------------------
|
||||
* Targ_NewGN --
|
||||
* Create and initialize a new graph node
|
||||
*
|
||||
* Results:
|
||||
* An initialized graph node with the name field filled with a copy
|
||||
* of the passed name
|
||||
*
|
||||
* Side Effects:
|
||||
* None.
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
GNode *
|
||||
Targ_NewGN (name)
|
||||
char *name; /* the name to stick in the new node */
|
||||
{
|
||||
register GNode *gn;
|
||||
|
||||
gn = (GNode *) emalloc (sizeof (GNode));
|
||||
gn->name = strdup (name);
|
||||
gn->path = (char *) 0;
|
||||
if (name[0] == '-' && name[1] == 'l') {
|
||||
gn->type = OP_LIB;
|
||||
} else {
|
||||
gn->type = 0;
|
||||
}
|
||||
gn->unmade = 0;
|
||||
gn->make = FALSE;
|
||||
gn->made = UNMADE;
|
||||
gn->childMade = FALSE;
|
||||
gn->mtime = gn->cmtime = 0;
|
||||
gn->iParents = Lst_Init (FALSE);
|
||||
gn->cohorts = Lst_Init (FALSE);
|
||||
gn->parents = Lst_Init (FALSE);
|
||||
gn->children = Lst_Init (FALSE);
|
||||
gn->successors = Lst_Init(FALSE);
|
||||
gn->preds = Lst_Init(FALSE);
|
||||
gn->context = Lst_Init (FALSE);
|
||||
gn->commands = Lst_Init (FALSE);
|
||||
gn->suffix = NULL;
|
||||
|
||||
return (gn);
|
||||
}
|
||||
|
||||
/*-
|
||||
*-----------------------------------------------------------------------
|
||||
* Targ_FindNode --
|
||||
* Find a node in the list using the given name for matching
|
||||
*
|
||||
* Results:
|
||||
* The node in the list if it was. If it wasn't, return NILGNODE of
|
||||
* flags was TARG_NOCREATE or the newly created and initialized node
|
||||
* if it was TARG_CREATE
|
||||
*
|
||||
* Side Effects:
|
||||
* Sometimes a node is created and added to the list
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
GNode *
|
||||
Targ_FindNode (name, flags)
|
||||
char *name; /* the name to find */
|
||||
int flags; /* flags governing events when target not
|
||||
* found */
|
||||
{
|
||||
GNode *gn; /* node in that element */
|
||||
Hash_Entry *he; /* New or used hash entry for node */
|
||||
Boolean isNew; /* Set TRUE if Hash_CreateEntry had to create */
|
||||
/* an entry for the node */
|
||||
|
||||
|
||||
if (flags & TARG_CREATE) {
|
||||
he = Hash_CreateEntry (&targets, name, &isNew);
|
||||
if (isNew) {
|
||||
gn = Targ_NewGN (name);
|
||||
Hash_SetValue (he, gn);
|
||||
(void) Lst_AtEnd (allTargets, (ClientData)gn);
|
||||
}
|
||||
} else {
|
||||
he = Hash_FindEntry (&targets, name);
|
||||
}
|
||||
|
||||
if (he == (Hash_Entry *) NULL) {
|
||||
return (NILGNODE);
|
||||
} else {
|
||||
return ((GNode *) Hash_GetValue (he));
|
||||
}
|
||||
}
|
||||
|
||||
/*-
|
||||
*-----------------------------------------------------------------------
|
||||
* Targ_FindList --
|
||||
* Make a complete list of GNodes from the given list of names
|
||||
*
|
||||
* Results:
|
||||
* A complete list of graph nodes corresponding to all instances of all
|
||||
* the names in names.
|
||||
*
|
||||
* Side Effects:
|
||||
* If flags is TARG_CREATE, nodes will be created for all names in
|
||||
* names which do not yet have graph nodes. If flags is TARG_NOCREATE,
|
||||
* an error message will be printed for each name which can't be found.
|
||||
* -----------------------------------------------------------------------
|
||||
*/
|
||||
Lst
|
||||
Targ_FindList (names, flags)
|
||||
Lst names; /* list of names to find */
|
||||
int flags; /* flags used if no node is found for a given
|
||||
* name */
|
||||
{
|
||||
Lst nodes; /* result list */
|
||||
register LstNode ln; /* name list element */
|
||||
register GNode *gn; /* node in tLn */
|
||||
char *name;
|
||||
|
||||
nodes = Lst_Init (FALSE);
|
||||
|
||||
if (Lst_Open (names) == FAILURE) {
|
||||
return (nodes);
|
||||
}
|
||||
while ((ln = Lst_Next (names)) != NILLNODE) {
|
||||
name = (char *)Lst_Datum(ln);
|
||||
gn = Targ_FindNode (name, flags);
|
||||
if (gn != NILGNODE) {
|
||||
/*
|
||||
* Note: Lst_AtEnd must come before the Lst_Concat so the nodes
|
||||
* are added to the list in the order in which they were
|
||||
* encountered in the makefile.
|
||||
*/
|
||||
(void) Lst_AtEnd (nodes, (ClientData)gn);
|
||||
if (gn->type & OP_DOUBLEDEP) {
|
||||
(void)Lst_Concat (nodes, gn->cohorts, LST_CONCNEW);
|
||||
}
|
||||
} else if (flags == TARG_NOCREATE) {
|
||||
Error ("\"%s\" -- target unknown.", name);
|
||||
}
|
||||
}
|
||||
Lst_Close (names);
|
||||
return (nodes);
|
||||
}
|
||||
|
||||
/*-
|
||||
*-----------------------------------------------------------------------
|
||||
* Targ_Ignore --
|
||||
* Return true if should ignore errors when creating gn
|
||||
*
|
||||
* Results:
|
||||
* TRUE if should ignore errors
|
||||
*
|
||||
* Side Effects:
|
||||
* None
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
Boolean
|
||||
Targ_Ignore (gn)
|
||||
GNode *gn; /* node to check for */
|
||||
{
|
||||
if (ignoreErrors || gn->type & OP_IGNORE) {
|
||||
return (TRUE);
|
||||
} else {
|
||||
return (FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
/*-
|
||||
*-----------------------------------------------------------------------
|
||||
* Targ_Silent --
|
||||
* Return true if be silent when creating gn
|
||||
*
|
||||
* Results:
|
||||
* TRUE if should be silent
|
||||
*
|
||||
* Side Effects:
|
||||
* None
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
Boolean
|
||||
Targ_Silent (gn)
|
||||
GNode *gn; /* node to check for */
|
||||
{
|
||||
if (beSilent || gn->type & OP_SILENT) {
|
||||
return (TRUE);
|
||||
} else {
|
||||
return (FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
/*-
|
||||
*-----------------------------------------------------------------------
|
||||
* Targ_Precious --
|
||||
* See if the given target is precious
|
||||
*
|
||||
* Results:
|
||||
* TRUE if it is precious. FALSE otherwise
|
||||
*
|
||||
* Side Effects:
|
||||
* None
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
Boolean
|
||||
Targ_Precious (gn)
|
||||
GNode *gn; /* the node to check */
|
||||
{
|
||||
if (allPrecious || (gn->type & (OP_PRECIOUS|OP_DOUBLEDEP))) {
|
||||
return (TRUE);
|
||||
} else {
|
||||
return (FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
/******************* DEBUG INFO PRINTING ****************/
|
||||
|
||||
static GNode *mainTarg; /* the main target, as set by Targ_SetMain */
|
||||
/*-
|
||||
*-----------------------------------------------------------------------
|
||||
* Targ_SetMain --
|
||||
* Set our idea of the main target we'll be creating. Used for
|
||||
* debugging output.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
*
|
||||
* Side Effects:
|
||||
* "mainTarg" is set to the main target's node.
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
void
|
||||
Targ_SetMain (gn)
|
||||
GNode *gn; /* The main target we'll create */
|
||||
{
|
||||
mainTarg = gn;
|
||||
}
|
||||
|
||||
static int
|
||||
/*ARGSUSED*/
|
||||
TargPrintName (gn, ppath)
|
||||
GNode *gn;
|
||||
int ppath;
|
||||
{
|
||||
printf ("%s ", gn->name);
|
||||
#ifdef notdef
|
||||
if (ppath) {
|
||||
if (gn->path) {
|
||||
printf ("[%s] ", gn->path);
|
||||
}
|
||||
if (gn == mainTarg) {
|
||||
printf ("(MAIN NAME) ");
|
||||
}
|
||||
}
|
||||
#endif /* notdef */
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
Targ_PrintCmd (cmd)
|
||||
char *cmd;
|
||||
{
|
||||
printf ("\t%s\n", cmd);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*-
|
||||
*-----------------------------------------------------------------------
|
||||
* Targ_FmtTime --
|
||||
* Format a modification time in some reasonable way and return it.
|
||||
*
|
||||
* Results:
|
||||
* The time reformatted.
|
||||
*
|
||||
* Side Effects:
|
||||
* The time is placed in a static area, so it is overwritten
|
||||
* with each call.
|
||||
*
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
char *
|
||||
Targ_FmtTime (time)
|
||||
time_t time;
|
||||
{
|
||||
struct tm *parts;
|
||||
static char buf[40];
|
||||
static char *months[] = {
|
||||
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
|
||||
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
|
||||
};
|
||||
|
||||
parts = localtime(&time);
|
||||
|
||||
sprintf (buf, "%d:%02d:%02d %s %d, 19%d",
|
||||
parts->tm_hour, parts->tm_min, parts->tm_sec,
|
||||
months[parts->tm_mon], parts->tm_mday, parts->tm_year);
|
||||
return(buf);
|
||||
}
|
||||
|
||||
/*-
|
||||
*-----------------------------------------------------------------------
|
||||
* Targ_PrintType --
|
||||
* Print out a type field giving only those attributes the user can
|
||||
* set.
|
||||
*
|
||||
* Results:
|
||||
*
|
||||
* Side Effects:
|
||||
*
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
void
|
||||
Targ_PrintType (type)
|
||||
register int type;
|
||||
{
|
||||
register int tbit;
|
||||
|
||||
#ifdef __STDC__
|
||||
#define PRINTBIT(attr) case CONCAT(OP_,attr): printf("." #attr " "); break
|
||||
#define PRINTDBIT(attr) case CONCAT(OP_,attr): if (DEBUG(TARG)) printf("." #attr " "); break
|
||||
#else
|
||||
#define PRINTBIT(attr) case CONCAT(OP_,attr): printf(".attr "); break
|
||||
#define PRINTDBIT(attr) case CONCAT(OP_,attr): if (DEBUG(TARG)) printf(".attr "); break
|
||||
#endif /* __STDC__ */
|
||||
|
||||
type &= ~OP_OPMASK;
|
||||
|
||||
while (type) {
|
||||
tbit = 1 << (ffs(type) - 1);
|
||||
type &= ~tbit;
|
||||
|
||||
switch(tbit) {
|
||||
PRINTBIT(OPTIONAL);
|
||||
PRINTBIT(USE);
|
||||
PRINTBIT(EXEC);
|
||||
PRINTBIT(IGNORE);
|
||||
PRINTBIT(PRECIOUS);
|
||||
PRINTBIT(SILENT);
|
||||
PRINTBIT(MAKE);
|
||||
PRINTBIT(JOIN);
|
||||
PRINTBIT(INVISIBLE);
|
||||
PRINTBIT(NOTMAIN);
|
||||
PRINTDBIT(LIB);
|
||||
/*XXX: MEMBER is defined, so CONCAT(OP_,MEMBER) gives OP_"%" */
|
||||
case OP_MEMBER: if (DEBUG(TARG)) printf(".MEMBER "); break;
|
||||
PRINTDBIT(ARCHV);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*-
|
||||
*-----------------------------------------------------------------------
|
||||
* TargPrintNode --
|
||||
* print the contents of a node
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
static int
|
||||
TargPrintNode (gn, pass)
|
||||
GNode *gn;
|
||||
int pass;
|
||||
{
|
||||
if (!OP_NOP(gn->type)) {
|
||||
printf("#\n");
|
||||
if (gn == mainTarg) {
|
||||
printf("# *** MAIN TARGET ***\n");
|
||||
}
|
||||
if (pass == 2) {
|
||||
if (gn->unmade) {
|
||||
printf("# %d unmade children\n", gn->unmade);
|
||||
} else {
|
||||
printf("# No unmade children\n");
|
||||
}
|
||||
if (! (gn->type & (OP_JOIN|OP_USE|OP_EXEC))) {
|
||||
if (gn->mtime != 0) {
|
||||
printf("# last modified %s: %s\n",
|
||||
Targ_FmtTime(gn->mtime),
|
||||
(gn->made == UNMADE ? "unmade" :
|
||||
(gn->made == MADE ? "made" :
|
||||
(gn->made == UPTODATE ? "up-to-date" :
|
||||
"error when made"))));
|
||||
} else if (gn->made != UNMADE) {
|
||||
printf("# non-existent (maybe): %s\n",
|
||||
(gn->made == MADE ? "made" :
|
||||
(gn->made == UPTODATE ? "up-to-date" :
|
||||
(gn->made == ERROR ? "error when made" :
|
||||
"aborted"))));
|
||||
} else {
|
||||
printf("# unmade\n");
|
||||
}
|
||||
}
|
||||
if (!Lst_IsEmpty (gn->iParents)) {
|
||||
printf("# implicit parents: ");
|
||||
Lst_ForEach (gn->iParents, TargPrintName, (ClientData)0);
|
||||
fputc ('\n', stdout);
|
||||
}
|
||||
}
|
||||
if (!Lst_IsEmpty (gn->parents)) {
|
||||
printf("# parents: ");
|
||||
Lst_ForEach (gn->parents, TargPrintName, (ClientData)0);
|
||||
fputc ('\n', stdout);
|
||||
}
|
||||
|
||||
printf("%-16s", gn->name);
|
||||
switch (gn->type & OP_OPMASK) {
|
||||
case OP_DEPENDS:
|
||||
printf(": "); break;
|
||||
case OP_FORCE:
|
||||
printf("! "); break;
|
||||
case OP_DOUBLEDEP:
|
||||
printf(":: "); break;
|
||||
}
|
||||
Targ_PrintType (gn->type);
|
||||
Lst_ForEach (gn->children, TargPrintName, (ClientData)0);
|
||||
fputc ('\n', stdout);
|
||||
Lst_ForEach (gn->commands, Targ_PrintCmd, (ClientData)0);
|
||||
printf("\n\n");
|
||||
if (gn->type & OP_DOUBLEDEP) {
|
||||
Lst_ForEach (gn->cohorts, TargPrintNode, (ClientData)pass);
|
||||
}
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*-
|
||||
*-----------------------------------------------------------------------
|
||||
* TargPrintOnlySrc --
|
||||
* Print only those targets that are just a source.
|
||||
*
|
||||
* Results:
|
||||
* 0.
|
||||
*
|
||||
* Side Effects:
|
||||
* The name of each file is printed preceeded by #\t
|
||||
*
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
static int
|
||||
TargPrintOnlySrc(gn)
|
||||
GNode *gn;
|
||||
{
|
||||
if (OP_NOP(gn->type)) {
|
||||
printf("#\t%s [%s]\n", gn->name,
|
||||
gn->path ? gn->path : gn->name);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*-
|
||||
*-----------------------------------------------------------------------
|
||||
* Targ_PrintGraph --
|
||||
* print the entire graph. heh heh
|
||||
*
|
||||
* Results:
|
||||
* none
|
||||
*
|
||||
* Side Effects:
|
||||
* lots o' output
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
void
|
||||
Targ_PrintGraph (pass)
|
||||
int pass; /* Which pass this is. 1 => no processing
|
||||
* 2 => processing done */
|
||||
{
|
||||
printf("#*** Input graph:\n");
|
||||
Lst_ForEach (allTargets, TargPrintNode, (ClientData)pass);
|
||||
printf("\n\n");
|
||||
printf("#\n# Files that are only sources:\n");
|
||||
Lst_ForEach (allTargets, TargPrintOnlySrc);
|
||||
printf("#*** Global Variables:\n");
|
||||
Var_Dump (VAR_GLOBAL);
|
||||
printf("#*** Command-line Variables:\n");
|
||||
Var_Dump (VAR_CMD);
|
||||
printf("\n");
|
||||
Dir_PrintDirectories();
|
||||
printf("\n");
|
||||
Suff_PrintAll();
|
||||
}
|
1986
usr.bin/make/var.c
Normal file
1986
usr.bin/make/var.c
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user