summaryrefslogtreecommitdiff
path: root/usr.bin/make
diff options
context:
space:
mode:
authorMarc Espie <espie@cvs.openbsd.org>2007-09-17 12:42:10 +0000
committerMarc Espie <espie@cvs.openbsd.org>2007-09-17 12:42:10 +0000
commit04da241c9a9d1947a02599b69c4d28cad730e2ee (patch)
tree411a70834205a49e35f9401bcb6a7d91905ebc7a /usr.bin/make
parent623d7eb586551d91075741d88eb155937894af6b (diff)
rewrite of the basic suffix/target parsing: use hash for suffixes.
Store special targets in target hash, and use them for the parsing. Use OP_DUMMY flag to mark targets that don't really exist yet, such as interrupt and default nodes. Also, .PATHxxx is special in suffixes. Small tweaks to compat.c, so that run_commands does more stuff after the fork() (and thus no need to free things). Remove distinction between local and global jobs.
Diffstat (limited to 'usr.bin/make')
-rw-r--r--usr.bin/make/Makefile14
-rw-r--r--usr.bin/make/compat.c355
-rw-r--r--usr.bin/make/engine.c264
-rw-r--r--usr.bin/make/extern.h2
-rw-r--r--usr.bin/make/gnode.h133
-rw-r--r--usr.bin/make/init.c4
-rw-r--r--usr.bin/make/job.c310
-rw-r--r--usr.bin/make/job.h4
-rw-r--r--usr.bin/make/main.c22
-rw-r--r--usr.bin/make/main.h4
-rw-r--r--usr.bin/make/parse.c1292
-rw-r--r--usr.bin/make/suff.c1360
-rw-r--r--usr.bin/make/suff.h19
-rw-r--r--usr.bin/make/targ.c195
-rw-r--r--usr.bin/make/targ.h22
15 files changed, 1757 insertions, 2243 deletions
diff --git a/usr.bin/make/Makefile b/usr.bin/make/Makefile
index afc59ae3895..c60937fd0ed 100644
--- a/usr.bin/make/Makefile
+++ b/usr.bin/make/Makefile
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.46 2007/09/16 10:39:07 espie Exp $
+# $OpenBSD: Makefile,v 1.47 2007/09/17 12:42:09 espie Exp $
PROG= make
CFLAGS+= -I${.OBJDIR} -I${.CURDIR}
@@ -15,9 +15,8 @@ CDEFS+=-DHAS_EXTENDED_GETCWD
CFLAGS+=${CDEFS}
HOSTCFLAGS+=${CDEFS}
-SRCS= arch.c buf.c cmd_exec.c compat.c cond.c dir.c direxpand.c \
- engine.c error.c for.c \
- init.c job.c lowparse.c main.c make.c memory.c parse.c \
+SRCS= arch.c buf.c cmd_exec.c compat.c cond.c dir.c direxpand.c engine.c \
+ error.c for.c init.c job.c lowparse.c main.c make.c memory.c parse.c \
parsevar.c str.c stats.c suff.c targ.c timestamp.c \
var.c varmodifiers.c varname.c
SRCS+= lstAddNew.c lstAppend.c lstConcat.c lstConcatDestroy.c \
@@ -28,10 +27,9 @@ SRCS+= lstAddNew.c lstAppend.c lstConcat.c lstConcatDestroy.c \
CLEANFILES+=generate hashconsts.h generate.o regress.o check
CLEANFILES+=${LIBOBJS} libohash.a
-CLEANFILES+= varhashconsts.h condhashconsts.h nodehashconsts.h
-CLEANFILES+= generate.o generate
+CLEANFILES+= varhashconsts.h condhashconsts.h generate.o generate
-beforedepend: varhashconsts.h condhashconsts.h
+beforedepend: varhashconsts.h condhashconsts.h nodehashconsts.h
# may need tweaking if you add variable synonyms or change the hash function
MAGICVARSLOTS=77
MAGICCONDSLOTS=65
@@ -57,8 +55,10 @@ regress: check
# kludge for people who forget to make depend
var.o: varhashconsts.h
cond.o: condhashconsts.h
+targ.o parse.o: nodehashconsts.h
var.ln: varhashconsts.h
cond.ln: condhashconsts.h
+targ.ln parse.ln: nodehashconsts.h
.if make(install)
SUBDIR+= PSD.doc
diff --git a/usr.bin/make/compat.c b/usr.bin/make/compat.c
index 29e1cb933f9..b9d7f1a75fa 100644
--- a/usr.bin/make/compat.c
+++ b/usr.bin/make/compat.c
@@ -1,5 +1,5 @@
/* $OpenPackages$ */
-/* $OpenBSD: compat.c,v 1.59 2007/09/17 09:28:36 espie Exp $ */
+/* $OpenBSD: compat.c,v 1.60 2007/09/17 12:42:09 espie Exp $ */
/* $NetBSD: compat.c,v 1.14 1996/11/06 17:59:01 christos Exp $ */
/*
@@ -66,18 +66,13 @@
#include "lst.h"
#include "pathnames.h"
-/* 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 *ENDNode;
static void CompatInterrupt(int);
static int CompatRunCommand(LstNode, void *);
static void CompatMake(void *, void *);
-static int shellneed(char **);
+static int run_gnode(GNode *);
+static void setup_meta(void);
+static char **recheck_command_for_shell(char **);
+static void run_command(const char *, bool);
static volatile sig_atomic_t interrupted;
@@ -88,56 +83,84 @@ CompatInterrupt(int signo)
interrupted = signo;
}
-/*-
- *-----------------------------------------------------------------------
- * shellneed --
- *
- * Results:
- * Returns 1 if a specified set of arguments
- * must be executed by the shell,
- * 0 if it can be run via execve, and -1 if the command can be
- * handled internally
- *
- * Side Effects:
- * May modify the process umask
- *-----------------------------------------------------------------------
- */
-static int
-shellneed(char **av)
+/* 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 void
+setup_meta(void)
+{
+ char *p;
+
+ for (p = "#=|^(){};&<>*?[]:$`\\\n"; *p != '\0'; p++)
+ meta[(unsigned char) *p] = 1;
+ /* The null character serves as a sentinel in the string. */
+ meta[0] = 1;
+}
+
+static char **
+recheck_command_for_shell(char **av)
{
char *runsh[] = {
- "alias", "cd", "eval", "exec", "exit", "read", "set", "ulimit",
- "unalias", "unset", "wait",
- NULL
+ "alias", "cd", "eval", "exit", "read", "set", "ulimit",
+ "unalias", "unset", "wait", "umask", NULL
};
char **p;
- /* FIXME most of these ARE actual no-ops */
+ /* optimization: if exec cmd, we avoid the intermediate shell */
+ if (strcmp(av[0], "exec") == 0)
+ av++;
+
for (p = runsh; *p; p++)
if (strcmp(av[0], *p) == 0)
- return 1;
-
- if (strcmp(av[0], "umask") == 0) {
- long umi;
- char *ep = NULL;
- mode_t um;
-
- if (av[1] != NULL) {
- umi = strtol(av[1], &ep, 8);
- if (ep == NULL)
- return 1;
- um = umi;
- }
- else {
- um = umask(0);
- printf("%o\n", um);
- }
- (void)umask(um);
- return -1;
+ return NULL;
+
+ return av;
+}
+
+static void
+run_command(const char *cmd, bool errCheck)
+{
+ const char *p;
+ char *shargv[4];
+ char **todo;
+
+ shargv[0] = _PATH_BSHELL;
+
+ shargv[1] = errCheck ? "-ec" : "-c";
+ shargv[2] = (char *)cmd;
+ shargv[3] = NULL;
+
+ todo = shargv;
+
+
+ /* 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 (p = cmd; !meta[(unsigned char)*p]; p++)
+ continue;
+ if (*p == '\0') {
+ char *bp;
+ char **av;
+ int argc;
+ /* No meta-characters, so probably no need to exec a shell.
+ * Break the command into words to form an argument vector
+ * we can execute. */
+ av = brk_string(cmd, &argc, &bp);
+ av = recheck_command_for_shell(av);
+ if (av != NULL)
+ todo = av;
}
+ execvp(todo[0], todo);
- return 0;
+ if (errno == ENOENT)
+ fprintf(stderr, "%s: not found\n", todo[0]);
+ else
+ perror(todo[0]);
+ _exit(1);
}
/*-
@@ -154,24 +177,19 @@ shellneed(char **av)
*-----------------------------------------------------------------------
*/
static int
-CompatRunCommand(LstNode cmdNode,/* Command to execute */
- void *gnp) /* Node from which the command came */
+CompatRunCommand(LstNode cmdNode, /* Command to execute */
+ void *gnp) /* Node from which the command came */
{
- char *cmdStart; /* Start of expanded command */
- char *cp, *bp = NULL;
- bool silent; /* Don't print command */
- bool doExecute; /* Execute the command */
- volatile bool errCheck; /* Check errors */
- int reason; /* Reason for child's death */
- int status; /* Description of child's death */
- pid_t cpid; /* Child actually found */
- pid_t stat; /* Status of fork */
- char **volatile av; /* Argument vector for thing to exec */
- int argc; /* Number of arguments in av or 0 if not
- * dynamically allocated */
+ char *cmdStart; /* Start of expanded command */
+ bool silent; /* Don't print command */
+ bool doExecute; /* Execute the command */
+ bool errCheck; /* Check errors */
+ int reason; /* Reason for child's death */
+ int status; /* Description of child's death */
+ pid_t cpid; /* Child actually found */
+ pid_t stat; /* Status of fork */
char *cmd = (char *)Lst_Datum(cmdNode);
GNode *gn = (GNode *)gnp;
- static char *shargv[4] = { _PATH_BSHELL };
silent = gn->type & OP_SILENT;
errCheck = !(gn->type & OP_IGNORE);
@@ -179,11 +197,8 @@ CompatRunCommand(LstNode cmdNode,/* Command to execute */
cmdStart = Var_Subst(cmd, &gn->context, false);
- /* brk_string will return an argv with a NULL in av[0], 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?). */
-
+ /* How can we execute a null command ? we warn the user that the
+ * command expanded to nothing (is this the right thing to do?). */
if (*cmdStart == '\0') {
free(cmdStart);
Error("%s expands to empty string", cmd);
@@ -192,14 +207,14 @@ CompatRunCommand(LstNode cmdNode,/* Command to execute */
cmd = cmdStart;
Lst_Replace(cmdNode, cmdStart);
- if ((gn->type & OP_SAVE_CMDS) && (gn != ENDNode)) {
- Lst_AtEnd(&ENDNode->commands, cmdStart);
+ if ((gn->type & OP_SAVE_CMDS) && (gn != end_node)) {
+ Lst_AtEnd(&end_node->commands, cmdStart);
+ end_node->type &= ~OP_DUMMY;
return 1;
} else if (strcmp(cmdStart, "...") == 0) {
gn->type |= OP_SAVE_CMDS;
return 1;
}
-
for (;; cmd++) {
if (*cmd == '@')
silent = DEBUG(LOUD) ? false : true;
@@ -210,80 +225,29 @@ CompatRunCommand(LstNode cmdNode,/* Command to execute */
else
break;
}
-
while (isspace(*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 (!doExecute)
return 1;
- 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. */
-
- shargv[1] = errCheck ? "-ec" : "-c";
- shargv[2] = cmd;
- shargv[3] = NULL;
- av = shargv;
- argc = 0;
- } else {
- /* No meta-characters, so probably no need to exec a shell.
- * Break the command into words to form an argument vector
- * we can execute. */
- av = brk_string(cmd, &argc, &bp);
- switch (shellneed(av)) {
- case -1: /* handled internally */
- free(bp);
- free(av);
- return 1;
- case 1:
- shargv[1] = errCheck ? "-ec" : "-c";
- shargv[2] = cmd;
- shargv[3] = NULL;
- free(av);
- free(bp);
- bp = NULL;
- av = shargv;
- argc = 0;
- break;
- default: /* nothing needed */
- break;
- }
- }
-
/* Fork and execute the single command. If the fork fails, we abort. */
- cpid = fork();
- if (cpid == -1)
+ switch (cpid = fork()) {
+ case -1:
Fatal("Could not fork");
- if (cpid == 0) {
- execvp(av[0], av);
- if (errno == ENOENT)
- fprintf(stderr, "%s: not found\n", av[0]);
- else
- perror(av[0]);
- _exit(1);
- }
- if (bp) {
- free(av);
- free(bp);
+ /*NOTREACHED*/
+ case 0:
+ run_command(cmd, errCheck);
+ /*NOTREACHED*/
+ default:
+ break;
}
free(cmdStart);
Lst_Replace(cmdNode, NULL);
@@ -305,7 +269,7 @@ CompatRunCommand(LstNode cmdNode,/* Command to execute */
else if (WIFEXITED(reason)) {
status = WEXITSTATUS(reason); /* exited */
if (status != 0)
- printf("*** Error code %d", status);
+ printf("*** Error code %d", status);
} else {
status = WTERMSIG(reason); /* signaled */
printf("*** Signal %d", status);
@@ -320,9 +284,9 @@ CompatRunCommand(LstNode cmdNode,/* Command to execute */
* but let others continue. */
printf(" (continuing)\n");
} else {
- /* Continue executing commands for this
- * target. If we return 0, this will
- * happen... */
+ /* Continue executing commands for
+ * this target. If we return 0,
+ * this will happen... */
printf(" (ignored)\n");
status = 0;
}
@@ -335,25 +299,33 @@ CompatRunCommand(LstNode cmdNode,/* Command to execute */
/* This is reached only if interrupted */
if (!Targ_Precious(gn)) {
- char *file = Varq_Value(TARGET_INDEX, gn);
+ char *file = Varq_Value(TARGET_INDEX, gn);
if (!noExecute && eunlink(file) != -1)
Error("*** %s removed\n", file);
}
if (interrupted == SIGINT) {
- GNode *i = Targ_FindNode(".INTERRUPT", TARG_NOCREATE);
signal(SIGINT, SIG_IGN);
signal(SIGTERM, SIG_IGN);
signal(SIGHUP, SIG_IGN);
signal(SIGQUIT, SIG_IGN);
interrupted = 0;
- if (i != NULL)
- Lst_ForEachNodeWhile(&i->commands, CompatRunCommand, i);
+ run_gnode(interrupt_node);
exit(SIGINT);
}
exit(interrupted);
}
+static int
+run_gnode(GNode *gn)
+{
+ if (gn != NULL && (gn->type & OP_DUMMY) == 0) {
+ Lst_ForEachNodeWhile(&gn->commands, CompatRunCommand, gn);
+ return gn->made;
+ } else
+ return NOSUCHNODE;
+}
+
/*-
*-----------------------------------------------------------------------
* CompatMake --
@@ -379,11 +351,12 @@ CompatMake(void *gnp, /* The node to make */
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. */
+ * 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);
@@ -401,11 +374,11 @@ CompatMake(void *gnp, /* The node to make */
/* 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 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)) {
+ if (!Make_OODate(gn)) {
gn->made = UPTODATE;
if (DEBUG(MAKE))
printf("up-to-date.\n");
@@ -413,41 +386,40 @@ CompatMake(void *gnp, /* The node to make */
} 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 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(). */
+ /* 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)
- Lst_ForEachNodeWhile(&gn->commands,
- CompatRunCommand, gn);
- else
- Job_Touch(gn, gn->type & OP_SILENT);
+ /* Our commands are ok, but we still have to worry
+ * about the -t flag... */
+ if (!touchFlag)
+ run_gnode(gn);
+ 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. */
+ * update its modification time and timestamp all
+ * its parents.
+ * This is to keep its state from affecting that of
+ * its parent. */
gn->made = MADE;
/* This is what Make does and it's actually a good
* thing, as it allows rules like
@@ -455,17 +427,13 @@ CompatMake(void *gnp, /* The node to make */
* 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
+ * 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.
*/
if (noExecute || is_out_of_date(Dir_MTime(gn)))
gn->mtime = now;
@@ -493,8 +461,8 @@ CompatMake(void *gnp, /* The node to make */
exit(1);
}
} else if (gn->made == ERROR)
- /* Already had an error when making this beastie. Tell the
- * parent to abort. */
+ /* Already had an error when making this beastie. Tell the parent
+ * to abort. */
pgn->make = false;
else {
if (Lst_Member(&gn->iParents, pgn) != NULL) {
@@ -526,32 +494,21 @@ CompatMake(void *gnp, /* The node to make */
void
Compat_Run(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 */
+ GNode *gn = NULL; /* Current root target */
+ int errors; /* Number of targets not remade due to errors */
signal(SIGINT, CompatInterrupt);
signal(SIGTERM, CompatInterrupt);
signal(SIGHUP, CompatInterrupt);
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);
+ setup_meta();
/* If the user has defined a .BEGIN target, execute the commands
* attached to it. */
if (!queryFlag) {
- gn = Targ_FindNode(".BEGIN", TARG_NOCREATE);
- if (gn != NULL) {
- Lst_ForEachNodeWhile(&gn->commands, CompatRunCommand,
- gn);
- if (gn->made == ERROR) {
- printf("\n\nStop.\n");
- exit(1);
- }
+ if (run_gnode(begin_node) == ERROR) {
+ printf("\n\nStop.\n");
+ exit(1);
}
}
@@ -560,9 +517,10 @@ Compat_Run(Lst targs) /* List of target nodes to re-create */
* 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
+ * 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.
+ * inferiors could not be made due to errors.
*/
errors = 0;
while ((gn = (GNode *)Lst_DeQueue(targs)) != NULL) {
@@ -579,6 +537,5 @@ Compat_Run(Lst targs) /* List of target nodes to re-create */
/* If the user has defined a .END target, run its commands. */
if (errors == 0)
- Lst_ForEachNodeWhile(&ENDNode->commands, CompatRunCommand,
- ENDNode);
+ run_gnode(end_node);
}
diff --git a/usr.bin/make/engine.c b/usr.bin/make/engine.c
index 960b7b2bc3b..4dba6633604 100644
--- a/usr.bin/make/engine.c
+++ b/usr.bin/make/engine.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: engine.c,v 1.8 2007/09/17 12:19:11 espie Exp $ */
+/* $OpenBSD: engine.c,v 1.9 2007/09/17 12:42:09 espie Exp $ */
/*
* Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
* Copyright (c) 1988, 1989 by Adam de Boor
@@ -51,35 +51,22 @@
#include "lst.h"
#include "timestamp.h"
#include "make.h"
-#include "main.h"
static void MakeTimeStamp(void *, void *);
static void MakeAddAllSrc(void *, void *);
static int rewrite_time(const char *);
-/*-
- *-----------------------------------------------------------------------
- * Job_CheckCommands --
- * Make sure the given node has all the commands it needs.
- *
- * Results:
- * true if the commands list is/was ok.
- *
- * Side Effects:
- * The node will have commands from the .DEFAULT rule added to it
- * if it needs them.
- *-----------------------------------------------------------------------
- */
bool
Job_CheckCommands(GNode *gn, void (*abortProc)(char *, ...))
{
if (OP_NOP(gn->type) && Lst_IsEmpty(&gn->commands) &&
- (gn->type & OP_LIB) == 0) {
+ (gn->type & (OP_NODEFAULT | OP_LIB)) == 0) {
/*
* No commands. Look for .DEFAULT rule from which we might infer
* commands
*/
- if (DEFAULT != NULL && !Lst_IsEmpty(&DEFAULT->commands)) {
+ if ((DEFAULT->type & OP_DUMMY) == 0 &&
+ !Lst_IsEmpty(&DEFAULT->commands)) {
/*
* Make only looks for a .DEFAULT if the node was never
* the target of an operator, so that's what we do too.
@@ -145,24 +132,13 @@ rewrite_time(const char *name)
return 0;
}
-/*-
- *-----------------------------------------------------------------------
- * Job_Touch --
- * Touch the given target. Called by JobStart when the -t flag was
- * given
- *
- * Side Effects:
- * The data modification of the file is changed. In addition, if the
- * file did not exist, it is created.
- *-----------------------------------------------------------------------
- */
void
Job_Touch(GNode *gn, bool silent)
{
if (gn->type & (OP_JOIN|OP_USE|OP_EXEC|OP_OPTIONAL)) {
/*
- * .JOIN, .USE and .OPTIONAL targets are "virtual"
- * targets and, as such, shouldn't really be created.
+ * .JOIN, .USE, and .OPTIONAL targets are "virtual" targets
+ * and, as such, shouldn't really be created.
*/
return;
}
@@ -189,22 +165,11 @@ Job_Touch(GNode *gn, bool silent)
"*** couldn't touch %s: %s", file,
strerror(errno));
(void)fflush(stdout);
- }
+ }
}
}
}
-/*-
- *-----------------------------------------------------------------------
- * Make_TimeStamp --
- * Set the cmtime field of a parent node based on the mtime stamp in its
- * child.
- *
- * Side Effects:
- * The cmtime of the parent node will be changed if the mtime
- * field of the child is greater than it.
- *-----------------------------------------------------------------------
- */
void
Make_TimeStamp(GNode *parent, GNode *child)
{
@@ -212,29 +177,8 @@ Make_TimeStamp(GNode *parent, GNode *child)
parent->cmtime = child->mtime;
}
-/*-
- *-----------------------------------------------------------------------
- * 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.
- *
- * Side Effects:
- * Children and commands may be added to the parent and the parent's
- * type may be changed.
- *
- *-----------------------------------------------------------------------
- */
void
-Make_HandleUse(
- GNode *cgn, /* The .USE node */
+Make_HandleUse(GNode *cgn, /* The .USE node */
GNode *pgn) /* The target of the .USE node */
{
GNode *gn; /* A child of the .USE node */
@@ -242,8 +186,8 @@ Make_HandleUse(
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. */
+ /* .USE or transformation and target has no commands
+ * -- append the child's commands to the parent. */
Lst_Concat(&pgn->commands, &cgn->commands);
}
@@ -264,97 +208,55 @@ Make_HandleUse(
* 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...
+ * decide whether to queue the parent or examine its children...
*/
- if (cgn->type & OP_USE) {
+ if (cgn->type & OP_USE)
pgn->unmade--;
- }
}
}
-/*-
- *-----------------------------------------------------------------------
- * 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...)..
- *
- * Side Effects:
- * The ALLSRC variable for the given node is extended.
- *-----------------------------------------------------------------------
- */
static void
-MakeAddAllSrc(
- void *cgnp, /* The child to add */
- void *pgnp) /* The parent to whose ALLSRC variable it should be */
- /* added */
+MakeAddAllSrc(void *cgnp, void *pgnp)
{
- GNode *cgn = (GNode *)cgnp;
- GNode *pgn = (GNode *)pgnp;
- if ((cgn->type & (OP_EXEC|OP_USE|OP_INVISIBLE)) == 0) {
- const char *child;
+ GNode *child = (GNode *)cgnp;
+ GNode *parent = (GNode *)pgnp;
+ if ((child->type & (OP_EXEC|OP_USE|OP_INVISIBLE)) == 0) {
+ const char *target;
- if (OP_NOP(cgn->type) ||
- (child = Varq_Value(TARGET_INDEX, cgn)) == NULL) {
+ if (OP_NOP(child->type) ||
+ (target = Varq_Value(TARGET_INDEX, child)) == NULL) {
/*
* this node is only source; use the specific pathname
* for it
*/
- child = cgn->path != NULL ? cgn->path : cgn->name;
+ target = child->path != NULL ? child->path :
+ child->name;
}
- Varq_Append(ALLSRC_INDEX, child, pgn);
- if (pgn->type & OP_JOIN) {
- if (cgn->made == MADE) {
- Varq_Append(OODATE_INDEX, child, pgn);
- }
- } else if (is_strictly_before(pgn->mtime, cgn->mtime) ||
- (!is_strictly_before(cgn->mtime, now) &&
- cgn->made == MADE)) {
+ Varq_Append(ALLSRC_INDEX, target, parent);
+ if (parent->type & OP_JOIN) {
+ if (child->made == MADE)
+ Varq_Append(OODATE_INDEX, target, parent);
+ } else if (is_strictly_before(parent->mtime, child->mtime) ||
+ (!is_strictly_before(child->mtime, now) &&
+ child->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.
- *
+ * This is to keep make 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.
*/
- Varq_Append(OODATE_INDEX, child, pgn);
+ Varq_Append(OODATE_INDEX, target, parent);
}
}
}
-/*-
- *-----------------------------------------------------------------------
- * 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.
- *
- * 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(GNode *gn)
{
@@ -371,35 +273,15 @@ Make_DoAllVar(GNode *gn)
/* Wrapper to call Make_TimeStamp from a forEach loop. */
static void
-MakeTimeStamp(
- void *pgn, /* the current parent */
- void *cgn) /* the child we've just examined */
+MakeTimeStamp(void *parent, void *child)
{
- Make_TimeStamp((GNode *)pgn, (GNode *)cgn);
+ Make_TimeStamp((GNode *)parent, (GNode *)child);
}
-/*-
- *-----------------------------------------------------------------------
- * 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.
- *-----------------------------------------------------------------------
- */
bool
-Make_OODate(GNode *gn) /* the node to check */
+Make_OODate(GNode *gn)
{
- bool oodate;
+ bool oodate;
/*
* Certain types of targets needn't even be sought as their datedness
@@ -408,47 +290,38 @@ Make_OODate(GNode *gn) /* the node to check */
if ((gn->type & (OP_JOIN|OP_USE|OP_EXEC)) == 0) {
(void)Dir_MTime(gn);
if (DEBUG(MAKE)) {
- if (!is_out_of_date(gn->mtime)) {
+ if (!is_out_of_date(gn->mtime))
printf("modified %s...",
time_to_string(gn->mtime));
- } else {
+ 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.
+ * - 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-Compatibility 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)) {
+ if (DEBUG(MAKE))
printf(".USE node...");
- }
oodate = false;
} else if ((gn->type & OP_LIB) && Arch_IsLib(gn)) {
- if (DEBUG(MAKE)) {
- printf("library...");
- }
-
- /*
- * always out of date if no children and :: target
- */
+ if (DEBUG(MAKE))
+ printf("library...");
+ /* always out of date if no children and :: target */
oodate = Arch_LibOODate(gn) ||
(is_out_of_date(gn->cmtime) && (gn->type & OP_DOUBLEDEP));
} else if (gn->type & OP_JOIN) {
@@ -456,56 +329,43 @@ Make_OODate(GNode *gn) /* the node to check */
* A target with the .JOIN attribute is only considered
* out-of-date if any of its children was out-of-date.
*/
- if (DEBUG(MAKE)) {
+ if (DEBUG(MAKE))
printf(".JOIN node...");
- }
oodate = gn->childMade;
} else if (gn->type & (OP_FORCE|OP_EXEC|OP_PHONY)) {
/*
- * A node which is the object of the force (!) operator or
- * which has the .EXEC attribute is always considered
- * out-of-date.
+ * 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) {
+ if (gn->type & OP_FORCE)
printf("! operator...");
- } else if (gn->type & OP_PHONY) {
+ else if (gn->type & OP_PHONY)
printf(".PHONY node...");
- } else {
+ else
printf(".EXEC node...");
- }
}
oodate = true;
} else if (is_strictly_before(gn->mtime, gn->cmtime) ||
- (is_out_of_date(gn->cmtime) &&
+ (is_out_of_date(gn->cmtime) &&
(is_out_of_date(gn->mtime) || (gn->type & OP_DOUBLEDEP)))) {
/*
* A node whose modification time is less than that of its
* youngest child or that has no children (cmtime ==
* OUT_OF_DATE) and either doesn't exist (mtime == OUT_OF_DATE)
- * or was the object of a :: operator is out-of-date. Why?
- * Because that's the way Make does it.
+ * or was the object of a :: operator is out-of-date.
*/
if (DEBUG(MAKE)) {
- if (is_strictly_before(gn->mtime, gn->cmtime)) {
+ if (is_strictly_before(gn->mtime, gn->cmtime))
printf("modified before source...");
- } else if (is_out_of_date(gn->mtime)) {
+ else if (is_out_of_date(gn->mtime))
printf("non-existent and no sources...");
- } else {
+ 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 */
}
/*
diff --git a/usr.bin/make/extern.h b/usr.bin/make/extern.h
index 57681882d54..4ea798093aa 100644
--- a/usr.bin/make/extern.h
+++ b/usr.bin/make/extern.h
@@ -2,7 +2,7 @@
#define EXTERN_H
/* $OpenPackages$ */
-/* $OpenBSD: extern.h,v 1.40 2007/09/17 12:01:16 espie Exp $ */
+/* $OpenBSD: extern.h,v 1.41 2007/09/17 12:42:09 espie Exp $ */
/* $NetBSD: nonints.h,v 1.12 1996/11/06 17:59:19 christos Exp $ */
/*-
diff --git a/usr.bin/make/gnode.h b/usr.bin/make/gnode.h
index a4ce27b1ce6..7d5f1770495 100644
--- a/usr.bin/make/gnode.h
+++ b/usr.bin/make/gnode.h
@@ -1,7 +1,7 @@
#ifndef GNODE_H
#define GNODE_H
/* $OpenPackages$ */
-/* $OpenBSD: gnode.h,v 1.4 2001/11/23 23:42:45 deraadt Exp $ */
+/* $OpenBSD: gnode.h,v 1.5 2007/09/17 12:42:09 espie Exp $ */
/*
* Copyright (c) 2001 Marc Espie.
@@ -67,61 +67,78 @@ struct Suff_;
* 17) a Lst of strings that are commands to be given to a shell
* to create this target.
*/
+
+#define UNMADE 0
+#define BEINGMADE 1
+#define MADE 2
+#define UPTODATE 3
+#define ERROR 4
+#define ABORTED 5
+#define CYCLE 6
+#define ENDCYCLE 7
+#define NOSUCHNODE 8
+
+#define SPECIAL_NONE 0
+#define SPECIAL_PATH 21
+#define SPECIAL_MASK 63
+#define SPECIAL_TARGET 64
+#define SPECIAL_SOURCE 128
+#define SPECIAL_TARGETSOURCE (SPECIAL_TARGET|SPECIAL_SOURCE)
+
struct GNode_ {
- char *path; /* The full pathname of the file */
- int type; /* Its type (see the OP flags, below) */
- int order; /* Its wait weight */
-
- bool 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 occurred 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.
- */
- bool childMade; /* true if one of this target's children was
- * made */
- int unmade; /* The number of unmade children */
-
- TIMESTAMP mtime; /* Its modification time */
- TIMESTAMP cmtime; /* The modification time of its youngest
- * child */
-
- LIST iParents; /* Links to parents for which this is an
- * implied source, if any */
- LIST cohorts; /* Other nodes for the :: operator */
- LIST parents; /* Nodes that depend on this one */
- LIST children; /* Nodes on which this one depends */
- LIST successors; /* Nodes that must be made after this one */
- LIST preds; /* Nodes that must be made before this one */
-
- SymTable context; /* The local variables */
- unsigned long lineno; /* First line number of commands. */
- const char * fname; /* File name of commands. */
- LIST commands; /* Creation commands */
- LstNode current; /* Current command, for job */
-
- struct Suff_ *suffix; /* Suffix for the node (determined by
- * Suff_FindDeps and opaque to everyone
- * but the Suff module) */
- char name[1]; /* The target's name */
+ int special_op; /* special op to apply */
+ unsigned char special;/* type of special node */
+ char make; /* true if this target needs to be remade */
+ char childMade; /* true if one of this target's children was
+ * made */
+ char 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 occurred 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.
+ */
+ char *path; /* The full pathname of the file */
+ int type; /* Its type (see the OP flags, below) */
+ int order; /* Its wait weight */
+
+ int unmade; /* The number of unmade children */
+
+ TIMESTAMP mtime; /* Its modification time */
+ TIMESTAMP cmtime; /* The modification time of its youngest
+ * child */
+
+ LIST iParents; /* Links to parents for which this is an
+ * implied source, if any */
+ LIST cohorts; /* Other nodes for the :: operator */
+ LIST parents; /* Nodes that depend on this one */
+ LIST children; /* Nodes on which this one depends */
+ LIST successors; /* Nodes that must be made after this one */
+ LIST preds; /* Nodes that must be made before this one */
+
+ SymTable context; /* The local variables */
+ unsigned long lineno;/* First line number of commands. */
+ const char *fname; /* File name of commands. */
+ LIST commands; /* Creation commands */
+ LstNode current; /* Current command, for job */
+
+ struct Suff_ *suffix;/* Suffix for the node (determined by
+ * Suff_FindDeps and opaque to everyone
+ * but the Suff module) */
+ char name[1]; /* The target's name */
};
/*
@@ -151,7 +168,7 @@ struct GNode_ {
#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
+#define OP_MAKE 0x00000200 /* Target is a recursive make so its
* commands should always be executed when
* it is out of date, regardless of the
* state of the -n or -t flags */
@@ -166,6 +183,10 @@ struct GNode_ {
* target' processing in parse.c */
#define OP_PHONY 0x00010000 /* Not a file target; run always */
#define OP_NOPATH 0x00020000 /* Don't search for file in the path */
+#define OP_NODEFAULT 0x00040000 /* Special node that never needs */
+ /* DEFAULT commands applied */
+#define OP_DUMMY 0x00080000 /* node was created by default, but it */
+ /* does not really exist. */
/* 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 */
diff --git a/usr.bin/make/init.c b/usr.bin/make/init.c
index 231e3fe968f..21d2c89ae26 100644
--- a/usr.bin/make/init.c
+++ b/usr.bin/make/init.c
@@ -1,5 +1,5 @@
/* $OpenPackages$ */
-/* $OpenBSD: init.c,v 1.3 2006/05/06 10:52:34 espie Exp $ */
+/* $OpenBSD: init.c,v 1.4 2007/09/17 12:42:09 espie Exp $ */
/*
* Copyright (c) 2001 Marc Espie.
@@ -44,6 +44,7 @@ Init(void)
{
Init_Timestamp();
Init_Stats();
+ Targ_Init();
Dir_Init(); /* Initialize directory structures so -I flags
* can be processed correctly */
Parse_Init(); /* Need to initialize the paths of #include
@@ -51,7 +52,6 @@ Init(void)
Var_Init(); /* As well as the lists of variables for
* parsing arguments */
Arch_Init();
- Targ_Init();
Suff_Init();
}
diff --git a/usr.bin/make/job.c b/usr.bin/make/job.c
index 1105768e8bf..e0e2bf91e75 100644
--- a/usr.bin/make/job.c
+++ b/usr.bin/make/job.c
@@ -1,5 +1,5 @@
/* $OpenPackages$ */
-/* $OpenBSD: job.c,v 1.77 2007/09/17 12:03:40 espie Exp $ */
+/* $OpenBSD: job.c,v 1.78 2007/09/17 12:42:09 espie Exp $ */
/* $NetBSD: job.c,v 1.16 1996/11/06 17:59:08 christos Exp $ */
/*
@@ -48,8 +48,6 @@
* frequently to keep the whole make going at
* a decent clip, since job table entries aren't
* removed until their process is caught this way.
- * Its single argument is true if the function
- * should block waiting for a child to terminate.
*
* Job_CatchOutput Print any output our children have produced.
* Should also be called fairly frequently to
@@ -132,11 +130,11 @@
* commands.
* 4) An FILE* for writing out the commands. This is only
* used before the job is actually started.
- * 5) Things used for handling the shell's output.
+ * 5) Things used for handling the shell's output.
* 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.
+ * maintained for each job.
* 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,
@@ -162,17 +160,17 @@ typedef struct Job_ {
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_SPECIAL 0x004 /* Target is a special one. i.e., always run */
+ /* it even when the table is full */
+#define JOB_IGNDOTS 0x008 /* Ignore "..." lines when processing */
+ /* commands */
#define JOB_FIRST 0x020 /* Job is first job for the node */
#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 */
+#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 */
int inPipe; /* Input side of pipe associated
* with job's output channel */
int outPipe; /* Output side of pipe associated with
@@ -183,6 +181,7 @@ typedef struct Job_ {
int curPos; /* Current position in op_outBuf */
} Job;
+
/*
* error handling variables
*/
@@ -198,13 +197,6 @@ static int aborting = 0; /* why is the make aborting? */
*/
#define FILENO(a) ((unsigned) fileno(a))
-/*
- * post-make command processing. The node postCommands is really just the
- * .END target but we keep it around to avoid having to search for it
- * all the time.
- */
-static GNode *postCommands; /* node containing commands to execute when
- * everything else is done */
static int numCommands; /* The number of commands actually printed
* for a target. Should this number be
* 0, no shell will be executed. */
@@ -235,16 +227,11 @@ static char tfile[sizeof(TMPPAT)];
static const char *shellPath = _PATH_BSHELL;
static const char *shellName = "sh";
+
static int maxJobs; /* The most children we can run at once */
-static int maxLocal; /* The most local ones we can have */
static int nJobs = 0; /* The number of children currently running */
-static int nLocal; /* The number of local children */
static LIST jobs; /* The structures that describe them */
-static bool jobFull; /* Flag to tell when the job table is full. It
- * is set true when (1) the total number of
- * running jobs equals the maximum allowed or
- * (2) a job can only be run locally, but
- * nLocal equals maxLocal */
+static bool jobFull; /* Flag to tell when the job table is full. */
static fd_set *outputsp; /* Set of descriptors of pipes connected to
* the output channels of children */
static int outputsn;
@@ -539,7 +526,7 @@ DBPRINTF(Job *job, const char *fmt, ...)
* If the command is just "..." we take all future commands for this
* job to be commands to be executed once the entire graph has been
* made and return non-zero to signal that the end of the commands
- * was reached. These commands are later attached to the postCommands
+ * was reached. These commands are later attached to the end_node
* node and executed by Job_End when all things are done.
* This function is called from JobStart via Lst_Find
*
@@ -555,20 +542,20 @@ DBPRINTF(Job *job, const char *fmt, ...)
*-----------------------------------------------------------------------
*/
static int
-JobPrintCommand(LstNode cmdNode, /* command string to print */
- void *jobp) /* job for which to print it */
+JobPrintCommand(LstNode cmdNode, /* command string to print */
+ void *jobp) /* job for which to print it */
{
- bool noSpecials; /* true if we shouldn't worry about
- * inserting special commands into
- * the input stream. */
- bool shutUp = false; /* true if we put a no echo command
- * into the command file */
- bool errOff = false; /* true if we turned error checking
- * off before printing the command
- * and need to turn it back on */
- char *cmdTemplate; /* Template to use when printing the
- * command */
- char *cmdStart; /* Start of expanded command */
+ bool noSpecials; /* true if we shouldn't worry about
+ * inserting special commands into
+ * the input stream. */
+ bool shutUp = false; /* true if we put a no echo command
+ * into the command file */
+ bool errOff = false; /* true if we turned error checking
+ * off before printing the command
+ * and need to turn it back on */
+ char *cmdTemplate; /* Template to use when printing the
+ * command */
+ char *cmdStart; /* Start of expanded command */
char *cmd = (char *)Lst_Datum(cmdNode);
Job *job = (Job *)jobp;
@@ -583,6 +570,7 @@ JobPrintCommand(LstNode cmdNode, /* command string to print */
return 1;
}
+
numCommands++;
/* For debugging, we replace each command with the result of expanding
@@ -618,13 +606,12 @@ JobPrintCommand(LstNode cmdNode, /* command string to print */
if (errOff) {
if ( !(job->flags & JOB_IGNERR) && !noSpecials) {
/*
- * we don't want the error-control commands
- * showing up either, so we turn off echoing
- * while executing them. We could put another
- * field in the shell structure to tell
- * JobDoOutput to look for this string too, but
- * why make it any more complex than it already
- * is?
+ * we don't want the error-control commands showing
+ * up either, so we turn off echoing while executing
+ * them. We could put another field in the shell
+ * structure to tell JobDoOutput to look for this
+ * string too, but why make it any more complex than
+ * it already is?
*/
if (!(job->flags & JOB_SILENT) && !shutUp) {
DBPRINTF(job, "%s; %s; %s\n", SHELL_ECHO_OFF,
@@ -664,7 +651,7 @@ JobPrintCommand(LstNode cmdNode, /* command string to print */
* Callback function for JobFinish...
*
* Side Effects:
- * The command is tacked onto the end of postCommands's commands list.
+ * The command is tacked onto the end of end_node's commands list.
*-----------------------------------------------------------------------
*/
static void
@@ -674,7 +661,7 @@ JobSaveCommand(void *cmd, void *gn)
char *result;
result = Var_Subst((char *)cmd, &g->context, false);
- Lst_AtEnd(&postCommands->commands, result);
+ Lst_AtEnd(&end_node->commands, result);
}
@@ -710,7 +697,7 @@ JobClose(Job *job)
*
* Side Effects:
* Some nodes may be put on the toBeMade queue.
- * Final commands for the job are placed on postCommands.
+ * Final commands for the job are placed on end_node.
*
* If we got an error and are aborting (aborting == ABORT_ERROR) and
* the job list is now empty, we are done for the day.
@@ -723,7 +710,7 @@ static void
JobFinish(Job *job, /* job to finish */
int *status) /* sub-why job went away */
{
- bool done;
+ bool done;
if ((WIFEXITED(*status) &&
WEXITSTATUS(*status) != 0 && !(job->flags & JOB_IGNERR)) ||
@@ -773,8 +760,8 @@ JobFinish(Job *job, /* job to finish */
if (WIFEXITED(*status)) {
if (DEBUG(JOB)) {
- (void)fprintf(stdout, "Process %ld exited.\n",
- (long)job->pid);
+ (void)fprintf(stdout,
+ "Process %ld exited.\n", (long)job->pid);
(void)fflush(stdout);
}
if (WEXITSTATUS(*status) != 0) {
@@ -800,8 +787,8 @@ JobFinish(Job *job, /* job to finish */
}
} else if (WIFSTOPPED(*status)) {
if (DEBUG(JOB)) {
- (void)fprintf(stdout, "Process %ld stopped.\n",
- (long)job->pid);
+ (void)fprintf(stdout,
+ "Process %ld stopped.\n", (long)job->pid);
(void)fflush(stdout);
}
if (job->node != lastNode) {
@@ -831,7 +818,7 @@ JobFinish(Job *job, /* job to finish */
if (!(job->flags & JOB_CONTINUING)) {
if (DEBUG(JOB)) {
(void)fprintf(stdout,
- "Warning: process %ld was not continuing.\n",
+ "Warning: process %ld was not continuing.\n",
(long)job->pid);
(void)fflush(stdout);
}
@@ -855,7 +842,6 @@ JobFinish(Job *job, /* job to finish */
(long)job->pid);
(void)fflush(stdout);
}
- nLocal++;
if (nJobs == maxJobs) {
jobFull = true;
if (DEBUG(JOB)) {
@@ -964,7 +950,7 @@ JobExec(Job *job, char **argv)
pid_t cpid; /* ID of new child */
if (DEBUG(JOB)) {
- int i;
+ int i;
(void)fprintf(stdout, "Running %s\n", job->node->name);
(void)fprintf(stdout, "\tCommand: ");
@@ -1003,8 +989,8 @@ JobExec(Job *job, char **argv)
(void)lseek(0, 0, SEEK_SET);
/*
- * Set up the child's output to be routed through the
- * pipe we've created for it.
+ * Set up the child's output to be routed through the pipe
+ * we've created for it.
*/
if (dup2(job->outPipe, 1) == -1)
Punt("Cannot dup2: %s", strerror(errno));
@@ -1069,7 +1055,6 @@ JobExec(Job *job, char **argv)
FD_SET(job->inPipe, outputsp);
}
- nLocal++;
/*
* XXX: Used to not happen if REMOTE. Why?
*/
@@ -1111,7 +1096,7 @@ JobMakeArgv(Job *job, char **argv)
if (args[1]) {
argv[argc] = args;
argc++;
- }
+ }
argv[argc] = NULL;
}
@@ -1146,7 +1131,7 @@ JobRestart(Job *job)
job->node->name);
(void)fflush(stdout);
}
- if (nLocal >= maxLocal && !(job->flags & JOB_SPECIAL)) {
+ if (nJobs >= maxJobs && !(job->flags & JOB_SPECIAL)) {
/*
* Can't be exported and not allowed to run locally --
* put it back on the hold queue and mark the table
@@ -1182,13 +1167,10 @@ JobRestart(Job *job)
(void)fprintf(stdout, "Resuming %s...", job->node->name);
(void)fflush(stdout);
}
- if ((nLocal < maxLocal ||
- ((job->flags & JOB_SPECIAL) &&
- maxLocal == 0)
- ) && nJobs != maxJobs) {
+ if (nJobs != maxJobs || (job->flags & JOB_SPECIAL)) {
/*
- * If we haven't reached the concurrency limit already
- * (or maxLocal is 0), it's ok to resume the job.
+ * If we haven't reached the concurrency limit already,
+ * it's ok to resume the job.
*/
bool error;
int status;
@@ -1253,17 +1235,17 @@ JobRestart(Job *job)
*-----------------------------------------------------------------------
*/
static int
-JobStart(GNode *gn, /* target to create */
- int flags, /* flags for the job to override normal ones.
- * e.g. JOB_SPECIAL or JOB_IGNDOTS */
- Job *previous) /* The previous Job structure for this node,
- * if any. */
+JobStart(GNode *gn, /* target to create */
+ int flags, /* flags for the job to override normal ones.
+ * e.g. JOB_SPECIAL or JOB_IGNDOTS */
+ Job *previous) /* The previous Job structure for this node,
+ * if any. */
{
- Job *job; /* new job descriptor */
- char *argv[4]; /* Argument vector to shell */
- bool cmdsOK; /* true if the nodes commands were all right */
- bool local; /* Set true if the job was run locally */
- bool noExec; /* Set true if we decide not to run the job */
+ Job *job; /* new job descriptor */
+ char *argv[4]; /* Argument vector to shell */
+ bool cmdsOK; /* true if the nodes commands were all right */
+ bool local; /* Set true if the job was run locally */
+ bool noExec; /* Set true if we decide not to run the job */
if (previous != NULL) {
previous->flags &= ~(JOB_FIRST|JOB_IGNERR|JOB_SILENT);
@@ -1483,18 +1465,9 @@ JobStart(GNode *gn, /* target to create */
local = true;
- if (local && nLocal >= maxLocal &&
- !(job->flags & JOB_SPECIAL) &&
- maxLocal != 0
- ) {
- /*
- * The job can only be run locally, but we've hit the limit of
- * local concurrency, so put the job on hold until some other
- * job finishes. Note that the special jobs (.BEGIN, .INTERRUPT
- * and .END) may be run locally even when the local limit has
- * been reached (e.g. when maxLocal == 0), though they will be
- * exported if at all possible. In addition, any target marked
- * with .NOEXPORT will be run locally if maxLocal is 0.
+ if (nJobs >= maxJobs && !(job->flags & JOB_SPECIAL)) {
+ /* we've hit the limit of concurrency, so put the job on hold
+ * until some other job finishes.
*/
jobFull = true;
@@ -1504,20 +1477,6 @@ JobStart(GNode *gn, /* target to create */
}
job->flags |= JOB_RESTART;
Lst_AtEnd(&stoppedJobs, job);
- } else {
- if (nLocal >= maxLocal && local) {
- /*
- * If we're running this job locally as a special case
- * (see above), at least say the table is full.
- */
- jobFull = true;
- if (DEBUG(JOB)) {
- (void)fprintf(stdout,
- "Local job queue is full.\n");
- (void)fflush(stdout);
- }
- }
- JobExec(job, argv);
}
return JOB_RUNNING;
}
@@ -1536,11 +1495,10 @@ JobOutput(Job *job, char *cp, char *endp, int msg)
lastNode = job->node;
}
/*
- * The only way there wouldn't be a newline
- * after this line is if it were the last in
- * the buffer. however, since the
- * non-printable comes after it, there must be
- * a newline, so we don't print one.
+ * The only way there wouldn't be a newline after
+ * this line is if it were the last in the buffer.
+ * however, since the non-printable comes after it,
+ * there must be a newline, so we don't print one.
*/
(void)fprintf(stdout, "%s", cp);
(void)fflush(stdout);
@@ -1548,13 +1506,12 @@ JobOutput(Job *job, char *cp, char *endp, int msg)
cp = ecp + strlen(SHELL_ECHO_OFF);
if (cp != endp) {
/*
- * Still more to print, look again after
- * skipping the whitespace following the
- * non-printable command....
+ * Still more to print, look again after skipping
+ * the whitespace following the non-printable
+ * command....
*/
cp++;
- while (*cp == ' ' || *cp == '\t' ||
- *cp == '\n') {
+ while (*cp == ' ' || *cp == '\t' || *cp == '\n') {
cp++;
}
ecp = strstr(cp, SHELL_ECHO_OFF);
@@ -1594,12 +1551,12 @@ JobDoOutput(Job *job, /* the job whose output needs printing */
bool finish) /* true if this is the last time we'll be
* called for this job */
{
- bool gotNL = false; /* true if got a newline */
+ bool gotNL = false; /* true if got a newline */
bool fbuf; /* true if our buffer filled up */
int nr; /* number of bytes read */
int i; /* auxiliary index into outBuf */
- int max; /* limit for i (end of current data) */
- int nRead; /* (Temporary) number of bytes read */
+ int max; /* limit for i (end of current data) */
+ int nRead; /* (Temporary) number of bytes read */
/*
* Read as many bytes as will fit in the buffer.
@@ -1620,10 +1577,10 @@ end_loop:
}
/*
- * If we hit the end-of-file (the job is dead), we must flush
- * its remaining output, so pretend we read a newline if
- * there's any output remaining in the buffer. Also clear the
- * 'finish' flag so we stop looping.
+ * If we hit the end-of-file (the job is dead), we must flush its
+ * remaining output, so pretend we read a newline if there's any
+ * output remaining in the buffer.
+ * Also clear the 'finish' flag so we stop looping.
*/
if (nr == 0 && job->curPos != 0) {
job->outBuf[job->curPos] = '\n';
@@ -1634,9 +1591,9 @@ end_loop:
}
/*
- * Look for the last newline in the bytes we just got. If there
- * is one, break out of the loop with 'i' as its index and
- * gotNL set true.
+ * Look for the last newline in the bytes we just got. If there is
+ * one, break out of the loop with 'i' as its index and gotNL set
+ * true.
*/
max = job->curPos + nr;
for (i = job->curPos + nr - 1; i >= job->curPos; i--) {
@@ -1655,8 +1612,8 @@ end_loop:
job->curPos += nr;
if (job->curPos == JOB_BUFSIZE) {
/*
- * If we've run out of buffer space, we have no
- * choice but to print the stuff. sigh.
+ * If we've run out of buffer space, we have no choice
+ * but to print the stuff. sigh.
*/
fbuf = true;
i = job->curPos;
@@ -1664,28 +1621,26 @@ end_loop:
}
if (gotNL || fbuf) {
/*
- * Need to send the output to the screen. Null
- * terminate it first, overwriting the newline
- * character if there was one. So long as the line
- * isn't one we should filter (according to the shell
- * description), we print the line, preceded by a
- * target banner if this target isn't the same as the
- * one for which we last printed something. The rest
- * of the data in the buffer are then shifted down to
- * the start of the buffer and curPos is set
- * accordingly.
+ * Need to send the output to the screen. Null terminate it
+ * first, overwriting the newline character if there was one.
+ * So long as the line isn't one we should filter (according
+ * to the shell description), we print the line, preceded
+ * by a target banner if this target isn't the same as the
+ * one for which we last printed something.
+ * The rest of the data in the buffer are then shifted down
+ * to the start of the buffer and curPos is set accordingly.
*/
job->outBuf[i] = '\0';
if (i >= job->curPos) {
char *cp;
- cp = JobOutput(job, job->outBuf,
- &job->outBuf[i], false);
+ cp = JobOutput(job, job->outBuf, &job->outBuf[i],
+ false);
/*
- * There's still more in that thar buffer. This
- * time, though, we know there's no newline at
- * the end, so we add one of our own free will.
+ * There's still more in that thar buffer. This time,
+ * though, we know there's no newline at the end, so we
+ * add one of our own free will.
*/
if (*cp != '\0') {
if (job->node != lastNode) {
@@ -1705,21 +1660,20 @@ end_loop:
} else {
/*
- * We have written everything out, so we just
- * start over from the start of the buffer. No
- * copying. No nothing.
+ * We have written everything out, so we just start over
+ * from the start of the buffer. No copying. No nothing.
*/
job->curPos = 0;
}
}
if (finish) {
/*
- * If the finish flag is true, we must loop until we
- * hit end-of-file on the pipe. This is guaranteed to
- * happen eventually since the other end of the pipe is
- * now closed (we closed it explicitly and the child
- * has exited). When we do get an EOF, finish will be
- * set false and we'll fall through and out.
+ * If the finish flag is true, we must loop until we hit
+ * end-of-file on the pipe. This is guaranteed to happen
+ * eventually since the other end of the pipe is now closed
+ * (we closed it explicitly and the child has exited). When
+ * we do get an EOF, finish will be set false and we'll fall
+ * through and out.
*/
goto end_loop;
}
@@ -1743,15 +1697,15 @@ end_loop:
void
Job_CatchChildren()
{
- pid_t pid; /* pid of dead child */
- Job *job; /* job descriptor for dead child */
- LstNode jnode; /* list element for finding job */
- int status; /* Exit/termination status */
+ pid_t pid; /* pid of dead child */
+ Job *job; /* job descriptor for dead child */
+ LstNode jnode; /* list element for finding job */
+ int status; /* Exit/termination status */
/*
* Don't even bother if we know there's no one around.
*/
- if (nLocal == 0) {
+ if (nJobs == 0) {
return;
}
@@ -1790,7 +1744,6 @@ Job_CatchChildren()
(void)fflush(stdout);
}
jobFull = false;
- nLocal--;
}
JobFinish(job, &status);
@@ -1820,7 +1773,6 @@ Job_CatchOutput(void)
int count = howmany(outputsn+1, NFDBITS) * sizeof(fd_mask);
fd_set *readfdsp = malloc(count);
-
(void)fflush(stdout);
if (readfdsp == NULL)
return;
@@ -1874,12 +1826,8 @@ Job_Make(GNode *gn)
*-----------------------------------------------------------------------
*/
void
-Job_Init(int maxproc, /* the greatest number of jobs which may be
- * running at one time */
- int maxlocal) /* the greatest number of local jobs which may
- * be running at once. */
+Job_Init(int maxproc)
{
- GNode *begin; /* node for commands to do at the very start */
int tfd;
(void)strlcpy(tfile, TMPPAT, sizeof(tfile));
@@ -1891,9 +1839,6 @@ Job_Init(int maxproc, /* the greatest number of jobs which may be
Static_Lst_Init(&jobs);
Static_Lst_Init(&stoppedJobs);
maxJobs = maxproc;
- maxLocal = maxlocal;
- nJobs = 0;
- nLocal = 0;
jobFull = false;
aborting = 0;
@@ -1948,16 +1893,13 @@ Job_Init(int maxproc, /* the greatest number of jobs which may be
}
#endif
- begin = Targ_FindNode(".BEGIN", TARG_NOCREATE);
-
- if (begin != NULL) {
- JobStart(begin, JOB_SPECIAL, (Job *)0);
+ if ((begin_node->type & OP_DUMMY) == 0) {
+ JobStart(begin_node, JOB_SPECIAL, (Job *)0);
while (nJobs) {
Job_CatchOutput();
Job_CatchChildren();
}
}
- postCommands = Targ_FindNode(".END", TARG_CREATE);
}
/*-
@@ -2026,8 +1968,7 @@ JobInterrupt(int runINTERRUPT, /* Non-zero if commands for the .INTERRUPT
int signo) /* signal received */
{
LstNode ln; /* element in job table */
- Job *job; /* job descriptor in that element */
- GNode *interrupt; /* the node describing the .INTERRUPT target */
+ Job *job; /* job descriptor in that element */
aborting = ABORT_INTERRUPT;
@@ -2053,11 +1994,10 @@ JobInterrupt(int runINTERRUPT, /* Non-zero if commands for the .INTERRUPT
}
if (runINTERRUPT && !touchFlag) {
- interrupt = Targ_FindNode(".INTERRUPT", TARG_NOCREATE);
- if (interrupt != NULL) {
+ if ((interrupt_node->type & OP_DUMMY) == 0) {
ignoreErrors = false;
- JobStart(interrupt, JOB_IGNDOTS, (Job *)0);
+ JobStart(interrupt_node, JOB_IGNDOTS, (Job *)0);
while (nJobs) {
Job_CatchOutput();
Job_CatchChildren();
@@ -2085,11 +2025,11 @@ JobInterrupt(int runINTERRUPT, /* Non-zero if commands for the .INTERRUPT
int
Job_Finish(void)
{
- if (postCommands != NULL && !Lst_IsEmpty(&postCommands->commands)) {
+ if (end_node != NULL && !Lst_IsEmpty(&end_node->commands)) {
if (errors) {
Error("Errors reported so .END ignored");
} else {
- JobStart(postCommands, JOB_SPECIAL | JOB_IGNDOTS, NULL);
+ JobStart(end_node, JOB_SPECIAL | JOB_IGNDOTS, NULL);
while (nJobs) {
Job_CatchOutput();
@@ -2101,20 +2041,10 @@ Job_Finish(void)
return errors;
}
-/*-
- *-----------------------------------------------------------------------
- * Job_End --
- * Cleanup any memory used by the jobs module
- *
- * Side Effects:
- * Memory is freed
- *-----------------------------------------------------------------------
- */
#ifdef CLEANUP
void
Job_End(void)
{
- efree(shellArgv);
}
#endif
diff --git a/usr.bin/make/job.h b/usr.bin/make/job.h
index aae2fc8f0cd..eeb5e077738 100644
--- a/usr.bin/make/job.h
+++ b/usr.bin/make/job.h
@@ -2,7 +2,7 @@
#define _JOB_H_
/* $OpenPackages$ */
-/* $OpenBSD: job.h,v 1.17 2007/09/17 12:01:16 espie Exp $ */
+/* $OpenBSD: job.h,v 1.18 2007/09/17 12:42:09 espie Exp $ */
/* $NetBSD: job.h,v 1.5 1996/11/06 17:59:10 christos Exp $ */
/*
@@ -49,7 +49,7 @@
extern void Job_CatchChildren(void);
extern void Job_CatchOutput(void);
extern void Job_Make(GNode *);
-extern void Job_Init(int, int);
+extern void Job_Init(int);
extern bool Job_Full(void);
extern bool Job_Empty(void);
extern int Job_Finish(void);
diff --git a/usr.bin/make/main.c b/usr.bin/make/main.c
index c980898a0e4..7453c020ccb 100644
--- a/usr.bin/make/main.c
+++ b/usr.bin/make/main.c
@@ -1,5 +1,5 @@
/* $OpenPackages$ */
-/* $OpenBSD: main.c,v 1.82 2007/09/17 12:01:17 espie Exp $ */
+/* $OpenBSD: main.c,v 1.83 2007/09/17 12:42:09 espie Exp $ */
/* $NetBSD: main.c,v 1.34 1997/03/24 20:56:36 gwr Exp $ */
/*
@@ -75,22 +75,16 @@
# endif
#endif
-#ifndef DEFMAXLOCAL
-#define DEFMAXLOCAL DEFMAXJOBS
-#endif /* DEFMAXLOCAL */
-
#define MAKEFLAGS ".MAKEFLAGS"
static LIST to_create; /* Targets to be made */
Lst create = &to_create;
-GNode *DEFAULT; /* .DEFAULT node */
bool allPrecious; /* .PRECIOUS given on line by itself */
static bool noBuiltins; /* -r flag */
static LIST makefiles; /* ordered list of makefiles to read */
static LIST varstoprint; /* list of variables to print */
int maxJobs; /* -j argument */
-static int maxLocal; /* -L argument */
bool compatMake; /* -B argument */
int debug; /* -d flag */
bool noExecute; /* -n flag */
@@ -301,7 +295,6 @@ MainParseArgs(int argc, char **argv)
optarg);
usage();
}
- maxLocal = maxJobs;
record_option(c, optarg);
break;
}
@@ -677,8 +670,7 @@ main(int argc, char **argv)
touchFlag = false; /* Actually update targets */
debug = 0; /* No debug verbosity, please. */
- maxLocal = DEFMAXLOCAL; /* Set default local max concurrency */
- maxJobs = maxLocal;
+ maxJobs = DEFMAXJOBS; /* Set default local max concurrency */
compatMake = false; /* No compat mode */
@@ -716,8 +708,6 @@ main(int argc, char **argv)
Var_AddCmdline(MAKEFLAGS);
- DEFAULT = NULL;
-
/*
* Set up the .TARGETS variable to contain the list of targets to be
* created. If none specified, make the variable empty -- the parser
@@ -753,9 +743,7 @@ main(int argc, char **argv)
setup_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();
+ process_suffixes_after_makefile_is_read();
/* Print the initial graph, if the user requested it. */
if (DEBUG(GRAPH1))
@@ -792,9 +780,7 @@ main(int argc, char **argv)
* (to prevent the .BEGIN from being executed should
* it exist). */
if (!queryFlag) {
- if (maxLocal == -1)
- maxLocal = maxJobs;
- Job_Init(maxJobs, maxLocal);
+ Job_Init(maxJobs);
}
/* Traverse the graph, checking on all the targets. */
diff --git a/usr.bin/make/main.h b/usr.bin/make/main.h
index 711e84b6806..ce737a921a0 100644
--- a/usr.bin/make/main.h
+++ b/usr.bin/make/main.h
@@ -1,7 +1,7 @@
#ifndef MAIN_H
#define MAIN_H
/* $OpenPackages$ */
-/* $OpenBSD: main.h,v 1.2 2007/09/17 09:28:36 espie Exp $ */
+/* $OpenBSD: main.h,v 1.3 2007/09/17 12:42:09 espie Exp $ */
/*
* Copyright (c) 2001 Marc Espie.
@@ -39,6 +39,4 @@ extern void Main_ParseArgLine(const char *);
* .if make(...) statements. */
extern Lst create;
-extern GNode *DEFAULT; /* .DEFAULT rule */
-
#endif
diff --git a/usr.bin/make/parse.c b/usr.bin/make/parse.c
index 63fdfa2f103..ce248699a7b 100644
--- a/usr.bin/make/parse.c
+++ b/usr.bin/make/parse.c
@@ -1,5 +1,5 @@
/* $OpenPackages$ */
-/* $OpenBSD: parse.c,v 1.91 2007/09/17 11:32:25 espie Exp $ */
+/* $OpenBSD: parse.c,v 1.92 2007/09/17 12:42:09 espie Exp $ */
/* $NetBSD: parse.c,v 1.29 1997/03/10 21:20:04 christos Exp $ */
/*
@@ -91,8 +91,13 @@
#include "parsevar.h"
#include "stats.h"
#include "garray.h"
+#include "node_int.h"
+#include "nodehashconsts.h"
+/* gsources and gtargets should be local to some functions, but they're
+ * set as persistent arrays for performance reasons.
+ */
static struct growableArray gsources, gtargets;
#define SOURCES_SIZE 128
#define TARGETS_SIZE 32
@@ -110,40 +115,13 @@ static GNode *mainNode; /* The main target to create. This is the
* first target on the first dependency
* line in the first makefile */
/*-
- * specType contains the SPECial TYPE of the current target. It is
- * Not if the target is unspecial. If it *is* special, however, the children
- * are linked as children of the parent but not vice versa. This variable is
- * set in ParseDoDependency
+ * specType contains the special TYPE of the current target. It is
+ * SPECIAL_NONE if the target is unspecial. If it *is* special, however,
+ * the children are linked as children of the parent but not vice versa.
+ * This variable is set in ParseDoDependency
*/
-typedef enum {
- Begin, /* .BEGIN */
- Default, /* .DEFAULT */
- End, /* .END */
- Ignore, /* .IGNORE */
- Includes, /* .INCLUDES */
- Interrupt, /* .INTERRUPT */
- Libs, /* .LIBS */
- MFlags, /* .MFLAGS or .MAKEFLAGS */
- Main, /* .MAIN and we don't have anything user-specified to
- * make */
- NoExport, /* .NOEXPORT */
- NoPath, /* .NOPATH */
- Not, /* Not special */
- NotParallel, /* .NOTPARALELL */
- Null, /* .NULL */
- Order, /* .ORDER */
- Parallel, /* .PARALLEL */
- ExPath, /* .PATH */
- Phony, /* .PHONY */
- Precious, /* .PRECIOUS */
- Silent, /* .SILENT */
- SingleShell, /* .SINGLESHELL */
- Suffixes, /* .SUFFIXES */
- Wait, /* .WAIT */
- Attribute /* Generic attribute */
-} ParseSpecial;
-
-static ParseSpecial specType;
+
+static int specType;
static int waiting;
/*
@@ -152,66 +130,18 @@ static int waiting;
*/
static GNode *predecessor;
-/*
- * The parseKeywords table is searched using binary search when deciding
- * if a target or source is special. The 'spec' field is the ParseSpecial
- * type of the keyword ("Not" if the keyword isn't special as a target) while
- * the 'op' field is the operator to apply to the list of targets if the
- * keyword is used as a source ("0" if the keyword isn't special as a source)
- */
-static struct {
- char *name; /* Name of keyword */
- ParseSpecial spec; /* Type when used as a target */
- int op; /* Operator when used as a source */
-} parseKeywords[] = {
-{ ".BEGIN", Begin, 0 },
-{ ".DEFAULT", Default, 0 },
-{ ".END", End, 0 },
-{ ".EXEC", Attribute, OP_EXEC },
-{ ".IGNORE", Ignore, OP_IGNORE },
-{ ".INCLUDES", Includes, 0 },
-{ ".INTERRUPT", Interrupt, 0 },
-{ ".INVISIBLE", Attribute, OP_INVISIBLE },
-{ ".JOIN", Attribute, OP_JOIN },
-{ ".LIBS", Libs, 0 },
-{ ".MADE", Attribute, OP_MADE },
-{ ".MAIN", Main, 0 },
-{ ".MAKE", Attribute, OP_MAKE },
-{ ".MAKEFLAGS", MFlags, 0 },
-{ ".MFLAGS", MFlags, 0 },
-#if 0 /* basic scaffolding for NOPATH, not working yet */
-{ ".NOPATH", NoPath, OP_NOPATH },
-#endif
-{ ".NOTMAIN", Attribute, OP_NOTMAIN },
-{ ".NOTPARALLEL", NotParallel, 0 },
-{ ".NO_PARALLEL", NotParallel, 0 },
-{ ".NULL", Null, 0 },
-{ ".OPTIONAL", Attribute, OP_OPTIONAL },
-{ ".ORDER", Order, 0 },
-{ ".PARALLEL", Parallel, 0 },
-{ ".PATH", ExPath, 0 },
-{ ".PHONY", Phony, OP_PHONY },
-{ ".PRECIOUS", Precious, OP_PRECIOUS },
-{ ".RECURSIVE", Attribute, OP_MAKE },
-{ ".SILENT", Silent, OP_SILENT },
-{ ".SINGLESHELL", SingleShell, 0 },
-{ ".SUFFIXES", Suffixes, 0 },
-{ ".USE", Attribute, OP_USE },
-{ ".WAIT", Wait, 0 },
-};
-
-static int ParseFindKeyword(const char *);
static void ParseLinkSrc(GNode *, GNode *);
-static int ParseDoOp(GNode *, int);
+static int ParseDoOp(GNode **, int);
static int ParseAddDep(GNode *, GNode *);
-static void ParseDoSrc(int, const char *);
+static void ParseDoSrc(struct growableArray *, struct growableArray *, int,
+ const char *, const char *);
static int ParseFindMain(void *, void *);
-static void ParseAddDir(void *, void *);
static void ParseClearPath(void *);
-static void add_target_node(const char *);
-static void add_target_nodes(const char *);
-static void ParseDoDependency(char *);
+static void add_target_node(const char *, const char *);
+static void add_target_nodes(const char *, const char *);
+static void apply_op(struct growableArray *, int, GNode *);
+static void ParseDoDependency(const char *);
static void ParseAddCmd(void *, void *);
static void ParseHasCommands(void *);
static bool handle_poison(const char *);
@@ -227,43 +157,100 @@ static void lookup_sysv_style_include(const char *, const char *, bool);
static void lookup_sysv_include(const char *, const char *);
static void lookup_conditional_include(const char *, const char *);
static bool parse_as_special_line(Buffer, Buffer, const char *);
+
+static const char *parse_do_targets(Lst, int *, const char *);
static void parse_target_line(struct growableArray *, const char *,
const char *);
-/*-
- *----------------------------------------------------------------------
- * ParseFindKeyword --
- * Look in the table of keywords for one matching the given string.
- *
- * Results:
- * The index of the keyword, or -1 if it isn't there.
- *----------------------------------------------------------------------
- */
-static int
-ParseFindKeyword(const char *str) /* keyword to look up */
+static void finish_commands(struct growableArray *);
+static void parse_commands(struct growableArray *, const char *);
+static void create_special_nodes(void);
+static bool found_delimiter(const char *);
+static int handle_special_targets(Lst);
+
+#define SPECIAL_EXEC 4
+#define SPECIAL_IGNORE 5
+#define SPECIAL_INCLUDES 6
+#define SPECIAL_INVISIBLE 8
+#define SPECIAL_JOIN 9
+#define SPECIAL_LIBS 10
+#define SPECIAL_MADE 11
+#define SPECIAL_MAIN 12
+#define SPECIAL_MAKE 13
+#define SPECIAL_MFLAGS 14
+#define SPECIAL_NOTMAIN 15
+#define SPECIAL_NOTPARALLEL 16
+#define SPECIAL_NULL 17
+#define SPECIAL_OPTIONAL 18
+#define SPECIAL_ORDER 19
+#define SPECIAL_PARALLEL 20
+#define SPECIAL_PHONY 22
+#define SPECIAL_PRECIOUS 23
+#define SPECIAL_SILENT 25
+#define SPECIAL_SINGLESHELL 26
+#define SPECIAL_SUFFIXES 27
+#define SPECIAL_USE 28
+#define SPECIAL_WAIT 29
+#define SPECIAL_NOPATH 30
+#define SPECIAL_ERROR 31
+
+
+#define P(k) k, sizeof(k), K_##k
+
+static struct {
+ const char *keyword;
+ size_t sz;
+ uint32_t hv;
+ int type;
+ int special_op;
+} specials[] = {
+ { P(NODE_EXEC), SPECIAL_EXEC | SPECIAL_TARGETSOURCE, OP_EXEC, },
+ { P(NODE_IGNORE), SPECIAL_IGNORE | SPECIAL_TARGETSOURCE, OP_IGNORE, },
+ { P(NODE_INCLUDES), SPECIAL_INCLUDES | SPECIAL_TARGET, 0, },
+ { P(NODE_INVISIBLE),SPECIAL_INVISIBLE | SPECIAL_TARGETSOURCE,OP_INVISIBLE, },
+ { P(NODE_JOIN), SPECIAL_JOIN | SPECIAL_TARGETSOURCE, OP_JOIN, },
+ { P(NODE_LIBS), SPECIAL_LIBS | SPECIAL_TARGET, 0, },
+ { P(NODE_MADE), SPECIAL_MADE | SPECIAL_TARGETSOURCE, OP_MADE, },
+ { P(NODE_MAIN), SPECIAL_MAIN | SPECIAL_TARGET, 0, },
+ { P(NODE_MAKE), SPECIAL_MAKE | SPECIAL_TARGETSOURCE, OP_MAKE, },
+ { P(NODE_MAKEFLAGS), SPECIAL_MFLAGS | SPECIAL_TARGET, 0, },
+ { P(NODE_MFLAGS), SPECIAL_MFLAGS | SPECIAL_TARGET, 0, },
+ { P(NODE_NOTMAIN), SPECIAL_NOTMAIN | SPECIAL_TARGETSOURCE, OP_NOTMAIN, },
+ { P(NODE_NOTPARALLEL),SPECIAL_NOTPARALLEL | SPECIAL_TARGET, 0, },
+ { P(NODE_NO_PARALLEL),SPECIAL_NOTPARALLEL | SPECIAL_TARGET, 0, },
+ { P(NODE_NULL), SPECIAL_NULL | SPECIAL_TARGET, 0, },
+ { P(NODE_OPTIONAL), SPECIAL_OPTIONAL | SPECIAL_TARGETSOURCE,OP_OPTIONAL, },
+ { P(NODE_ORDER), SPECIAL_ORDER | SPECIAL_TARGET, 0, },
+ { P(NODE_PARALLEL), SPECIAL_PARALLEL | SPECIAL_TARGET, 0, },
+ { P(NODE_PATH), SPECIAL_PATH | SPECIAL_TARGET, 0, },
+ { P(NODE_PHONY), SPECIAL_PHONY | SPECIAL_TARGETSOURCE, OP_PHONY, },
+ { P(NODE_PRECIOUS), SPECIAL_PRECIOUS | SPECIAL_TARGETSOURCE,OP_PRECIOUS, },
+ { P(NODE_RECURSIVE),SPECIAL_MAKE | SPECIAL_TARGETSOURCE, OP_MAKE, },
+ { P(NODE_SILENT), SPECIAL_SILENT | SPECIAL_TARGETSOURCE, OP_SILENT, },
+ { P(NODE_SINGLESHELL),SPECIAL_SINGLESHELL | SPECIAL_TARGET, 0, },
+ { P(NODE_SUFFIXES), SPECIAL_SUFFIXES | SPECIAL_TARGET, 0, },
+ { P(NODE_USE), SPECIAL_USE | SPECIAL_TARGETSOURCE, OP_USE, },
+ { P(NODE_WAIT), SPECIAL_WAIT | SPECIAL_TARGETSOURCE, 0 },
+#if 0
+ { P(NODE_NOPATH), SPECIAL_NOPATH, },
+#endif
+};
+
+#undef P
+
+static void
+create_special_nodes()
{
- int start,
- end,
- cur;
- int diff;
-
- start = 0;
- end = (sizeof(parseKeywords)/sizeof(parseKeywords[0])) - 1;
-
- do {
- cur = start + (end - start) / 2;
- diff = strcmp(str, parseKeywords[cur].name);
-
- if (diff == 0) {
- return cur;
- } else if (diff < 0) {
- end = cur - 1;
- } else {
- start = cur + 1;
+ unsigned int i;
+
+ for (i = 0; i < sizeof(specials)/sizeof(specials[0]); i++) {
+ GNode *gn = Targ_FindNodeh(specials[i].keyword,
+ specials[i].sz, specials[i].hv, TARG_CREATE);
+ gn->special = specials[i].type;
+ gn->special_op = specials[i].special_op;
}
- } while (start <= end);
- return -1;
}
+
/*-
*---------------------------------------------------------------------
* ParseLinkSrc --
@@ -282,18 +269,18 @@ ParseLinkSrc(
GNode *pgn, /* The parent node */
GNode *cgn) /* The child node */
{
- if (Lst_AddNew(&pgn->children, cgn)) {
- if (specType == Not)
- Lst_AtEnd(&cgn->parents, pgn);
- pgn->unmade++;
- }
+ if (Lst_AddNew(&pgn->children, cgn)) {
+ if (specType == SPECIAL_NONE)
+ Lst_AtEnd(&cgn->parents, pgn);
+ pgn->unmade++;
+ }
}
/*-
*---------------------------------------------------------------------
* ParseDoOp --
* Apply the parsed operator to the given target node. Used in a
- * Lst_Find call by ParseDoDependency once all targets have
+ * Array_Find call by ParseDoDependency once all targets have
* been found and their operator parsed. If the previous and new
* operators are incompatible, a major error is taken.
*
@@ -304,56 +291,52 @@ ParseLinkSrc(
*/
static int
ParseDoOp(
- GNode *gn, /* The node to which the operator is to be applied */
+ GNode **gnp,
int op) /* The operator to apply */
{
- /*
- * If the dependency mask of the operator and the node don't match and
- * the node has actually had an operator applied to it before, and
- * the operator actually has some dependency information in it, complain.
- */
- if (((op & OP_OPMASK) != (gn->type & OP_OPMASK)) &&
- !OP_NOP(gn->type) && !OP_NOP(op)) {
- Parse_Error(PARSE_FATAL,
- "Inconsistent operator for %s", gn->name);
- return 0;
- }
+ GNode *gn = *gnp;
+ /*
+ * If the dependency mask of the operator and the node don't match and
+ * the node has actually had an operator applied to it before, and
+ * the operator actually has some dependency information in it, complain.
+ */
+ if (((op & OP_OPMASK) != (gn->type & OP_OPMASK)) &&
+ !OP_NOP(gn->type) && !OP_NOP(op)) {
+ Parse_Error(PARSE_FATAL, "Inconsistent operator for %s", gn->name);
+ return 0;
+ }
- if (op == OP_DOUBLEDEP && ((gn->type & OP_OPMASK) == OP_DOUBLEDEP)) {
- /* If the node was the object of a :: operator, we need to
- * create a new instance of it for the children and commands on
- * this dependency line. The new instance is placed on the
- * 'cohorts' list of the initial one (note the initial one is
- * not on its own cohorts list) and the new instance is linked
- * to all parents of the initial instance. */
- GNode *cohort;
- LstNode ln;
- unsigned int i;
-
- cohort = Targ_NewGN(gn->name);
- /* Duplicate links to parents so graph traversal is simple.
- * Perhaps some type bits should be duplicated?
- *
- * Make the cohort invisible as well to avoid duplicating it
- * into other variables. True, parents of this target won't
- * tend to do anything with their local variables, but better
- * safe than sorry. */
- for (ln = Lst_First(&gn->parents); ln != NULL; ln = Lst_Adv(ln))
- ParseLinkSrc((GNode *)Lst_Datum(ln), cohort);
- cohort->type = OP_DOUBLEDEP|OP_INVISIBLE;
- Lst_AtEnd(&gn->cohorts, cohort);
-
- /* Replace the node in the targets list with the new copy */
- for (i = 0; i < gtargets.n; i++)
- if (gtargets.a[i] == gn)
- break;
- gtargets.a[i] = cohort;
- gn = cohort;
- }
- /* We don't want to nuke any previous flags (whatever they were) so we
- * just OR the new operator into the old. */
- gn->type |= op;
- return 1;
+ if (op == OP_DOUBLEDEP && ((gn->type & OP_OPMASK) == OP_DOUBLEDEP)) {
+ /* If the node was the object of a :: operator, we need to create a
+ * new instance of it for the children and commands on this dependency
+ * line. The new instance is placed on the 'cohorts' list of the
+ * initial one (note the initial one is not on its own cohorts list)
+ * and the new instance is linked to all parents of the initial
+ * instance. */
+ GNode *cohort;
+ LstNode ln;
+
+ cohort = Targ_NewGN(gn->name);
+ /* Duplicate links to parents so graph traversal is simple. Perhaps
+ * some type bits should be duplicated?
+ *
+ * Make the cohort invisible as well to avoid duplicating it into
+ * other variables. True, parents of this target won't tend to do
+ * anything with their local variables, but better safe than
+ * sorry. */
+ for (ln = Lst_First(&gn->parents); ln != NULL; ln = Lst_Adv(ln))
+ ParseLinkSrc((GNode *)Lst_Datum(ln), cohort);
+ cohort->type = OP_DOUBLEDEP|OP_INVISIBLE;
+ Lst_AtEnd(&gn->cohorts, cohort);
+
+ /* Replace the node in the targets list with the new copy */
+ *gnp = cohort;
+ gn = cohort;
+ }
+ /* We don't want to nuke any previous flags (whatever they were) so we
+ * just OR the new operator into the old. */
+ gn->type |= op;
+ return 1;
}
/*-
@@ -375,18 +358,26 @@ ParseDoOp(
static int
ParseAddDep(GNode *p, GNode *s)
{
- if (p->order < s->order) {
- /* XXX: This can cause loops, and loops can cause unmade
- * targets, but checking is tedious, and the debugging output
- * can show the problem. */
- Lst_AtEnd(&p->successors, s);
- Lst_AtEnd(&s->preds, p);
- return 1;
- }
- else
- return 0;
+ if (p->order < s->order) {
+ /* XXX: This can cause loops, and loops can cause unmade targets,
+ * but checking is tedious, and the debugging output can show the
+ * problem. */
+ Lst_AtEnd(&p->successors, s);
+ Lst_AtEnd(&s->preds, p);
+ return 1;
+ }
+ else
+ return 0;
}
+static void
+apply_op(struct growableArray *targets, int op, GNode *gn)
+{
+ if (op)
+ gn->type |= op;
+ else
+ Array_ForEach(targets, ParseLinkSrc, gn);
+}
/*-
*---------------------------------------------------------------------
@@ -404,102 +395,77 @@ ParseAddDep(GNode *p, GNode *s)
*/
static void
ParseDoSrc(
+ struct growableArray *targets,
+ struct growableArray *sources,
int tOp, /* operator (if any) from special targets */
- const char *src) /* name of the source to handle */
+ const char *src, /* name of the source to handle */
+ const char *esrc)
{
- GNode *gn = NULL;
-
- if (*src == '.' && isupper(src[1])) {
- int keywd = ParseFindKeyword(src);
- if (keywd != -1) {
- int op = parseKeywords[keywd].op;
- if (op != 0) {
- Array_Find(&gtargets, ParseDoOp, op);
- return;
- }
- if (parseKeywords[keywd].spec == Wait) {
- waiting++;
- return;
- }
+ GNode *gn = Targ_FindNodei(src, esrc, TARG_CREATE);
+ if ((gn->special & SPECIAL_SOURCE) != 0) {
+ if (gn->special_op) {
+ Array_FindP(targets, ParseDoOp, gn->special_op);
+ return;
+ } else {
+ assert((gn->special & SPECIAL_MASK) == SPECIAL_WAIT);
+ waiting++;
+ return;
}
}
switch (specType) {
- case Main:
+ case SPECIAL_MAIN:
/*
* If we have noted the existence of a .MAIN, it means we need
* to add the sources of said target to the list of things
- * to create. The string 'src' is likely to be freed, so we
- * must make a new copy of it. Note that this will only be
- * invoked if the user didn't specify a target on the command
- * line. This is to allow #ifmake's to succeed, or something...
+ * to create. Note that this will only be invoked if the user
+ * didn't specify a target on the command line. This is to
+ * allow #ifmake's to succeed, or something...
*/
- Lst_AtEnd(create, estrdup(src));
+ Lst_AtEnd(create, gn->name);
/*
* Add the name to the .TARGETS variable as well, so the user
* can employ that, if desired.
*/
- Var_Append(".TARGETS", src);
+ Var_Append(".TARGETS", gn->name);
return;
- case Order:
+ case SPECIAL_ORDER:
/*
* Create proper predecessor/successor links between the
* previous source and the current one.
*/
- gn = Targ_FindNode(src, TARG_CREATE);
if (predecessor != NULL) {
Lst_AtEnd(&predecessor->successors, gn);
Lst_AtEnd(&gn->preds, predecessor);
}
- /*
- * The current source now becomes the predecessor for the next
- * one.
- */
predecessor = gn;
break;
default:
/*
- * If the source is not an attribute, we need to find/create
- * a node for it. After that we can apply any operator to it
- * from a special target or link it to its parents, as
- * appropriate.
- *
* In the case of a source that was the object of a :: operator,
* the attribute is applied to all of its instances (as kept in
* the 'cohorts' list of the node) or all the cohorts are linked
* to all the targets.
*/
- gn = Targ_FindNode(src, TARG_CREATE);
- if (tOp) {
- gn->type |= tOp;
- } else {
- Array_ForEach(&gtargets, ParseLinkSrc, gn);
- }
+ apply_op(targets, tOp, gn);
if ((gn->type & OP_OPMASK) == OP_DOUBLEDEP) {
- GNode *cohort;
LstNode ln;
- for (ln=Lst_First(&gn->cohorts); ln != NULL;
+ for (ln=Lst_First(&gn->cohorts); ln != NULL;
ln = Lst_Adv(ln)){
- cohort = (GNode *)Lst_Datum(ln);
- if (tOp) {
- cohort->type |= tOp;
- } else {
- Array_ForEach(&gtargets, ParseLinkSrc,
- cohort);
- }
+ apply_op(targets, tOp,
+ (GNode *)Lst_Datum(ln));
}
}
break;
}
gn->order = waiting;
- Array_AtEnd(&gsources, gn);
- if (waiting) {
- Array_Find(&gsources, ParseAddDep, gn);
- }
+ Array_AtEnd(sources, gn);
+ if (waiting)
+ Array_Find(sources, ParseAddDep, gn);
}
/*-
@@ -513,7 +479,7 @@ ParseDoSrc(
* 1 if main not found yet, 0 if it is.
*
* Side Effects:
- * mainNode is changed and Targ_SetMain is called.
+ * mainNode is changed and.
*-----------------------------------------------------------------------
*/
static int
@@ -521,29 +487,13 @@ ParseFindMain(
void *gnp, /* Node to examine */
void *dummy UNUSED)
{
- GNode *gn = (GNode *)gnp;
- if ((gn->type & OP_NOTARGET) == 0) {
- mainNode = gn;
- Targ_SetMain(gn);
- return 0;
- } else {
- return 1;
- }
-}
-
-/*-
- *-----------------------------------------------------------------------
- * ParseAddDir --
- * Front-end for Dir_AddDir to make sure Lst_ForEach keeps going
- *
- * Side Effects:
- * See Dir_AddDir.
- *-----------------------------------------------------------------------
- */
-static void
-ParseAddDir(void *path, void *name)
-{
- Dir_AddDir((Lst)path, (char *)name);
+ GNode *gn = (GNode *)gnp;
+ if ((gn->type & OP_NOTARGET) == 0 && gn->special == SPECIAL_NONE) {
+ mainNode = gn;
+ return 0;
+ } else {
+ return 1;
+ }
}
/*-
@@ -555,31 +505,33 @@ ParseAddDir(void *path, void *name)
static void
ParseClearPath(void *p)
{
- Lst path = (Lst)p;
+ Lst path = (Lst)p;
- Lst_Destroy(path, Dir_Destroy);
- Lst_Init(path);
+ Lst_Destroy(path, Dir_Destroy);
+ Lst_Init(path);
}
static void
-add_target_node(const char *line)
+add_target_node(const char *line, const char *end)
{
GNode *gn;
- if (!Suff_IsTransform(line))
- gn = Targ_FindNode(line, TARG_CREATE);
- else
- gn = Suff_AddTransform(line);
+ gn = Suff_ParseAsTransform(line, end);
+
+ if (gn == NULL) {
+ gn = Targ_FindNodei(line, end, TARG_CREATE);
+ gn->type &= ~OP_DUMMY;
+ }
if (gn != NULL)
Array_AtEnd(&gtargets, gn);
}
static void
-add_target_nodes(const char *line)
+add_target_nodes(const char *line, const char *end)
{
- if (Dir_HasWildcards(line)) {
+ if (Dir_HasWildcardsi(line, end)) {
/*
* Targets are to be sought only in the current directory,
* so create an empty path for the thing. Note we need to
@@ -592,14 +544,201 @@ add_target_nodes(const char *line)
Lst_Init(&emptyPath);
Lst_Init(&curTargs);
- Dir_Expand(line, &emptyPath, &curTargs);
+ Dir_Expandi(line, end, &emptyPath, &curTargs);
Lst_Destroy(&emptyPath, Dir_Destroy);
while ((targName = (char *)Lst_DeQueue(&curTargs)) != NULL) {
- add_target_node(targName);
+ add_target_node(targName, targName + strlen(targName));
}
Lst_Destroy(&curTargs, NOFREE);
} else {
- add_target_node(line);
+ add_target_node(line, end);
+ }
+}
+
+/* special target line check: a proper delimiter is a ':' or '!', but
+ * we don't want to end a target on such a character if there is a better
+ * match later on.
+ * By "better" I mean one that is followed by whitespace. This allows the
+ * user to have targets like:
+ * fie::fi:fo: fum
+ * where "fie::fi:fo" is the target. In real life this is used for perl5
+ * library man pages where "::" separates an object from its class. Ie:
+ * "File::Spec::Unix".
+ * This behaviour is also consistent with other versions of make.
+ */
+static bool
+found_delimiter(const char *s)
+{
+ if (*s == '!' || *s == ':') {
+ const char *p = s + 1;
+
+ if (*s == ':' && *p == ':')
+ p++;
+
+ /* Found the best match already. */
+ if (isspace(*p) || *p == '\0')
+ return true;
+
+ do {
+ p += strcspn(p, "!:");
+ if (*p == '\0')
+ break;
+ p++;
+ } while (!isspace(*p));
+
+ /* No better match later on... */
+ if (*p == '\0')
+ return true;
+ }
+ return false;
+}
+
+static const char *
+parse_do_targets(Lst paths, int *op, const char *line)
+{
+ const char *cp;
+
+ do {
+ for (cp = line; *cp && !isspace(*cp) && *cp != '(';) {
+ if (*cp == '$')
+ /* Must be a dynamic source (would have been
+ * expanded otherwise), so call the Var module
+ * to parse the puppy so we can safely advance
+ * beyond it...There should be no errors in
+ * this, as they would have been discovered in
+ * the initial Var_Subst and we wouldn't be
+ * here. */
+ Var_ParseSkip(&cp, NULL);
+ else {
+ if (found_delimiter(cp))
+ break;
+ cp++;
+ }
+ }
+
+ if (*cp == '(') {
+ LIST temp;
+ Lst_Init(&temp);
+ /* Archives must be handled specially to make sure the
+ * OP_ARCHV flag is set in their 'type' field, for one
+ * thing, and because things like "archive(file1.o
+ * file2.o file3.o)" are permissible.
+ * Arch_ParseArchive will set 'line' to be the first
+ * non-blank after the archive-spec. It creates/finds
+ * nodes for the members and places them on the given
+ * list, returning true if all went well and false if
+ * there was an error in the specification. On error,
+ * line should remain untouched. */
+ if (!Arch_ParseArchive(&line, &temp, NULL)) {
+ Parse_Error(PARSE_FATAL,
+ "Error in archive specification: \"%s\"",
+ line);
+ return NULL;
+ } else {
+ AppendList2Array(&temp, &gtargets);
+ Lst_Destroy(&temp, NOFREE);
+ cp = line;
+ continue;
+ }
+ }
+ if (*cp == '\0') {
+ /* Ending a dependency line without an operator is a
+ * Bozo no-no */
+ Parse_Error(PARSE_FATAL, "Need an operator");
+ return NULL;
+ }
+ /*
+ * Have word in line. Get or create its nodes and stick it at
+ * the end of the targets list
+ */
+ if (*line != '\0')
+ add_target_nodes(line, cp);
+
+ while (isspace(*cp))
+ cp++;
+ line = cp;
+ } while (*line != '!' && *line != ':' && *line);
+ *op = handle_special_targets(paths);
+ return cp;
+}
+
+static void
+dump_targets()
+{
+ size_t i;
+ for (i = 0; i < gtargets.n; i++)
+ fprintf(stderr, "%s", gtargets.a[i]->name);
+ fprintf(stderr, "\n");
+}
+
+static int
+handle_special_targets(Lst paths)
+{
+ size_t i;
+ int seen_path = 0;
+ int seen_special = 0;
+ int seen_normal = 0;
+ int type;
+
+ for (i = 0; i < gtargets.n; i++) {
+ type = gtargets.a[i]->special;
+ if ((type & SPECIAL_MASK) == SPECIAL_PATH) {
+ seen_path++;
+ Lst_AtEnd(paths, find_suffix_path(gtargets.a[i]));
+ } else if ((type & SPECIAL_TARGET) != 0)
+ seen_special++;
+ else
+ seen_normal++;
+ }
+ if ((seen_path != 0) + (seen_special != 0) + (seen_normal != 0) > 1) {
+ Parse_Error(PARSE_FATAL, "Wrong mix of special targets");
+ dump_targets();
+ specType = SPECIAL_ERROR;
+ return 0;
+ }
+ if (seen_normal != 0) {
+ specType = SPECIAL_NONE;
+ return 0;
+ }
+ else if (seen_path != 0) {
+ specType = SPECIAL_PATH;
+ return 0;
+ } else if (seen_special == 0) {
+ specType = SPECIAL_NONE;
+ return 0;
+ } else if (seen_special != 1) {
+ Parse_Error(PARSE_FATAL, "Mixing special targets is not allowed");
+ dump_targets();
+ return 0;
+ } else if (seen_special == 1) {
+ specType = gtargets.a[0]->special & SPECIAL_MASK;
+ switch (specType) {
+ case SPECIAL_MAIN:
+ if (!Lst_IsEmpty(create)) {
+ specType = SPECIAL_NONE;
+ }
+ break;
+ case SPECIAL_NOTPARALLEL:
+ {
+ extern int maxJobs;
+
+ maxJobs = 1;
+ break;
+ }
+ case SPECIAL_SINGLESHELL:
+ compatMake = 1;
+ break;
+ case SPECIAL_ORDER:
+ predecessor = NULL;
+ break;
+ default:
+ break;
+ }
+ return gtargets.a[0]->special_op;
+ } else {
+ /* we're allowed to have 0 target */
+ specType = SPECIAL_NONE;
+ return 0;
}
}
@@ -635,444 +774,215 @@ add_target_nodes(const char *line)
*---------------------------------------------------------------------
*/
static void
-ParseDoDependency(char *line) /* the line to parse */
+ParseDoDependency(const char *line) /* the line to parse */
{
- char *cp; /* our current position */
- GNode *gn; /* a general purpose temporary node */
- int op; /* the operator on the line */
- char savec; /* a place to save a character */
- LIST paths; /* List of search paths to alter when parsing
- * a list of .PATH targets */
- int tOp; /* operator from special target */
- tOp = 0;
-
- specType = Not;
- waiting = 0;
- Lst_Init(&paths);
-
- Array_Reset(&gsources);
-
- do {
- for (cp = line; *cp && !isspace(*cp) && *cp != '(';)
- if (*cp == '$')
- /* Must be a dynamic source (would have been expanded
- * otherwise), so call the Var module to parse the puppy
- * so we can safely advance beyond it...There should be
- * no errors in this, as they would have been discovered
- * in the initial Var_Subst and we wouldn't be here. */
- Var_ParseSkip(&cp, NULL);
- else {
- /* We don't want to end a word on ':' or '!' if there is a
- * better match later on in the string. By "better" I mean
- * one that is followed by whitespace. This allows the user
- * to have targets like:
- * fie::fi:fo: fum
- * where "fie::fi:fo" is the target. In real life this is used
- * for perl5 library man pages where "::" separates an object
- * from its class. Ie: "File::Spec::Unix". This behaviour
- * is also consistent with other versions of make. */
- if (*cp == '!' || *cp == ':') {
- char *p = cp + 1;
-
- if (*cp == ':' && *p == ':')
- p++;
+ const char *cp; /* our current position */
+ int op; /* the operator on the line */
+ LIST paths; /* List of search paths to alter when parsing
+ * a list of .PATH targets */
+ int tOp; /* operator from special target */
- /* Found the best match already. */
- if (isspace(*p) || *p == '\0')
- break;
- do {
- p += strcspn(p, "!:");
- if (*p == '\0')
- break;
- p++;
- } while (!isspace(*p));
+ waiting = 0;
+ Lst_Init(&paths);
- /* No better match later on... */
- if (*p == '\0')
- break;
+ Array_Reset(&gsources);
+ cp = parse_do_targets(&paths, &tOp, line);
+ if (cp == NULL || specType == SPECIAL_ERROR)
+ return;
+
+ /* Have now parsed all the target names. Must parse the operator next.
+ * The result is left in op . */
+ if (*cp == '!') {
+ op = OP_FORCE;
+ } else if (*cp == ':') {
+ if (cp[1] == ':') {
+ op = OP_DOUBLEDEP;
+ cp++;
+ } else {
+ op = OP_DEPENDS;
}
- cp++;
- }
- if (*cp == '(') {
- LIST temp;
- Lst_Init(&temp);
- /* Archives must be handled specially to make sure the OP_ARCHV
- * flag is set in their 'type' field, for one thing, and because
- * things like "archive(file1.o file2.o file3.o)" are permissible.
- * Arch_ParseArchive will set 'line' to be the first non-blank
- * after the archive-spec. It creates/finds nodes for the members
- * and places them on the given list, returning true if all
- * went well and false if there was an error in the
- * specification. On error, line should remain untouched. */
- if (!Arch_ParseArchive(&line, &temp, NULL)) {
- Parse_Error(PARSE_FATAL,
- "Error in archive specification: \"%s\"", line);
+ } else {
+ Parse_Error(PARSE_FATAL, "Missing dependency operator");
return;
- } else {
- AppendList2Array(&temp, &gtargets);
- Lst_Destroy(&temp, NOFREE);
- continue;
- }
}
- savec = *cp;
- if (*cp == '\0') {
- /* Ending a dependency line without an operator is a Bozo no-no */
- Parse_Error(PARSE_FATAL, "Need an operator");
- return;
- }
- *cp = '\0';
- /* Have a word in line. See if it's a special target and set
- * specType to match it. */
- if (*line == '.' && isupper(line[1])) {
- /* See if the target is a special target that must have it
- * or its sources handled specially. */
- int keywd = ParseFindKeyword(line);
- if (keywd != -1) {
- if (specType == ExPath && parseKeywords[keywd].spec != ExPath) {
- Parse_Error(PARSE_FATAL, "Mismatched special targets");
- return;
- }
+ cp++; /* Advance beyond operator */
- specType = parseKeywords[keywd].spec;
- tOp = parseKeywords[keywd].op;
+ Array_FindP(&gtargets, ParseDoOp, op);
- /*
- * Certain special targets have special semantics:
- * .PATH Have to set the defaultPath
- * variable too
- * .MAIN Its sources are only used if
- * nothing has been specified to
- * create.
- * .DEFAULT Need to create a node to hang
- * commands on, but we don't want
- * it in the graph, nor do we want
- * it to be the Main Target, so we
- * create it, set OP_NOTMAIN and
- * add it to the list, setting
- * DEFAULT to the new node for
- * later use. We claim the node is
- * A transformation rule to make
- * life easier later, when we'll
- * use Make_HandleUse to actually
- * apply the .DEFAULT commands.
- * .PHONY The list of targets
- * .NOPATH Don't search for file in the path
- * .BEGIN
- * .END
- * .INTERRUPT Are not to be considered the
- * main target.
- * .NOTPARALLEL Make only one target at a time.
- * .SINGLESHELL Create a shell for each command.
- * .ORDER Must set initial predecessor to NULL
- */
+ /*
+ * Get to the first source
+ */
+ while (isspace(*cp))
+ cp++;
+ line = cp;
+
+ /*
+ * Several special targets take different actions if present with no
+ * sources:
+ * a .SUFFIXES line with no sources clears out all old suffixes
+ * a .PRECIOUS line makes all targets precious
+ * a .IGNORE line ignores errors for all targets
+ * a .SILENT line creates silence when making all targets
+ * a .PATH removes all directories from the search path(s).
+ */
+ if (!*line) {
switch (specType) {
- case ExPath:
- Lst_AtEnd(&paths, defaultPath);
- break;
- case Main:
- if (!Lst_IsEmpty(create)) {
- specType = Not;
- }
+ case SPECIAL_SUFFIXES:
+ Suff_ClearSuffixes();
break;
- case Begin:
- case End:
- case Interrupt:
- gn = Targ_FindNode(line, TARG_CREATE);
- gn->type |= OP_NOTMAIN;
- Array_AtEnd(&gtargets, gn);
+ case SPECIAL_PRECIOUS:
+ allPrecious = true;
break;
- case Default:
- gn = Targ_NewGN(".DEFAULT");
- gn->type |= OP_NOTMAIN|OP_TRANSFORM;
- Array_AtEnd(&gtargets, gn);
- DEFAULT = gn;
+ case SPECIAL_IGNORE:
+ ignoreErrors = true;
break;
- case NotParallel:
- {
- extern int maxJobs;
-
- maxJobs = 1;
+ case SPECIAL_SILENT:
+ beSilent = true;
break;
- }
- case SingleShell:
- compatMake = 1;
- break;
- case Order:
- predecessor = NULL;
+ case SPECIAL_PATH:
+ Lst_Every(&paths, ParseClearPath);
break;
- default:
+ default:
break;
}
- } else if (strncmp(line, ".PATH", 5) == 0) {
- /*
- * .PATH<suffix> has to be handled specially.
- * Call on the suffix module to give us a path to
- * modify.
- */
- Lst path;
-
- specType = ExPath;
- path = Suff_GetPath(&line[5]);
- if (path == NULL) {
- Parse_Error(PARSE_FATAL,
- "Suffix '%s' not defined (yet)",
- &line[5]);
- return;
- } else {
- Lst_AtEnd(&paths, path);
- }
- }
+ } else if (specType == SPECIAL_MFLAGS) {
+ /*Call on functions in main.c to deal with these arguments */
+ Main_ParseArgLine(line);
+ return;
+ } else if (specType == SPECIAL_NOTPARALLEL ||
+ specType == SPECIAL_SINGLESHELL) {
+ return;
}
/*
- * Have word in line. Get or create its node and stick it at
- * the end of the targets list
+ * NOW GO FOR THE SOURCES
*/
- if (specType == Not && *line != '\0') {
- add_target_nodes(line);
- } else if (specType == ExPath && *line != '.' && *line != '\0')
- Parse_Error(PARSE_WARNING, "Extra target (%s) ignored", line);
-
- *cp = savec;
- /*
- * If it is a special type and not .PATH, it's the only target we
- * allow on this line...
- */
- if (specType != Not && specType != ExPath) {
- bool warn = false;
+ if (specType == SPECIAL_SUFFIXES || specType == SPECIAL_PATH ||
+ specType == SPECIAL_INCLUDES || specType == SPECIAL_LIBS ||
+ specType == SPECIAL_NULL) {
+ while (*line) {
+ /*
+ * If the target was one that doesn't take files as its
+ * sources but takes something like suffixes, we take each
+ * space-separated word on the line as a something and deal
+ * with it accordingly.
+ *
+ * If the target was .SUFFIXES, we take each source as a
+ * suffix and add it to the list of suffixes maintained by
+ * the Suff module.
+ *
+ * If the target was a .PATH, we add the source as a
+ * directory to search on the search path.
+ *
+ * If it was .INCLUDES, the source is taken to be the
+ * suffix of files which will be #included and whose search
+ * path should be present in the .INCLUDES variable.
+ *
+ * If it was .LIBS, the source is taken to be the suffix of
+ * files which are considered libraries and whose search
+ * path should be present in the .LIBS variable.
+ *
+ * If it was .NULL, the source is the suffix to use when a
+ * file has no valid suffix.
+ */
+ while (*cp && !isspace(*cp))
+ cp++;
+ switch (specType) {
+ case SPECIAL_SUFFIXES:
+ Suff_AddSuffixi(line, cp);
+ break;
+ case SPECIAL_PATH:
+ {
+ LstNode ln;
- while (*cp != '!' && *cp != ':' && *cp) {
- if (*cp != ' ' && *cp != '\t') {
- warn = true;
+ for (ln = Lst_First(&paths); ln != NULL;
+ ln = Lst_Adv(ln))
+ Dir_AddDiri((Lst)Lst_Datum(ln), line, cp);
+ break;
+ }
+ case SPECIAL_INCLUDES:
+ Suff_AddIncludei(line, cp);
+ break;
+ case SPECIAL_LIBS:
+ Suff_AddLibi(line, cp);
+ break;
+ case SPECIAL_NULL:
+ Suff_SetNulli(line, cp);
+ break;
+ default:
+ break;
+ }
+ if (*cp != '\0')
+ cp++;
+ while (isspace(*cp))
+ cp++;
+ line = cp;
}
- cp++;
- }
- if (warn) {
- Parse_Error(PARSE_WARNING, "Extra target ignored");
- }
- } else {
- while (isspace(*cp)) {
- cp++;
- }
- }
- line = cp;
- } while (*line != '!' && *line != ':' && *line);
-
- if (!Array_IsEmpty(&gtargets)) {
- switch (specType) {
- default:
- Parse_Error(PARSE_WARNING, "Special and mundane targets don't mix. Mundane ones ignored");
- break;
- case Default:
- case Begin:
- case End:
- case Interrupt:
- /* These four create nodes on which to hang commands, so
- * targets shouldn't be empty... */
- case Not:
- /* Nothing special here -- targets can be empty if it wants. */
- break;
- }
- }
-
- /* Have now parsed all the target names. Must parse the operator next. The
- * result is left in op . */
- if (*cp == '!') {
- op = OP_FORCE;
- } else if (*cp == ':') {
- if (cp[1] == ':') {
- op = OP_DOUBLEDEP;
- cp++;
+ Lst_Destroy(&paths, NOFREE);
} else {
- op = OP_DEPENDS;
- }
- } else {
- Parse_Error(PARSE_FATAL, "Missing dependency operator");
- return;
- }
-
- cp++; /* Advance beyond operator */
+ while (*line) {
+ /*
+ * The targets take real sources, so we must beware of
+ * archive specifications (i.e. things with left
+ * parentheses in them) and handle them accordingly.
+ */
+ while (*cp && !isspace(*cp)) {
+ if (*cp == '(' && cp > line && cp[-1] != '$') {
+ /*
+ * Only stop for a left parenthesis if
+ * it isn't at the start of a word
+ * (that'll be for variable changes
+ * later) and isn't preceded by a
+ * dollar sign (a dynamic source).
+ */
+ break;
+ } else {
+ cp++;
+ }
+ }
- Array_Find(&gtargets, ParseDoOp, op);
+ if (*cp == '(') {
+ GNode *gn;
+ LIST sources; /* list of archive source
+ * names after expansion */
- /*
- * Get to the first source
- */
- while (isspace(*cp)) {
- cp++;
- }
- line = cp;
-
- /*
- * Several special targets take different actions if present with no
- * sources:
- * a .SUFFIXES line with no sources clears out all old suffixes
- * a .PRECIOUS line makes all targets precious
- * a .IGNORE line ignores errors for all targets
- * a .SILENT line creates silence when making all targets
- * a .PATH removes all directories from the search path(s).
- */
- if (!*line) {
- switch (specType) {
- case Suffixes:
- Suff_ClearSuffixes();
- break;
- case Precious:
- allPrecious = true;
- break;
- case Ignore:
- ignoreErrors = true;
- break;
- case Silent:
- beSilent = true;
- break;
- case ExPath:
- Lst_Every(&paths, ParseClearPath);
- break;
- default:
- break;
- }
- } else if (specType == MFlags) {
- /*
- * Call on functions in main.c to deal with these arguments and
- * set the initial character to a null-character so the loop to
- * get sources won't get anything
- */
- Main_ParseArgLine(line);
- *line = '\0';
- } else if (specType == NotParallel || specType == SingleShell) {
- *line = '\0';
- }
+ Lst_Init(&sources);
+ if (!Arch_ParseArchive(&line, &sources, NULL)) {
+ Parse_Error(PARSE_FATAL,
+ "Error in source archive spec \"%s\"",
+ line);
+ return;
+ }
- /*
- * NOW GO FOR THE SOURCES
- */
- if (specType == Suffixes || specType == ExPath ||
- specType == Includes || specType == Libs ||
- specType == Null) {
- while (*line) {
- /*
- * If the target was one that doesn't take files as its sources
- * but takes something like suffixes, we take each
- * space-separated word on the line as a something and deal
- * with it accordingly.
- *
- * If the target was .SUFFIXES, we take each source as a
- * suffix and add it to the list of suffixes maintained by the
- * Suff module.
- *
- * If the target was a .PATH, we add the source as a directory
- * to search on the search path.
- *
- * If it was .INCLUDES, the source is taken to be the suffix of
- * files which will be #included and whose search path should
- * be present in the .INCLUDES variable.
- *
- * If it was .LIBS, the source is taken to be the suffix of
- * files which are considered libraries and whose search path
- * should be present in the .LIBS variable.
- *
- * If it was .NULL, the source is the suffix to use when a file
- * has no valid suffix.
- */
- char savec;
- while (*cp && !isspace(*cp)) {
- cp++;
- }
- savec = *cp;
- *cp = '\0';
- switch (specType) {
- case Suffixes:
- Suff_AddSuffix(line);
- break;
- case ExPath:
- Lst_ForEach(&paths, ParseAddDir, line);
- break;
- case Includes:
- Suff_AddInclude(line);
- break;
- case Libs:
- Suff_AddLib(line);
- break;
- case Null:
- Suff_SetNull(line);
- break;
- default:
- break;
- }
- *cp = savec;
- if (savec != '\0') {
- cp++;
- }
- while (isspace(*cp)) {
- cp++;
- }
- line = cp;
- }
- Lst_Destroy(&paths, NOFREE);
- } else {
- while (*line) {
- /*
- * The targets take real sources, so we must beware of archive
- * specifications (i.e. things with left parentheses in them)
- * and handle them accordingly.
- */
- while (*cp && !isspace(*cp)) {
- if (*cp == '(' && cp > line && cp[-1] != '$') {
- /*
- * Only stop for a left parenthesis if it isn't at the
- * start of a word (that'll be for variable changes
- * later) and isn't preceded by a dollar sign (a dynamic
- * source).
- */
- break;
- } else {
- cp++;
- }
- }
-
- if (*cp == '(') {
- GNode *gn;
- LIST sources; /* list of archive source names after
- * expansion */
-
- Lst_Init(&sources);
- if (!Arch_ParseArchive(&line, &sources, NULL)) {
- Parse_Error(PARSE_FATAL,
- "Error in source archive spec \"%s\"", line);
- return;
- }
+ while ((gn = (GNode *)Lst_DeQueue(&sources)) !=
+ NULL)
+ ParseDoSrc(&gtargets, &gsources, tOp,
+ gn->name, NULL);
+ cp = line;
+ } else {
+ const char *endSrc = cp;
- while ((gn = (GNode *)Lst_DeQueue(&sources)) != NULL)
- ParseDoSrc(tOp, gn->name);
- cp = line;
- } else {
- if (*cp) {
- *cp = '\0';
- cp++;
+ ParseDoSrc(&gtargets, &gsources, tOp, line,
+ endSrc);
+ if (*cp)
+ cp++;
+ }
+ while (isspace(*cp))
+ cp++;
+ line = cp;
}
-
- ParseDoSrc(tOp, line);
- }
- while (isspace(*cp)) {
- cp++;
- }
- line = cp;
}
- }
-
- if (mainNode == NULL) {
- /* If we have yet to decide on a main target to make, in the
- * absence of any user input, we want the first target on
- * the first dependency line that is actually a real target
- * (i.e. isn't a .USE or .EXEC rule) to be made. */
- Array_Find(&gtargets, ParseFindMain, NULL);
- }
- /* Finally, destroy the list of sources. */
+ if (mainNode == NULL) {
+ /* If we have yet to decide on a main target to make, in the
+ * absence of any user input, we want the first target on
+ * the first dependency line that is actually a real target
+ * (i.e. isn't a .USE or .EXEC rule) to be made. */
+ Array_Find(&gtargets, ParseFindMain, NULL);
+ }
}
/*-
@@ -1114,13 +1024,11 @@ static void
ParseHasCommands(void *gnp) /* Node to examine */
{
GNode *gn = (GNode *)gnp;
- if (!Lst_IsEmpty(&gn->commands)) {
+ if (!Lst_IsEmpty(&gn->commands))
gn->type |= OP_HAS_COMMANDS;
- }
}
-
/* Strip comments from line. Build a copy in buffer if necessary, */
static char *
strip_comments(Buffer copy, const char *line)
@@ -1399,6 +1307,7 @@ handle_poison(const char *line)
}
}
+
static bool
handle_for_loop(Buffer linebuf, const char *line)
{
@@ -1436,6 +1345,7 @@ handle_undef(const char *line)
return true;
}
+/* global hub for the construct */
static bool
handle_bsd_command(Buffer linebuf, Buffer copy, const char *line)
{
@@ -1481,7 +1391,6 @@ handle_bsd_command(Buffer linebuf, Buffer copy, const char *line)
static void
finish_commands(struct growableArray *targets)
{
- Array_Every(targets, Suff_EndTransform);
Array_Every(targets, ParseHasCommands);
Array_Reset(targets);
}
@@ -1632,8 +1541,9 @@ Parse_Init(void)
mainNode = NULL;
Static_Lst_Init(userIncludePath);
Static_Lst_Init(systemIncludePath);
- Array_Init(&gsources, SOURCES_SIZE);
Array_Init(&gtargets, TARGETS_SIZE);
+ Array_Init(&gsources, SOURCES_SIZE);
+ create_special_nodes();
LowParse_Init();
#ifdef CLEANUP
@@ -1657,14 +1567,14 @@ void
Parse_MainName(Lst listmain) /* result list */
{
- if (mainNode == NULL) {
- Punt("no target to make.");
- /*NOTREACHED*/
- } else if (mainNode->type & OP_DOUBLEDEP) {
- Lst_AtEnd(listmain, mainNode);
- Lst_Concat(listmain, &mainNode->cohorts);
- }
- else
- Lst_AtEnd(listmain, mainNode);
+ if (mainNode == NULL) {
+ Punt("no target to make.");
+ /*NOTREACHED*/
+ } else if (mainNode->type & OP_DOUBLEDEP) {
+ Lst_AtEnd(listmain, mainNode);
+ Lst_Concat(listmain, &mainNode->cohorts);
+ }
+ else
+ Lst_AtEnd(listmain, mainNode);
}
diff --git a/usr.bin/make/suff.c b/usr.bin/make/suff.c
index c362329ee11..45aface4c09 100644
--- a/usr.bin/make/suff.c
+++ b/usr.bin/make/suff.c
@@ -1,5 +1,5 @@
/* $OpenPackages$ */
-/* $OpenBSD: suff.c,v 1.69 2007/09/17 11:43:12 espie Exp $ */
+/* $OpenBSD: suff.c,v 1.70 2007/09/17 12:42:09 espie Exp $ */
/* $NetBSD: suff.c,v 1.13 1996/11/06 17:59:25 christos Exp $ */
/*
@@ -46,25 +46,9 @@
*
* Suff_End Cleanup the module
*
- * Suff_DoPaths This function is used to make life easier
- * when searching for a file according to its
- * suffix. It takes the global search path,
- * as defined using the .PATH: target, and appends
- * its directories to the path of each of the
- * defined suffixes, as specified using
- * .PATH<suffix>: targets. In addition, all
- * directories given for suffixes labeled as
- * include files or libraries, using the .INCLUDES
- * or .LIBS targets, are played with using
- * Dir_MakeFlags to create the .INCLUDES and
- * .LIBS global variables.
- *
* Suff_ClearSuffixes Clear out all the suffixes and defined
* transformations.
*
- * Suff_IsTransform Return true if the passed string is the lhs
- * of a transformation rule.
- *
* Suff_AddSuffix Add the passed string as another known suffix.
*
* Suff_GetPath Return the search path for the given suffix.
@@ -74,9 +58,11 @@
*
* Suff_AddLib Mark the given suffix as denoting a library.
*
- * Suff_AddTransform Add another transformation to the suffix
- * graph. Returns GNode suitable for framing, I
- * mean, tacking commands, attributes, etc. on.
+ * Suff_ParseAsTransform Line might be a suffix line, check it.
+ * If it's not, return NULL. Otherwise, add
+ * another transformation to the suffix graph.
+ * Returns GNode suitable for framing, I mean,
+ * tacking commands, attributes, etc. on.
*
* Suff_SetNull Define the suffix to consider the suffix of
* any file that doesn't have a known one.
@@ -87,14 +73,40 @@
* if the target had no implicit sources.
*/
+/* The suffix specifications are *really weird*
+ * Here is how it works:
+ * - each time you encounter a .SUFFIX: .s1 .s2 .s3
+ * you add the suffixes to the list of known suffixes, keeping it ordered.
+ * - when you see a
+ * .s1.s2:
+ * line, you match it against the known suffixes at this point, and it
+ * is tagged as a transform rule.
+ * - when you encounter a .SUFFIX:
+ * you reset the list of suffixes to empty, but you keep all the transforms
+ * around.
+ * - at the end of all Makefiles, you match recognized transforms against
+ * suffixes existing at this point.
+ *
+ * The description of SusV3 is really sketchy, but this is how make works,
+ * gmake works that way as well.
+ *
+ * The only difference is that gmake keeps its transform rules on the main
+ * target list, so if you define two suffixes and a transform, then resets
+ * the suffix and define a normal rule with the same name, you'll override
+ * the transform.
+ */
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
+#include <stdint.h>
+#include <stddef.h>
#include <string.h>
+#include <ohash.h>
#include "config.h"
#include "defines.h"
#include "dir.h"
#include "direxpand.h"
+#include "engine.h"
#include "arch.h"
#include "suff.h"
#include "var.h"
@@ -104,15 +116,13 @@
#include "lst.h"
#include "memory.h"
#include "gnode.h"
+#include "make.h"
#include "stats.h"
-#include "engine.h"
-static LIST sufflist; /* Lst of suffixes */
-#ifdef CLEANUP
-static LIST suffClean; /* Lst of suffixes to be cleaned */
-#endif
+static struct ohash suffixes; /* hash of suffixes */
+size_t maxLen; /* optimization: remember longest suffix */
static LIST srclist; /* Lst of sources */
-static LIST transforms; /* Lst of transformation rules */
+static struct ohash transforms;
static int sNum = 0; /* Counter for assigning suffix numbers */
@@ -120,33 +130,38 @@ static int sNum = 0; /* Counter for assigning suffix numbers */
* Structure describing an individual suffix.
*/
typedef struct Suff_ {
- char *name; /* The suffix itself */
- int nameLen; /* Length of the suffix */
- short flags; /* Type of suffix */
-#define SUFF_INCLUDE 0x01 /* One which is #include'd */
-#define SUFF_LIBRARY 0x02 /* One which contains a library */
-#define SUFF_NULL 0x04 /* The empty suffix */
- LIST searchPath; /* The path along which files of this suffix
- * may be found */
- int sNum; /* The suffix number */
- LIST parents; /* Suffixes we have a transformation to */
- LIST children; /* Suffixes we have a transformation from */
- LIST ref; /* List of lists this suffix is referenced */
+ size_t nameLen; /* Length of the suffix */
+ short flags; /* Type of suffix */
+#define SUFF_INCLUDE 0x01 /* One which is #include'd */
+#define SUFF_LIBRARY 0x02 /* One which contains a library */
+#define SUFF_NULL 0x04 /* The empty suffix */
+#define SUFF_EXISTS 0x08 /* So that we don't have to destroy them */
+#define SUFF_PATH 0x10 /* False suffix: actually, the path keyword */
+ LIST searchPath; /* The path along which files of this suffix
+ * may be found */
+ int sNum; /* The suffix number */
+ LIST parents; /* Suffixes we have a transformation to */
+ LIST children; /* Suffixes we have a transformation from */
+ char name[1]; /* The suffix itself */
} Suff;
+static struct ohash_info suff_info = {
+ offsetof(struct Suff_, name), NULL, hash_alloc, hash_free, element_alloc
+};
+
/*
* Structure used in the search for implied sources.
*/
typedef struct Src_ {
- char *file; /* The file to look for */
- char *pref; /* Prefix from which file was formed */
- Suff *suff; /* The suffix on the file */
- struct Src_ *parent; /* The Src for which this is a source */
- GNode *node; /* The node describing the file */
- int children; /* Count of existing children (so we don't free
+ char *file; /* The file to look for */
+ char *pref; /* Prefix from which file was formed */
+ Suff *suff; /* The suffix on the file */
+ struct Src_ *parent; /* The Src for which this is a source */
+ GNode *node; /* The node describing the file */
+ int children; /* Count of existing children (so we don't free
* this thing too early or never nuke it) */
#ifdef DEBUG_SRC
- LIST cp; /* Debug; children list */
+ LIST cp; /* Debug; children list */
#endif
} Src;
@@ -155,28 +170,34 @@ typedef struct Src_ {
* function...
*/
typedef struct {
- Lst l;
- Src *s;
+ Lst l;
+ Src *s;
} LstSrc;
-static Suff *suffNull; /* The NULL suffix for this run */
-static Suff *emptySuff; /* The empty suffix required for POSIX
- * single-suffix transformation rules */
+static Suff *suffNull; /* The NULL suffix for this run */
+static Suff *emptySuff; /* The empty suffix required for POSIX
+ * single-suffix transformation rules */
+
+
+static void build_path_variable(struct ohash *, int, const char *, const char *);
+static void add_property(const char *, const char *, int);
+#define parse_transform(s, p, q) parse_transformi(s, s + strlen(s), p, q)
+static bool parse_transformi(const char *, const char *, Suff **, Suff **);
+#define new_suffix(s) new_suffixi(s, NULL)
+static Suff *new_suffixi(const char *, const char *);
+static void reverse_hash_add_char(uint32_t *, const char *);
+static uint32_t reverse_hashi(const char *, const char **);
+static unsigned int reverse_slot(struct ohash *, const char *, const char **);
+static void clear_suffixes(void);
+static void record_possible_suffix(Suff *, GNode *, char *, Lst, Lst);
+static void record_possible_suffixes(GNode *, Lst, Lst);
+static Suff *find_suffix_as_suffix(Lst, const char *, const char *);
+static Suff *add_suffixi(const char *, const char *);
-
-static char *SuffStrIsPrefix(const char *, const char *);
-static char *SuffSuffIsSuffix(Suff *, const char *);
-static int SuffSuffIsSuffixP(void *, const void *);
-static int SuffSuffIsPrefix(void *, const void *);
-static int SuffHasNameP(void *, const void *);
-static int GNodeHasNameP(void *, const void *);
-static void SuffUnRef(Lst, Suff *);
#ifdef CLEANUP
static void SuffFree(void *);
#endif
static void SuffInsert(Lst, Suff *);
-static bool SuffParseTransform(const char *, Suff **, Suff **);
-static void SuffRebuildGraph(void *, void *);
static void SuffAddSrc(void *, void *);
static int SuffRemoveSrc(Lst);
static void SuffAddLevel(Lst, Src *);
@@ -191,54 +212,71 @@ static void SuffFindArchiveDeps(GNode *, Lst);
static void SuffFindNormalDeps(GNode *, Lst);
static void SuffPrintName(void *);
static void SuffPrintSuff(void *);
-static void SuffPrintTrans(void *);
+static void SuffPrintTrans(GNode *);
-static LstNode suff_find_by_name(const char *);
-static LstNode transform_find_by_name(const char *);
+#define find_suff(name) find_suffi(name, NULL)
+static Suff *find_suffi(const char *, const char *);
+static Suff *find_best_suffix(const char *, const char *);
+static GNode *find_transform(const char *);
+static GNode *find_or_create_transformi(const char *, const char *);
+static void setup_paths(void);
+static void build_suffixes_graph(void);
+static void special_path_hack(void);
#ifdef DEBUG_SRC
static void PrintAddr(void *);
#endif
- /*************** Lst Predicates ****************/
-/*-
- *-----------------------------------------------------------------------
- * SuffStrIsPrefix --
- * See if prefix is a prefix of str.
- *
- * Results:
- * NULL if it ain't, pointer to character in str after prefix if so
- *-----------------------------------------------------------------------
+
+/* we usually look at suffixes `backwards', which makes it necessary for
+ * us to have a specific hash function that proceeds backwards.
*/
-static char *
-SuffStrIsPrefix(const char *prefix, const char *str)
+
+
+static void
+reverse_hash_add_char(uint32_t *pk, const char *s)
{
- while (*str && *prefix == *str) {
- prefix++;
- str++;
+ *pk = ((*pk << 2) | (*pk >> 30)) ^ *s;
+}
+
+static uint32_t
+reverse_hashi(const char *s, const char **e)
+{
+ const char *p;
+ uint32_t k;
+
+ if (*e == NULL)
+ *e = s + strlen(s);
+ p = *e;
+ if (p == s)
+ k = 0;
+ else
+ k = *--p;
+ while (p != s) {
+ reverse_hash_add_char(&k, --p);
}
+ return k;
+}
- return *prefix ? NULL : (char *)str;
+static unsigned int
+reverse_slot(struct ohash *h, const char *s, const char **e)
+{
+ uint32_t hv;
+
+ hv = reverse_hashi(s, e);
+ return ohash_lookup_interval(h, s, *e, hv);
}
-/*-
- *-----------------------------------------------------------------------
- * SuffSuffIsSuffix --
- * See if suff is a suffix of str. str should point to the end of the
- * string to check.
- *
- * Results:
- * NULL if it ain't, pointer to first character of suffix in str if
- * it is.
- *-----------------------------------------------------------------------
- */
+
static char *
-SuffSuffIsSuffix(Suff *s, const char *str)
+suffix_is_suffix(Suff *s, const char *str, const char *estr)
{
- const char *p1; /* Pointer into suffix name */
- const char *p2; /* Pointer into string being examined */
+ const char *p1; /* Pointer into suffix name */
+ const char *p2; /* Pointer into string being examined */
+ if (estr - str < (ptrdiff_t) s->nameLen)
+ return NULL;
p1 = s->name + s->nameLen;
- p2 = str;
+ p2 = estr;
while (p1 != s->name) {
p1--;
@@ -250,79 +288,49 @@ SuffSuffIsSuffix(Suff *s, const char *str)
return (char *)p2;
}
-/*-
- *-----------------------------------------------------------------------
- * SuffSuffIsSuffixP --
- * Predicate form of SuffSuffIsSuffix. Passed as the callback function
- * to Lst_Find.
- *
- * Results:
- * 0 if the suffix is the one desired, non-zero if not.
- *-----------------------------------------------------------------------
- */
-static int
-SuffSuffIsSuffixP(void *s, const void *str)
+static Suff *
+find_suffi(const char *name, const char *ename)
{
- return !SuffSuffIsSuffix((Suff *)s, (const char *)str);
+ unsigned int slot;
+#ifdef STATS_SUFF
+ STAT_SUFF_LOOKUP_NAME++;
+#endif
+ slot = reverse_slot(&suffixes, name, &ename);
+ return ohash_find(&suffixes, slot);
}
-static int
-SuffHasNameP(void *s, const void *sname)
+static GNode *
+find_transform(const char *name)
{
- return strcmp((const char *)sname, ((Suff *)s)->name);
-}
+ unsigned int slot;
-static LstNode
-suff_find_by_name(const char *name)
-{
#ifdef STATS_SUFF
- STAT_SUFF_LOOKUP_NAME++;
+ STAT_TRANSFORM_LOOKUP_NAME++;
#endif
- return Lst_FindConst(&sufflist, SuffHasNameP, name);
-}
+ slot = ohash_qlookup(&transforms, name);
-static int
-GNodeHasNameP(void *gn, const void *name)
-{
- return strcmp((const char *)name, ((GNode *)gn)->name);
+ return ohash_find(&transforms, slot);
}
-static LstNode
-transform_find_by_name(const char *name)
+static GNode *
+find_or_create_transformi(const char *name, const char *end)
{
+ GNode *r;
+ unsigned int slot;
+
#ifdef STATS_SUFF
STAT_TRANSFORM_LOOKUP_NAME++;
#endif
- return Lst_FindConst(&transforms, GNodeHasNameP, name);
-}
-/*-
- *-----------------------------------------------------------------------
- * SuffSuffIsPrefix --
- * See if the suffix described by s is a prefix of the string. Care
- * must be taken when using this to search for transformations and
- * what-not, since there could well be two suffixes, one of which
- * is a prefix of the other...
- *
- * Results:
- * 0 if s is a prefix of str. non-zero otherwise
- *-----------------------------------------------------------------------
- */
-static int
-SuffSuffIsPrefix(void *s, const void *str)
-{
- return SuffStrIsPrefix(((Suff *)s)->name,
- (const char *)str) == NULL ? 1 : 0;
-}
+ slot = ohash_qlookupi(&transforms, name, &end);
- /*********** Maintenance Functions ************/
+ r = ohash_find(&transforms, slot);
-static void
-SuffUnRef(Lst l, Suff *sp)
-{
- LstNode ln = Lst_Member(l, sp);
- if (ln != NULL)
- Lst_Remove(l, ln);
- }
+ if (r == NULL) {
+ r = Targ_NewGNi(name, end);
+ ohash_insert(&transforms, slot, r);
+ }
+ return r;
+}
#ifdef CLEANUP
/*-
@@ -337,15 +345,11 @@ SuffUnRef(Lst l, Suff *sp)
static void
SuffFree(void *sp)
{
- Suff *s = (Suff *)sp;
-
- if (s == suffNull)
- suffNull = NULL;
+ Suff *s = (Suff *)sp;
if (s == emptySuff)
emptySuff = NULL;
- Lst_Destroy(&s->ref, NOFREE);
Lst_Destroy(&s->children, NOFREE);
Lst_Destroy(&s->parents, NOFREE);
Lst_Destroy(&s->searchPath, Dir_Destroy);
@@ -369,8 +373,8 @@ SuffFree(void *sp)
static void
SuffInsert(Lst l, Suff *s)
{
- LstNode ln; /* current element in l we're examining */
- Suff *s2 = NULL; /* the suffix descriptor in this element */
+ LstNode ln; /* current element in l we're examining */
+ Suff *s2 = NULL; /* the suffix descriptor in this element */
for (ln = Lst_First(l); ln != NULL; ln = Lst_Adv(ln)) {
s2 = (Suff *)Lst_Datum(ln);
@@ -378,21 +382,16 @@ SuffInsert(Lst l, Suff *s)
break;
}
- if (DEBUG(SUFF)) {
+ if (DEBUG(SUFF))
printf("inserting %s(%d)...", s->name, s->sNum);
- }
if (ln == NULL) {
- if (DEBUG(SUFF)) {
+ if (DEBUG(SUFF))
printf("at end of list\n");
- }
Lst_AtEnd(l, s);
- Lst_AtEnd(&s->ref, l);
} else if (s2->sNum != s->sNum) {
- if (DEBUG(SUFF)) {
+ if (DEBUG(SUFF))
printf("before %s(%d)\n", s2->name, s2->sNum);
- }
Lst_Insert(l, ln, s);
- Lst_AtEnd(&s->ref, l);
} else if (DEBUG(SUFF)) {
printf("already there\n");
}
@@ -401,359 +400,329 @@ SuffInsert(Lst l, Suff *s)
/*-
*-----------------------------------------------------------------------
* Suff_ClearSuffixes --
- * This is gross. Nuke the list of suffixes but keep all transformation
- * rules around. The transformation graph is destroyed in this process,
- * but we leave the list of rules so when a new graph is formed the rules
- * will remain.
- * This function is called from the parse module when a
- * .SUFFIXES:\n line is encountered.
+ * Nuke the list of suffixes but keep all transformation
+ * rules around.
*
* Side Effects:
- * the sufflist and its graph nodes are destroyed
+ * Current suffixes are reset
*-----------------------------------------------------------------------
*/
-void
-Suff_ClearSuffixes(void)
+static void
+clear_suffixes(void)
{
-#ifdef CLEANUP
- Lst_ConcatDestroy(&suffClean, &sufflist);
-#endif
- Lst_Init(&sufflist);
+ unsigned int i;
+ Suff *s;
+
+ for (s = ohash_first(&suffixes, &i); s != NULL;
+ s = ohash_next(&suffixes, &i))
+ s->flags &= ~SUFF_EXISTS;
+
sNum = 0;
+ maxLen = 0;
suffNull = emptySuff;
}
-/*-
- *-----------------------------------------------------------------------
- * SuffParseTransform --
- * Parse a transformation string to find its two component suffixes.
- *
- * Results:
- * true if the string is a valid transformation and false otherwise.
- *
- * Side Effects:
- * The passed pointers are overwritten.
- *-----------------------------------------------------------------------
+void
+Suff_ClearSuffixes(void)
+{
+ clear_suffixes();
+}
+
+
+/* okay = parse_transform(str, &src, &targ);
+ * try parsing a string as a transformation rule, returns true if
+ * successful. Fills &src, &targ with the constituent suffixes.
+ * Special hack: source suffixes must exist OR be the special SUFF_PATH
+ * pseudo suffix (.PATH)
*/
static bool
-SuffParseTransform(
- const char *str, /* String being parsed */
- Suff **srcPtr, /* Place to store source of trans. */
- Suff **targPtr) /* Place to store target of trans. */
+parse_transformi(const char *str, const char *e, Suff **srcPtr, Suff **targPtr)
{
- LstNode srcLn; /* element in suffix list of trans source*/
- Suff *src; /* Source of transformation */
- LstNode targLn; /* element in suffix list of trans target*/
- const char *str2; /* Extra pointer (maybe target suffix) */
- LstNode singleLn; /* element in suffix list of any suffix
- * that exactly matches str */
- Suff *single = NULL;/* Source of possible transformation to
- * null suffix */
-
- srcLn = NULL;
- singleLn = NULL;
+ Suff *src, *target, *best_src, *best_target;
+ const char *p;
- /*
- * Loop looking first for a suffix that matches the start of the
- * string and then for one that exactly matches the rest of it. If
- * we can find two that meet these criteria, we've successfully
- * parsed the string.
- */
- for (;;) {
- if (srcLn == NULL)
- srcLn = Lst_FindConst(&sufflist, SuffSuffIsPrefix, str);
- else
- srcLn = Lst_FindFromConst(Lst_Succ(srcLn),
- SuffSuffIsPrefix, str);
- if (srcLn == NULL) {
- /*
- * Ran out of source suffixes -- no such rule
- */
- if (singleLn != NULL) {
- /*
- * Not so fast Mr. Smith! There was a suffix
- * that encompassed the entire string, so we
- * assume it was a transformation to the null
- * suffix (thank you POSIX). We still prefer to
- * find a double rule over a singleton, hence
- * we leave this check until the end.
- *
- * XXX: Use emptySuff over suffNull?
+ size_t len;
+ uint32_t hv;
+ unsigned int slot;
+
+ /* empty string -> no suffix */
+ if (e == str)
+ return false;
+
+ len = e - str;
+
+ if (len > 2 * maxLen)
+ return false;
+
+ p = e;
+ best_src = best_target = NULL;
+
+ hv = *--p;
+ while (p != str) {
+ slot = ohash_lookup_interval(&suffixes, p, e, hv);
+ /* no double suffix in there */
+ if (p - str <= (ptrdiff_t)maxLen) {
+ target = ohash_find(&suffixes, slot);
+ if (target != NULL && (target->flags & SUFF_EXISTS)) {
+ src = find_suffi(str, p);
+ if (src != NULL &&
+ (src->flags & (SUFF_EXISTS | SUFF_PATH))) {
+ /* XXX even if we find a set of suffixes, we
+ * have to keep going to find the best one,
+ * namely, the one whose src appears first in
+ * .SUFFIXES
*/
- *srcPtr = single;
- *targPtr = suffNull;
- return true;
+ if (best_src == NULL ||
+ src->sNum < best_src->sNum) {
+ best_src = src;
+ best_target = target;
+ }
+ }
}
- return false;
}
- src = (Suff *)Lst_Datum(srcLn);
- str2 = str + src->nameLen;
- if (*str2 == '\0') {
- single = src;
- singleLn = srcLn;
- } else {
- targLn = suff_find_by_name(str2);
- if (targLn != NULL) {
- *srcPtr = src;
- *targPtr = (Suff *)Lst_Datum(targLn);
- return true;
- }
+ /* can't be a suffix anyways */
+ if (e - p >= (ptrdiff_t)maxLen)
+ break;
+ reverse_hash_add_char(&hv, --p);
+ }
+
+ if (p == str && best_src == NULL) {
+ /* no double suffix transformation, resort to single suffix if
+ * we find one. */
+ slot = ohash_lookup_interval(&suffixes, p, e, hv);
+ src = ohash_find(&suffixes, slot);
+ if (src != NULL && (src->flags & (SUFF_EXISTS | SUFF_PATH))) {
+ best_src = src;
+ best_target = suffNull;
}
}
+ if (best_src != NULL) {
+ *srcPtr = best_src;
+ *targPtr = best_target;
+ return true;
+ } else {
+ return false;
+ }
}
-/*-
- *-----------------------------------------------------------------------
- * Suff_IsTransform --
- * Return true if the given string is a transformation rule
- *
- * Results:
- * true if the string is a concatenation of two known suffixes.
- * false otherwise
- *-----------------------------------------------------------------------
- */
-bool
-Suff_IsTransform(const char *str)
+static void
+special_path_hack(void)
+{
+ Suff *path = add_suffixi(".PATH", NULL);
+ path->flags |= SUFF_PATH;
+}
+
+static Suff *
+find_best_suffix(const char *s, const char *e)
{
- Suff *src, *targ;
+ const char *p;
+ uint32_t hv;
+ unsigned int slot;
+ Suff *best = NULL;
+ Suff *suff;
- return SuffParseTransform(str, &src, &targ);
+ if (e == s)
+ return NULL;
+ p = e;
+ hv = *--p;
+ while (p != s) {
+ slot = ohash_lookup_interval(&suffixes, p, e, hv);
+ suff = ohash_find(&suffixes, slot);
+ if (suff != NULL)
+ if (best == NULL || suff->sNum < best->sNum)
+ best = suff;
+ if (e - p >= (ptrdiff_t)maxLen)
+ break;
+ reverse_hash_add_char(&hv, --p);
+ }
+ return best;
}
/*-
*-----------------------------------------------------------------------
- * Suff_AddTransform --
- * Add the transformation rule described by the line to the
- * list of rules and place the transformation itself in the graph
- *
- * Results:
- * The node created for the transformation in the transforms list
+ * Suff_ParseAsTransform --
+ * Try parsing a target line as a transformation rule, depending on
+ * existing suffixes.
*
- * Side Effects:
- * The node is placed on the end of the transforms Lst and links are
- * made between the two suffixes mentioned in the target name
+ * Possibly create anew transform, or reset an existing one.
*-----------------------------------------------------------------------
*/
GNode *
-Suff_AddTransform(const char *line)
+Suff_ParseAsTransform(const char *line, const char *end)
{
- GNode *gn; /* GNode of transformation rule */
- Suff *s, /* source suffix */
- *t; /* target suffix */
- LstNode ln; /* Node for existing transformation */
+ GNode *gn; /* GNode of transformation rule */
+ Suff *s; /* source suffix */
+ Suff *t; /* target suffix */
- ln = transform_find_by_name(line);
- if (ln == NULL) {
- /*
- * Make a new graph node for the transformation. It will be
- * filled in by the Parse module.
- */
- gn = Targ_NewGN(line);
- Lst_AtEnd(&transforms, gn);
- } else {
- /*
- * New specification for transformation rule. Just nuke the old
- * list of commands so they can be filled in again... We don't
- * actually free the commands themselves, because a given
- * command can be attached to several different
- * transformations.
- */
- gn = (GNode *)Lst_Datum(ln);
+ if (!parse_transformi(line, end, &s, &t))
+ return NULL;
+
+ gn = find_or_create_transformi(line, end);
+ /* In case the transform already exists, nuke old commands and children.
+ * Note we can't free them, since there might be stuff that references
+ * them elsewhere
+ */
+ if (!Lst_IsEmpty(&gn->commands)) {
Lst_Destroy(&gn->commands, NOFREE);
Lst_Init(&gn->commands);
+ }
+ if (!Lst_IsEmpty(&gn->children)) {
Lst_Destroy(&gn->children, NOFREE);
Lst_Init(&gn->children);
}
gn->type = OP_TRANSFORM;
+ if (s->flags & SUFF_PATH) {
+ gn->special = SPECIAL_PATH | SPECIAL_TARGET;
+ gn->suffix = t;
+ }
- (void)SuffParseTransform(line, &s, &t);
-
- /*
- * link the two together in the proper relationship and order
- */
- if (DEBUG(SUFF)) {
+ if (DEBUG(SUFF))
printf("defining transformation from `%s' to `%s'\n",
s->name, t->name);
+ return gn;
+}
+
+static void
+make_suffix_known(Suff *s)
+{
+ if ((s->flags & SUFF_EXISTS) == 0) {
+ s->sNum = sNum++;
+ s->flags |= SUFF_EXISTS;
+ if (s->nameLen > maxLen)
+ maxLen = s->nameLen;
}
- SuffInsert(&t->children, s);
- SuffInsert(&s->parents, t);
+}
- return gn;
+static Suff *
+new_suffixi(const char *str, const char *eptr)
+{
+ Suff *s;
+
+ s = ohash_create_entry(&suff_info, str, &eptr);
+ s->nameLen = eptr - str;
+ Lst_Init(&s->searchPath);
+ Lst_Init(&s->children);
+ Lst_Init(&s->parents);
+ s->flags = 0;
+ return s;
}
/*-
*-----------------------------------------------------------------------
- * Suff_EndTransform --
- * Handle the finish of a transformation definition, removing the
- * transformation from the graph if it has neither commands nor
- * sources. This is a callback procedure for the Parse module via
- * Lst_ForEach
+ * Suff_AddSuffix --
+ * Add the suffix in string to the end of the list of known suffixes.
+ * Should we restructure the suffix graph? Make doesn't...
*
* Side Effects:
- * If the node has no commands or children, the children and parents
- * lists of the affected suffices are altered.
+ * A GNode is created for the suffix and a Suff structure is created and
+ * added to the known suffixes, unless it was already known.
*-----------------------------------------------------------------------
*/
void
-Suff_EndTransform(void *gnp)
+Suff_AddSuffixi(const char *str, const char *end)
{
- GNode *gn = (GNode *)gnp;
-
- if ((gn->type & OP_TRANSFORM) && Lst_IsEmpty(&gn->commands) &&
- Lst_IsEmpty(&gn->children)) {
- Suff *s, *t;
-
- if (!SuffParseTransform(gn->name, &s, &t))
- return;
+ (void)add_suffixi(str, end);
+}
- if (DEBUG(SUFF)) {
- printf("deleting transformation from `%s' to `%s'\n",
- s->name, t->name);
- }
+static Suff *
+add_suffixi(const char *str, const char *end)
+{
+ Suff *s; /* new suffix descriptor */
- /*
- * Remove the source from the target's children list.
- *
- * We'll be called twice when the next target is seen, but .c
- * and .o are only linked once...
- */
- SuffUnRef(&t->children, s);
+ unsigned int slot;
- /*
- * Remove the target from the source's parents list
- */
- if (s != NULL)
- SuffUnRef(&s->parents, t);
- } else if ((gn->type & OP_TRANSFORM) && DEBUG(SUFF)) {
- printf("transformation %s complete\n", gn->name);
+ slot = reverse_slot(&suffixes, str, &end);
+ s = ohash_find(&suffixes, slot);
+ if (s == NULL) {
+ s = new_suffixi(str, end);
+ ohash_insert(&suffixes, slot, s);
}
+ make_suffix_known(s);
+ return s;
}
-/*-
- *-----------------------------------------------------------------------
- * SuffRebuildGraph --
- * Called from Suff_AddSuffix via Lst_ForEach to search through the
- * list of existing transformation rules and rebuild the transformation
- * graph when it has been destroyed by Suff_ClearSuffixes. If the
- * given rule is a transformation involving this suffix and another,
- * existing suffix, the proper relationship is established between
- * the two.
- *
- * Side Effects:
- * The appropriate links will be made between this suffix and
- * others if transformation rules exist for it.
- *-----------------------------------------------------------------------
+Lst
+find_suffix_path(GNode *gn)
+{
+ if (gn->suffix != NULL && gn->suffix != emptySuff)
+ return &(gn->suffix->searchPath);
+ else
+ return defaultPath;
+}
+
+/* find out the tagged suffixes, build a temporary path, and construct
+ * a variable based on that.
*/
static void
-SuffRebuildGraph(
- void *transformp, /* Transformation to test */
- void *sp) /* Suffix to rebuild */
+build_path_variable(struct ohash *h, int opt, const char *name,
+ const char *flag)
{
- GNode *transform = (GNode *)transformp;
- Suff *s = (Suff *)sp;
- char *cp;
- LstNode ln;
- Suff *s2;
-
- /* First see if it is a transformation from this suffix. */
- cp = SuffStrIsPrefix(s->name, transform->name);
- if (cp != NULL) {
- ln = suff_find_by_name(cp);
- if (ln != NULL) {
- /* Found target. Link in and return, since it can't be
- * anything else. */
- s2 = (Suff *)Lst_Datum(ln);
- SuffInsert(&s2->children, s);
- SuffInsert(&s->parents, s2);
- return;
- }
+ char *value;
+ LIST path;
+ Suff *s;
+ unsigned int i;
+
+ Lst_Init(&path);
+ for (s = ohash_first(h, &i); s != NULL; s = ohash_next(h, &i)) {
+ if (Lst_IsEmpty(&s->searchPath))
+ continue;
+ if (s->flags & opt)
+ Dir_Concat(&path, &s->searchPath);
}
- /* Not from, maybe to? */
- cp = SuffSuffIsSuffix(s, transform->name + strlen(transform->name));
- if (cp != NULL) {
- /* Null-terminate the source suffix in order to find it. */
- *cp = '\0';
- ln = suff_find_by_name(transform->name);
- /* Replace the start of the target suffix. */
- *cp = s->name[0];
- if (ln != NULL) {
- /* Found it -- establish the proper relationship. */
- s2 = (Suff *)Lst_Datum(ln);
- SuffInsert(&s->children, s2);
- SuffInsert(&s2->parents, s);
- }
+ value = Dir_MakeFlags(flag, &path);
+ Var_Set(name, value);
+ free(value);
+ Lst_Destroy(&path, Dir_Destroy);
+}
+
+static void
+add_property(const char *sname, const char *end, int opt)
+{
+ Suff *s;
+
+ s = find_suffi(sname, end);
+ if (s != NULL) {
+ s->flags |= opt;
}
}
-/*-
- *-----------------------------------------------------------------------
- * Suff_AddSuffix --
- * Add the suffix in string to the end of the list of known suffixes.
- * Should we restructure the suffix graph? Make doesn't...
- *
- * Side Effects:
- * A GNode is created for the suffix and a Suff structure is created and
- * added to the suffixes list unless the suffix was already known.
- *-----------------------------------------------------------------------
- */
void
-Suff_AddSuffix(const char *str)
+Suff_AddIncludei(const char *sname, const char *end)
{
- Suff *s; /* new suffix descriptor */
- LstNode ln;
+ add_property(sname, end, SUFF_INCLUDE);
+}
- ln = suff_find_by_name(str);
- if (ln == NULL) {
- s = emalloc(sizeof(Suff));
-
- s->name = estrdup(str);
- s->nameLen = strlen(s->name);
- Lst_Init(&s->searchPath);
- Lst_Init(&s->children);
- Lst_Init(&s->parents);
- Lst_Init(&s->ref);
- s->sNum = sNum++;
- s->flags = 0;
-
- Lst_AtEnd(&sufflist, s);
- /*
- * Look for any existing transformations from or to this suffix.
- * XXX: Only do this after a Suff_ClearSuffixes?
- */
- Lst_ForEach(&transforms, SuffRebuildGraph, s);
- }
+void
+Suff_AddLibi(const char *sname, const char *end)
+{
+ add_property(sname, end, SUFF_LIBRARY);
}
-/*-
- *-----------------------------------------------------------------------
- * Suff_GetPath --
- * Return the search path for the given suffix, if it's defined.
- *
- * Results:
- * The searchPath for the desired suffix or NULL if the suffix isn't
- * defined.
- *-----------------------------------------------------------------------
- */
-Lst
-Suff_GetPath(const char *sname)
+static void
+build_suffixes_graph(void)
{
- LstNode ln;
- Suff *s;
+ Suff *s, *s2;
+ GNode *gn;
+ unsigned int i;
- ln = suff_find_by_name(sname);
- if (ln == NULL) {
- return NULL;
- } else {
- s = (Suff *)Lst_Datum(ln);
- return &s->searchPath;
+ for (gn = ohash_first(&transforms, &i); gn != NULL;
+ gn = ohash_next(&transforms, &i)) {
+ if (Lst_IsEmpty(&gn->commands) && Lst_IsEmpty(&gn->children))
+ continue;
+ if ((gn->special & SPECIAL_MASK) == SPECIAL_PATH)
+ continue;
+ if (parse_transform(gn->name, &s, &s2)) {
+ SuffInsert(&s2->children, s);
+ SuffInsert(&s->parents, s2);
+ }
}
}
/*-
*-----------------------------------------------------------------------
- * Suff_DoPaths --
+ * setup_paths
* Extend the search paths for all suffixes to include the default
* search path.
*
@@ -766,90 +735,34 @@ Suff_GetPath(const char *sname)
* ".LIBS" and the flag is -L.
*-----------------------------------------------------------------------
*/
-void
-Suff_DoPaths(void)
+static void
+setup_paths(void)
{
- Suff *s;
- LstNode ln;
- char *ptr;
- LIST inIncludes; /* Cumulative .INCLUDES path */
- LIST inLibs; /* Cumulative .LIBS path */
-
- Lst_Init(&inIncludes);
- Lst_Init(&inLibs);
+ unsigned int i;
+ Suff *s;
- for (ln = Lst_First(&sufflist); ln != NULL; ln = Lst_Adv(ln)) {
- s = (Suff *)Lst_Datum(ln);
- if (!Lst_IsEmpty(&s->searchPath)) {
- if (s->flags & SUFF_INCLUDE) {
- Dir_Concat(&inIncludes, &s->searchPath);
- }
- if (s->flags & SUFF_LIBRARY) {
- Dir_Concat(&inLibs, &s->searchPath);
- }
+ for (s = ohash_first(&suffixes, &i); s != NULL;
+ s = ohash_next(&suffixes, &i)) {
+ if (!Lst_IsEmpty(&s->searchPath))
Dir_Concat(&s->searchPath, defaultPath);
- } else
+ else
Lst_Clone(&s->searchPath, defaultPath, Dir_CopyDir);
}
- Var_Set(".INCLUDES", ptr = Dir_MakeFlags("-I", &inIncludes));
- free(ptr);
- Var_Set(".LIBS", ptr = Dir_MakeFlags("-L", &inLibs));
- free(ptr);
-
- Lst_Destroy(&inIncludes, Dir_Destroy);
- Lst_Destroy(&inLibs, Dir_Destroy);
-}
-
-/*-
- *-----------------------------------------------------------------------
- * Suff_AddInclude --
- * Add the given suffix as a type of file which gets included.
- * Called from the parse module when a .INCLUDES line is parsed.
- * The suffix must have already been defined.
- *
- * Side Effects:
- * The SUFF_INCLUDE bit is set in the suffix's flags field
- *-----------------------------------------------------------------------
- */
-void
-Suff_AddInclude(const char *sname) /* Name of suffix to mark */
-{
- LstNode ln;
- Suff *s;
-
- ln = suff_find_by_name(sname);
- if (ln != NULL) {
- s = (Suff *)Lst_Datum(ln);
- s->flags |= SUFF_INCLUDE;
- }
+ build_path_variable(&suffixes, SUFF_INCLUDE, ".INCLUDES", "-I");
+ build_path_variable(&suffixes, SUFF_LIBRARY, ".LIBS", "-L");
}
-/*-
- *-----------------------------------------------------------------------
- * Suff_AddLib --
- * Add the given suffix as a type of file which is a library.
- * Called from the parse module when parsing a .LIBS line. The
- * suffix must have been defined via .SUFFIXES before this is
- * called.
- *
- * Side Effects:
- * The SUFF_LIBRARY bit is set in the suffix's flags field
- *-----------------------------------------------------------------------
- */
void
-Suff_AddLib(const char *sname) /* Name of suffix to mark */
+process_suffixes_after_makefile_is_read(void)
{
- LstNode ln;
- Suff *s;
-
- ln = suff_find_by_name(sname);
- if (ln != NULL) {
- s = (Suff *)Lst_Datum(ln);
- s->flags |= SUFF_LIBRARY;
- }
+ /* once the Makefile is finish reading, we can set up the default PATH
+ * stuff, and build the final suffixes graph
+ */
+ setup_paths();
+ /* and we link all transforms to active suffixes at this point. */
+ build_suffixes_graph();
}
-
/********** Implicit Source Search Functions *********/
/*-
@@ -865,13 +778,13 @@ Suff_AddLib(const char *sname) /* Name of suffix to mark */
*/
static void
SuffAddSrc(
- void *sp, /* suffix for which to create a Src structure */
- void *lsp) /* list and parent for the new Src */
+ void *sp, /* suffix for which to create a Src structure */
+ void *lsp) /* list and parent for the new Src */
{
- Suff *s = (Suff *)sp;
- LstSrc *ls = (LstSrc *)lsp;
- Src *s2; /* new Src structure */
- Src *targ; /* Target structure */
+ Suff *s = (Suff *)sp;
+ LstSrc *ls = (LstSrc *)lsp;
+ Src *s2; /* new Src structure */
+ Src *targ; /* Target structure */
targ = ls->s;
@@ -882,12 +795,12 @@ SuffAddSrc(
* Two birds, and all that...
*/
s2 = emalloc(sizeof(Src));
- s2->file = estrdup(targ->pref);
- s2->pref = targ->pref;
- s2->parent = targ;
- s2->node = NULL;
- s2->suff = s;
- s2->children = 0;
+ s2->file = estrdup(targ->pref);
+ s2->pref = targ->pref;
+ s2->parent = targ;
+ s2->node = NULL;
+ s2->suff = s;
+ s2->children = 0;
targ->children++;
Lst_AtEnd(ls->l, s2);
#ifdef DEBUG_SRC
@@ -899,16 +812,16 @@ SuffAddSrc(
#endif
}
s2 = emalloc(sizeof(Src));
- s2->file = Str_concat(targ->pref, s->name, 0);
- s2->pref = targ->pref;
- s2->parent = targ;
- s2->node = NULL;
- s2->suff = s;
- s2->children = 0;
+ s2->file = Str_concat(targ->pref, s->name, 0);
+ s2->pref = targ->pref;
+ s2->parent = targ;
+ s2->node = NULL;
+ s2->suff = s;
+ s2->children = 0;
targ->children++;
Lst_AtEnd(ls->l, s2);
#ifdef DEBUG_SRC
- Lst_Init(&s2->cp);
+ Lst_Init(&s2->cp);
Lst_AtEnd(&targ->cp, s2);
printf("2 add %x %x to %x:", targ, s2, ls->l);
Lst_Every(ls->l, PrintAddr);
@@ -928,8 +841,8 @@ SuffAddSrc(
*/
static void
SuffAddLevel(
- Lst l, /* list to which to add the new level */
- Src *targ) /* Src structure to use as the parent */
+ Lst l, /* list to which to add the new level */
+ Src *targ) /* Src structure to use as the parent */
{
LstSrc ls;
@@ -1011,19 +924,18 @@ SuffRemoveSrc(Lst l)
*/
static Src *
SuffFindThem(
- Lst srcs, /* list of Src structures to search through */
- Lst slst)
+ Lst srcs, /* list of Src structures to search through */
+ Lst slst)
{
- Src *s; /* current Src */
- Src *rs; /* returned Src */
- char *ptr;
+ Src *s; /* current Src */
+ Src *rs; /* returned Src */
+ char *ptr;
rs = NULL;
while ((s = (Src *)Lst_DeQueue(srcs)) != NULL) {
- if (DEBUG(SUFF)) {
+ if (DEBUG(SUFF))
printf("\ttrying %s...", s->file);
- }
/*
* A file is considered to exist if either a node exists in the
@@ -1047,17 +959,15 @@ SuffFindThem(
break;
}
- if (DEBUG(SUFF)) {
- printf("not there\n");
- }
+ if (DEBUG(SUFF))
+ printf("not there\n");
SuffAddLevel(srcs, s);
Lst_AtEnd(slst, s);
}
- if (DEBUG(SUFF) && rs) {
- printf("got it\n");
- }
+ if (DEBUG(SUFF) && rs)
+ printf("got it\n");
return rs;
}
@@ -1080,13 +990,13 @@ SuffFindCmds(
Src *targ, /* Src structure to play with */
Lst slst)
{
- LstNode ln; /* General-purpose list node */
- GNode *t, /* Target GNode */
- *s; /* Source GNode */
- int prefLen;/* The length of the defined prefix */
- Suff *suff; /* Suffix on matching beastie */
- Src *ret; /* Return value */
- const char *cp;
+ LstNode ln; /* General-purpose list node */
+ GNode *t; /* Target GNode */
+ GNode *s; /* Source GNode */
+ int prefLen; /* The length of the defined prefix */
+ Suff *suff; /* Suffix on matching beastie */
+ Src *ret; /* Return value */
+ const char *cp;
t = targ->node;
prefLen = strlen(targ->pref);
@@ -1103,9 +1013,8 @@ SuffFindCmds(
if (strncmp(cp, targ->pref, prefLen) == 0) {
/* The node matches the prefix ok, see if it has a known
* suffix. */
- LstNode ln2;
- ln2 = suff_find_by_name(&cp[prefLen]);
- if (ln2 != NULL) {
+ suff = find_suff(&cp[prefLen]);
+ if (suff != NULL) {
/*
* It even has a known suffix, see if there's a
* transformation defined between the node's
@@ -1114,8 +1023,6 @@ SuffFindCmds(
* XXX: Handle multi-stage transformations
* here, too.
*/
- suff = (Suff *)Lst_Datum(ln2);
-
if (Lst_Member(&suff->parents, targ->suff)
!= NULL) {
/*
@@ -1140,11 +1047,12 @@ SuffFindCmds(
Lst_AtEnd(&targ->cp, ret);
#endif
Lst_AtEnd(slst, ret);
- if (DEBUG(SUFF)) {
- printf ("\tusing existing source %s\n", s->name);
- }
+ if (DEBUG(SUFF))
+ printf(
+ "\tusing existing source %s\n",
+ s->name);
return ret;
- }
+ }
}
}
}
@@ -1154,9 +1062,9 @@ SuffFindCmds(
static void
SuffExpandVarChildren(LstNode after, GNode *cgn, GNode *pgn)
{
- GNode *gn; /* New source 8) */
- char *cp; /* Expanded value */
- LIST members;
+ GNode *gn; /* New source 8) */
+ char *cp; /* Expanded value */
+ LIST members;
if (DEBUG(SUFF))
@@ -1177,7 +1085,7 @@ SuffExpandVarChildren(LstNode after, GNode *cgn, GNode *pgn)
* on the Arch module to find the nodes for us, expanding
* variables in the parent's context.
*/
- const char *sacrifice = cp;
+ const char *sacrifice = (const char *)cp;
(void)Arch_ParseArchive(&sacrifice, &members, &pgn->context);
} else {
@@ -1186,7 +1094,7 @@ SuffExpandVarChildren(LstNode after, GNode *cgn, GNode *pgn)
* Unfortunately, we can't use brk_string because it
* doesn't understand about variable specifications with
* spaces in them... */
- char *start, *cp2;
+ const char *start, *cp2;
for (start = cp; *start == ' ' || *start == '\t'; start++)
continue;
@@ -1212,13 +1120,13 @@ SuffExpandVarChildren(LstNode after, GNode *cgn, GNode *pgn)
cp2+=2;
else
cp2++;
- }
+ }
- if (cp2 != start) {
- /* Stuff left over -- add it to the list too. */
- gn = Targ_FindNodei(start, cp2, TARG_CREATE);
- Lst_AtEnd(&members, gn);
- }
+ if (cp2 != start) {
+ /* Stuff left over -- add it to the list too. */
+ gn = Targ_FindNodei(start, cp2, TARG_CREATE);
+ Lst_AtEnd(&members, gn);
+ }
}
/* Add all elements of the members list to the parent node. */
while ((gn = (GNode *)Lst_DeQueue(&members)) != NULL) {
@@ -1240,11 +1148,11 @@ SuffExpandVarChildren(LstNode after, GNode *cgn, GNode *pgn)
static void
SuffExpandWildChildren(LstNode after, GNode *cgn, GNode *pgn)
{
- LstNode ln; /* List element for old source */
- char *cp; /* Expanded value */
+ Suff *s;
+ char *cp; /* Expanded value */
- LIST exp; /* List of expansions */
- Lst path; /* Search path along which to expand */
+ LIST exp; /* List of expansions */
+ Lst path; /* Search path along which to expand */
if (DEBUG(SUFF))
printf("Wildcard expanding \"%s\"...", cgn->name);
@@ -1255,12 +1163,9 @@ SuffExpandWildChildren(LstNode after, GNode *cgn, GNode *pgn)
* If it has no known suffix and we're allowed to use the null
* suffix, use its path.
* Else use the default system search path. */
- cp = cgn->name + strlen(cgn->name);
- ln = Lst_FindConst(&sufflist, SuffSuffIsSuffixP, cp);
-
- if (ln != NULL) {
- Suff *s = (Suff *)Lst_Datum(ln);
+ s = find_best_suffix(cgn->name, cgn->name + strlen(cgn->name));
+ if (s != NULL) {
if (DEBUG(SUFF))
printf("suffix is \"%s\"...", s->name);
path = &s->searchPath;
@@ -1274,7 +1179,7 @@ SuffExpandWildChildren(LstNode after, GNode *cgn, GNode *pgn)
/* Fetch next expansion off the list and find its GNode. */
while ((cp = (char *)Lst_DeQueue(&exp)) != NULL) {
- GNode *gn; /* New source 8) */
+ GNode *gn; /* New source 8) */
if (DEBUG(SUFF))
printf("%s...", cp);
gn = Targ_FindNode(cp, TARG_CREATE);
@@ -1326,7 +1231,7 @@ SuffExpandChildren(
else if (Dir_HasWildcards(cgn->name))
SuffExpandWildChildren(ln, cgn, pgn);
else
- /* Third case: nothing to expand. */
+ /* Third case: nothing to expand. */
return;
/* Since the source was expanded, remove it from the list of children to
@@ -1390,10 +1295,10 @@ SuffApplyTransform(
}
/* Locate the transformation rule itself. */
tname = Str_concat(s->name, t->name, 0);
- ln = transform_find_by_name(tname);
+ gn = find_transform(tname);
free(tname);
- if (ln == NULL)
+ if (gn == NULL)
/*
* Not really such a transformation rule (can happen when we're
* called to link an OP_MEMBER and OP_ARCHV node), so return
@@ -1401,8 +1306,6 @@ SuffApplyTransform(
*/
return false;
- gn = (GNode *)Lst_Datum(ln);
-
if (DEBUG(SUFF))
printf("\tapplying %s -> %s to \"%s\"\n", s->name, t->name,
tGn->name);
@@ -1426,6 +1329,19 @@ SuffApplyTransform(
return true;
}
+static Suff *
+find_suffix_as_suffix(Lst l, const char *b, const char *e)
+{
+ LstNode ln;
+ Suff *s;
+
+ for (ln = Lst_First(l); ln != NULL; ln = Lst_Adv(ln)) {
+ s = (Suff *)Lst_Datum(ln);
+ if (suffix_is_suffix(s, b, e))
+ return s;
+ }
+ return NULL;
+}
/*-
*-----------------------------------------------------------------------
@@ -1438,14 +1354,14 @@ SuffApplyTransform(
*/
static void
SuffFindArchiveDeps(
- GNode *gn, /* Node for which to locate dependencies */
+ GNode *gn, /* Node for which to locate dependencies */
Lst slst)
{
- char *eoarch; /* End of archive portion */
- char *eoname; /* End of member portion */
- GNode *mem; /* Node for member */
- Suff *ms; /* Suffix descriptor for member */
- char *name; /* Start of member's name */
+ char *eoarch; /* End of archive portion */
+ char *eoname; /* End of member portion */
+ GNode *mem; /* Node for member */
+ Suff *ms; /* Suffix descriptor for member */
+ char *name; /* Start of member's name */
/* The node is an archive(member) pair. so we must find a suffix
* for both of them. */
@@ -1498,17 +1414,17 @@ SuffFindArchiveDeps(
* searching through the entire list, we just look at suffixes
* to which the member's suffix may be transformed...
*/
- LstNode ln;
- /* Use first matching suffix... */
- ln = Lst_FindConst(&ms->parents, SuffSuffIsSuffixP, eoarch);
+ Suff *suff;
- if (ln != NULL) {
+ suff = find_suffix_as_suffix(&ms->parents, gn->name, eoarch);
+
+ if (suff != NULL) {
/* Got one -- apply it. */
- if (!SuffApplyTransform(gn, mem, (Suff *)Lst_Datum(ln),
- ms) && DEBUG(SUFF))
+ if (!SuffApplyTransform(gn, mem, suff, ms) &&
+ DEBUG(SUFF))
printf("\tNo transformation from %s -> %s\n",
- ms->name, ((Suff *)Lst_Datum(ln))->name);
+ ms->name, suff->name);
}
}
@@ -1523,6 +1439,65 @@ SuffFindArchiveDeps(
mem->type |= OP_MEMBER;
}
+static void
+record_possible_suffix(Suff *s, GNode *gn, char *eoname, Lst srcs, Lst targs)
+{
+ int prefLen;
+ Src *targ;
+ char *sopref = gn->name;
+
+ targ = emalloc(sizeof(Src));
+ targ->file = estrdup(gn->name);
+ targ->suff = s;
+ targ->node = gn;
+ targ->parent = NULL;
+ targ->children = 0;
+#ifdef DEBUG_SRC
+ Lst_Init(&targ->cp);
+#endif
+
+ /* Allocate room for the prefix, whose end is found by
+ * subtracting the length of the suffix from the end of
+ * the name. */
+ prefLen = (eoname - targ->suff->nameLen) - sopref;
+ targ->pref = emalloc(prefLen + 1);
+ memcpy(targ->pref, sopref, prefLen);
+ targ->pref[prefLen] = '\0';
+
+ /* Add nodes from which the target can be made. */
+ SuffAddLevel(srcs, targ);
+
+ /* Record the target so we can nuke it. */
+ Lst_AtEnd(targs, targ);
+}
+
+static void
+record_possible_suffixes(GNode *gn, Lst srcs, Lst targs)
+{
+ char *s = gn->name;
+ char *e = s + strlen(s);
+ const char *p;
+ uint32_t hv;
+ unsigned int slot;
+ Suff *suff;
+
+ if (e == s)
+ return;
+
+ p = e;
+ hv = *--p;
+
+ while (p != s) {
+ slot = ohash_lookup_interval(&suffixes, p, e, hv);
+ suff = ohash_find(&suffixes, slot);
+ if (suff != NULL && (suff->flags & SUFF_EXISTS))
+ record_possible_suffix(suff, gn, e, srcs, targs);
+ if (e - p >= (ptrdiff_t)maxLen)
+ break;
+ reverse_hash_add_char(&hv, --p);
+ }
+}
+
/*-
*-----------------------------------------------------------------------
* SuffFindNormalDeps --
@@ -1537,26 +1512,18 @@ SuffFindNormalDeps(
GNode *gn, /* Node for which to find sources */
Lst slst)
{
- char *eoname; /* End of name */
- char *sopref; /* Start of prefix */
- LstNode ln; /* Next suffix node to check */
LstNode np;
- LIST srcs; /* List of sources at which to look */
- LIST targs; /* List of targets to which things can be
- * transformed. They all have the same file,
- * but different suff and pref fields */
- Src *bottom; /* Start of found transformation path */
- Src *src; /* General Src pointer */
- char *pref; /* Prefix to use */
- Src *targ; /* General Src target pointer */
-
-
- eoname = gn->name + strlen(gn->name);
+ LstNode ln;
+ LIST srcs; /* List of sources at which to look */
+ LIST targs; /* List of targets to which things can be
+ * transformed. They all have the same file,
+ * but different suff and pref fields */
+ Src *bottom; /* Start of found transformation path */
+ Src *src; /* General Src pointer */
+ char *pref; /* Prefix to use */
+ Src *targ; /* General Src target pointer */
- sopref = gn->name;
- /* Begin at the beginning... */
- ln = Lst_First(&sufflist);
Lst_Init(&srcs);
Lst_Init(&targs);
@@ -1577,51 +1544,13 @@ SuffFindNormalDeps(
* children, then look for any overriding transformations they imply.
* Should we find one, we discard the one we found before. */
- while (ln != NULL) {
- /* Look for next possible suffix... */
- ln = Lst_FindFromConst(ln, SuffSuffIsSuffixP, eoname);
-
- if (ln != NULL) {
- int prefLen; /* Length of the prefix */
- Src *targ;
-
- /* Allocate a Src structure to which things can be
- * transformed. */
- targ = emalloc(sizeof(Src));
- targ->file = estrdup(gn->name);
- targ->suff = (Suff *)Lst_Datum(ln);
- targ->node = gn;
- targ->parent = NULL;
- targ->children = 0;
-#ifdef DEBUG_SRC
- Lst_Init(&targ->cp);
-#endif
-
- /* Allocate room for the prefix, whose end is found by
- * subtracting the length of the suffix from the end of
- * the name. */
- prefLen = (eoname - targ->suff->nameLen) - sopref;
- targ->pref = emalloc(prefLen + 1);
- memcpy(targ->pref, sopref, prefLen);
- targ->pref[prefLen] = '\0';
-
- /* Add nodes from which the target can be made. */
- SuffAddLevel(&srcs, targ);
-
- /* Record the target so we can nuke it. */
- Lst_AtEnd(&targs, targ);
-
- /* Search from this suffix's successor... */
- ln = Lst_Succ(ln);
- }
- }
+ record_possible_suffixes(gn, &srcs, &targs);
/* Handle target of unknown suffix... */
- if (Lst_IsEmpty(&targs) && suffNull != NULL) {
- if (DEBUG(SUFF)) {
+ if (Lst_IsEmpty(&targs)) {
+ if (DEBUG(SUFF))
printf("\tNo known suffix on %s. Using .NULL suffix\n",
gn->name);
- }
targ = emalloc(sizeof(Src));
targ->file = estrdup(gn->name);
@@ -1629,7 +1558,7 @@ SuffFindNormalDeps(
targ->node = gn;
targ->parent = NULL;
targ->children = 0;
- targ->pref = estrdup(sopref);
+ targ->pref = estrdup(gn->name);
#ifdef DEBUG_SRC
Lst_Init(&targ->cp);
#endif
@@ -1688,9 +1617,9 @@ SuffFindNormalDeps(
printf("\tNo valid suffix on %s\n", gn->name);
sfnd_abort:
- /* Deal with finding the thing on the default search path if
- * the node is only a source (not on the lhs of a dependency
- * operator or [XXX] it has neither children or commands). */
+ /* Deal with finding the thing on the default search path if the
+ * node is only a source (not on the lhs of a dependency operator
+ * or [XXX] it has neither children or commands). */
if (OP_NOP(gn->type) ||
(Lst_IsEmpty(&gn->children) &&
Lst_IsEmpty(&gn->commands))) {
@@ -1714,8 +1643,8 @@ sfnd_abort:
savec = gn->path[savep];
gn->path[savep] = '\0';
- if ((ptr = strrchr(gn->path, '/'))
- != NULL)
+ if ((ptr = strrchr(gn->path, '/')) !=
+ NULL)
ptr++;
else
ptr = gn->path;
@@ -1724,12 +1653,12 @@ sfnd_abort:
gn->path[savep] = savec;
} else {
- /* The .PREFIX gets the full path if
- * the target has no known suffix. */
+ /* The .PREFIX gets the full path if the
+ * target has no known suffix. */
gn->suffix = NULL;
- if ((ptr = strrchr(gn->path, '/'))
- != NULL)
+ if ((ptr = strrchr(gn->path, '/')) !=
+ NULL)
ptr++;
else
ptr = gn->path;
@@ -1797,8 +1726,8 @@ sfnd_abort:
targ->node = Targ_FindNode(targ->file, TARG_CREATE);
}
- SuffApplyTransform(targ->node, src->node, targ->suff,
- src->suff);
+ SuffApplyTransform(targ->node, src->node,
+ targ->suff, src->suff);
if (targ->node != gn) {
/* Finish off the dependency-search process for any
@@ -1882,9 +1811,8 @@ SuffFindDeps(GNode *gn, Lst slst)
gn->type |= OP_DEPS_FOUND;
}
- if (DEBUG(SUFF)) {
+ if (DEBUG(SUFF))
printf("SuffFindDeps (%s)\n", gn->name);
- }
if (gn->type & OP_ARCHV) {
SuffFindArchiveDeps(gn, slst);
@@ -1897,12 +1825,11 @@ SuffFindDeps(GNode *gn, Lst slst)
* do for it, so we just set the TARGET variable to the node's
* name in order to give it a value).
*/
- LstNode ln;
Suff *s;
- ln = suff_find_by_name(LIBSUFF);
- if (ln != NULL) {
- gn->suffix = s = (Suff *)Lst_Datum(ln);
+ s = find_suff(LIBSUFF);
+ if (s != NULL) {
+ gn->suffix = s;
Arch_FindLib(gn, &s->searchPath);
} else {
gn->suffix = NULL;
@@ -1919,34 +1846,24 @@ SuffFindDeps(GNode *gn, Lst slst)
}
/*-
- *-----------------------------------------------------------------------
- * Suff_SetNull --
- * Define which suffix is the null suffix.
- *
- * Side Effects:
- * 'suffNull' is altered.
- *
* Notes:
- * Need to handle the changing of the null suffix gracefully so the
- * old transformation rules don't just go away.
- *-----------------------------------------------------------------------
*/
void
-Suff_SetNull(const char *name)
+Suff_SetNulli(const char *name, const char *end)
{
Suff *s;
- LstNode ln;
- ln = suff_find_by_name(name);
- if (ln != NULL) {
- s = (Suff *)Lst_Datum(ln);
- if (suffNull != NULL) {
- suffNull->flags &= ~SUFF_NULL;
- }
+ s= find_suffi(name, end);
+ if (s != NULL) {
+ /* pass the pumpkin */
+ suffNull->flags &= ~SUFF_NULL;
s->flags |= SUFF_NULL;
/*
* XXX: Here's where the transformation mangling would take
* place
+ * we would need to handle the changing of the null suffix
+ * gracefully so the old transformation rules don't just go
+ * away.
*/
suffNull = s;
} else {
@@ -1967,30 +1884,22 @@ Suff_SetNull(const char *name)
void
Suff_Init(void)
{
- Static_Lst_Init(&sufflist);
-#ifdef CLEANUP
- Static_Lst_Init(&suffClean);
-#endif
Static_Lst_Init(&srclist);
- Static_Lst_Init(&transforms);
+ ohash_init(&transforms, 4, &gnode_info);
- sNum = 0;
/*
* Create null suffix for single-suffix rules (POSIX). The thing doesn't
* actually go on the suffix list or everyone will think that's its
* suffix.
*/
- emptySuff = suffNull = emalloc(sizeof(Suff));
-
- suffNull->name = estrdup("");
- suffNull->nameLen = 0;
- Lst_Init(&suffNull->searchPath);
- Dir_Concat(&suffNull->searchPath, defaultPath);
- Lst_Init(&suffNull->children);
- Lst_Init(&suffNull->parents);
- Lst_Init(&suffNull->ref);
- suffNull->sNum = sNum++;
- suffNull->flags = SUFF_NULL;
+ emptySuff = new_suffix("");
+ emptySuff->flags |= SUFF_NULL;
+ make_suffix_known(emptySuff);
+ Dir_Concat(&emptySuff->searchPath, defaultPath);
+ ohash_init(&suffixes, 4, &suff_info);
+ sNum = 0;
+ clear_suffixes();
+ special_path_hack();
}
@@ -2009,19 +1918,19 @@ Suff_Init(void)
void
Suff_End(void)
{
- Lst_Destroy(&sufflist, SuffFree);
- Lst_Destroy(&suffClean, SuffFree);
- if (suffNull)
- SuffFree(suffNull);
+ free_hash(&suffixes);
+ if (emptySuff)
+ SuffFree(emptySuff);
Lst_Destroy(&srclist, NOFREE);
- Lst_Destroy(&transforms, NOFREE);
+ ohash_delete(&transforms):
}
#endif
/********************* DEBUGGING FUNCTIONS **********************/
-static void SuffPrintName(void *s)
+static void
+SuffPrintName(void *s)
{
printf("%s ", ((Suff *)s)->name);
}
@@ -2068,10 +1977,8 @@ SuffPrintSuff(void *sp)
}
static void
-SuffPrintTrans(void *tp)
+SuffPrintTrans(GNode *t)
{
- GNode *t = (GNode *)tp;
-
printf("%-16s: ", t->name);
Targ_PrintType(t->type);
fputc('\n', stdout);
@@ -2082,11 +1989,20 @@ SuffPrintTrans(void *tp)
void
Suff_PrintAll(void)
{
+ Suff *s;
+ GNode *gn;
+ unsigned int i;
+
printf("#*** Suffixes:\n");
- Lst_Every(&sufflist, SuffPrintSuff);
+
+ for (s = ohash_first(&suffixes, &i); s != NULL;
+ s = ohash_next(&suffixes, &i))
+ SuffPrintSuff(s);
printf("#*** Transformations:\n");
- Lst_Every(&transforms, SuffPrintTrans);
+ for (gn = ohash_first(&transforms, &i); gn != NULL;
+ gn = ohash_next(&transforms, &i))
+ SuffPrintTrans(gn);
}
#ifdef DEBUG_SRC
diff --git a/usr.bin/make/suff.h b/usr.bin/make/suff.h
index 977b839a0c1..fd6a6d19873 100644
--- a/usr.bin/make/suff.h
+++ b/usr.bin/make/suff.h
@@ -1,7 +1,7 @@
#ifndef SUFF_H
#define SUFF_H
/* $OpenPackages$ */
-/* $OpenBSD: suff.h,v 1.2 2004/05/05 09:10:48 espie Exp $ */
+/* $OpenBSD: suff.h,v 1.3 2007/09/17 12:42:09 espie Exp $ */
/*
* Copyright (c) 2001 Marc Espie.
@@ -29,17 +29,16 @@
*/
extern void Suff_ClearSuffixes(void);
-extern bool Suff_IsTransform(const char *);
-extern GNode *Suff_AddTransform(const char *);
-extern void Suff_EndTransform(void *);
-extern void Suff_AddSuffix(const char *);
-extern Lst Suff_GetPath(const char *);
-extern void Suff_DoPaths(void);
-extern void Suff_AddInclude(const char *);
-extern void Suff_AddLib(const char *);
+extern GNode *Suff_ParseAsTransform(const char *, const char *);
+struct Suff_;
+extern void Suff_AddSuffixi(const char *, const char *);
+extern void Suff_AddIncludei(const char *, const char *);
+extern void Suff_AddLibi(const char *, const char *);
extern void Suff_FindDeps(GNode *);
-extern void Suff_SetNull(const char *);
+extern void Suff_SetNulli(const char *, const char *);
extern void Suff_Init(void);
+extern void process_suffixes_after_makefile_is_read(void);
+extern Lst find_suffix_path(GNode *);
#ifdef CLEANUP
extern void Suff_End(void);
#else
diff --git a/usr.bin/make/targ.c b/usr.bin/make/targ.c
index 588c1add13b..cb3ce35c0bc 100644
--- a/usr.bin/make/targ.c
+++ b/usr.bin/make/targ.c
@@ -1,5 +1,5 @@
/* $OpenPackages$ */
-/* $OpenBSD: targ.c,v 1.45 2007/09/17 09:28:36 espie Exp $ */
+/* $OpenBSD: targ.c,v 1.46 2007/09/17 12:42:09 espie Exp $ */
/* $NetBSD: targ.c,v 1.11 1997/02/20 16:51:50 christos Exp $ */
/*
@@ -115,14 +115,15 @@
#include "extern.h"
#include "timestamp.h"
#include "lst.h"
+#include "node_int.h"
+#include "nodehashconsts.h"
#ifdef CLEANUP
#include <stdlib.h>
#endif
static struct ohash targets; /* a hash table of same */
-static struct ohash_info gnode_info = {
- offsetof(GNode, name),
- NULL, hash_alloc, hash_free, element_alloc
+struct ohash_info gnode_info = {
+ offsetof(GNode, name), NULL, hash_alloc, hash_free, element_alloc
};
static void TargPrintOnlySrc(GNode *);
@@ -133,15 +134,8 @@ static LIST allTargets;
static void TargFreeGN(void *);
#endif
-/*-
- *-----------------------------------------------------------------------
- * Targ_Init --
- * Initialize this module
- *
- * Side Effects:
- * The targets hash table is initialized
- *-----------------------------------------------------------------------
- */
+GNode *begin_node, *end_node, *interrupt_node, *DEFAULT;
+
void
Targ_Init(void)
{
@@ -150,17 +144,17 @@ Targ_Init(void)
#ifdef CLEANUP
Lst_Init(&allTargets);
#endif
+ begin_node = Targ_FindConstantNode(NODE_BEGIN, TARG_CREATE);
+ begin_node->type |= OP_DUMMY | OP_NOTMAIN | OP_NODEFAULT;
+ end_node = Targ_FindConstantNode(NODE_END, TARG_CREATE);
+ end_node->type |= OP_DUMMY | OP_NOTMAIN | OP_NODEFAULT;
+ interrupt_node = Targ_FindConstantNode(NODE_INTERRUPT, TARG_CREATE);
+ interrupt_node->type |= OP_DUMMY | OP_NOTMAIN | OP_NODEFAULT;
+ DEFAULT = Targ_FindConstantNode(NODE_DEFAULT, TARG_CREATE);
+ DEFAULT->type |= OP_DUMMY | OP_NOTMAIN| OP_TRANSFORM | OP_NODEFAULT;
+
}
-/*-
- *-----------------------------------------------------------------------
- * Targ_End --
- * Finalize this module
- *
- * Side Effects:
- * All lists and gnodes are cleared
- *-----------------------------------------------------------------------
- */
#ifdef CLEANUP
void
Targ_End(void)
@@ -170,37 +164,24 @@ Targ_End(void)
}
#endif
-/*-
- *-----------------------------------------------------------------------
- * Targ_NewGNi --
- * 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 effect:
- * add targets to list of all targets if CLEANUP
- *-----------------------------------------------------------------------
- */
GNode *
-Targ_NewGNi(const char *name, /* the name to stick in the new node */
- const char *ename)
+Targ_NewGNi(const char *name, const char *ename)
{
GNode *gn;
gn = ohash_create_entry(&gnode_info, name, &ename);
gn->path = NULL;
- if (name[0] == '-' && name[1] == 'l') {
+ if (name[0] == '-' && name[1] == 'l')
gn->type = OP_LIB;
- } else {
+ else
gn->type = 0;
- }
- gn->unmade = 0;
- gn->make = false;
- gn->made = UNMADE;
+
+ gn->special = SPECIAL_NONE;
+ gn->unmade = 0;
+ gn->make = false;
+ gn->made = UNMADE;
gn->childMade = false;
- gn->order = 0;
+ gn->order = 0;
ts_set_out_of_date(gn->mtime);
ts_set_out_of_date(gn->cmtime);
Lst_Init(&gn->iParents);
@@ -226,12 +207,6 @@ Targ_NewGNi(const char *name, /* the name to stick in the new node */
}
#ifdef CLEANUP
-/*-
- *-----------------------------------------------------------------------
- * TargFreeGN --
- * Destroy a GNode
- *-----------------------------------------------------------------------
- */
static void
TargFreeGN(void *gnp)
{
@@ -250,30 +225,22 @@ TargFreeGN(void *gnp)
}
#endif
+GNode *
+Targ_FindNodei(const char *name, const char *ename, int flags)
+{
+ uint32_t hv;
+
+ hv = ohash_interval(name, &ename);
+ return Targ_FindNodeih(name, ename, hv, flags);
+}
-/*-
- *-----------------------------------------------------------------------
- * Targ_FindNodei --
- * 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 NULL if
- * flags was TARG_NOCREATE or the newly created and initialized node
- * if flags was TARG_CREATE
- *
- * Side Effects:
- * Sometimes a node is created and added to the list
- *-----------------------------------------------------------------------
- */
GNode *
-Targ_FindNodei(const char *name, const char *ename,
- int flags) /* flags governing events when target not
- * found */
+Targ_FindNodeih(const char *name, const char *ename, uint32_t hv, int flags)
{
- GNode *gn; /* node in that element */
+ GNode *gn;
unsigned int slot;
- slot = ohash_qlookupi(&targets, name, &ename);
+ slot = ohash_lookup_interval(&targets, name, ename, hv);
gn = ohash_find(&targets, slot);
@@ -285,25 +252,11 @@ Targ_FindNodei(const char *name, const char *ename,
return gn;
}
-/*-
- *-----------------------------------------------------------------------
- * Targ_FindList --
- * Make a complete list of GNodes from the given list of names
- *
- * Side Effects:
- * Nodes will be created for all names in names which do not yet have graph
- * nodes.
- *
- * A complete list of graph nodes corresponding to all instances of all
- * the names in names is added to nodes.
- * -----------------------------------------------------------------------
- */
void
-Targ_FindList(Lst nodes, /* result list */
- Lst names) /* list of names to find */
+Targ_FindList(Lst nodes, Lst names)
{
- LstNode ln; /* name list element */
- GNode *gn; /* node in tLn */
+ LstNode ln;
+ GNode *gn;
char *name;
for (ln = Lst_First(names); ln != NULL; ln = Lst_Adv(ln)) {
@@ -345,25 +298,6 @@ Targ_Precious(GNode *gn)
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.
- *
- * Side Effects:
- * "mainTarg" is set to the main target's node.
- *-----------------------------------------------------------------------
- */
-void
-Targ_SetMain(GNode *gn)
-{
- mainTarg = gn;
-}
-
static void
TargPrintName(void *gnp)
{
@@ -378,25 +312,13 @@ Targ_PrintCmd(void *cmd)
printf("\t%s\n", (char *)cmd);
}
-/*-
- *-----------------------------------------------------------------------
- * Targ_PrintType --
- * Print out a type field giving only those attributes the user can
- * set.
- *-----------------------------------------------------------------------
- */
void
Targ_PrintType(int type)
{
int tbit;
-#define PRINTBIT(attr) case CONCAT(OP_,attr): \
- printf("." #attr " "); \
- break
-#define PRINTDBIT(attr) case CONCAT(OP_,attr): \
- if (DEBUG(TARG)) \
- printf("." #attr " "); \
- break
+#define PRINTBIT(attr) case CONCAT(OP_,attr): printf("." #attr " "); break
+#define PRINTDBIT(attr) case CONCAT(OP_,attr): if (DEBUG(TARG)) printf("." #attr " "); break
type &= ~OP_OPMASK;
@@ -423,7 +345,7 @@ Targ_PrintType(int type)
break;
PRINTDBIT(ARCHV);
}
- }
+ }
}
static void
@@ -432,29 +354,22 @@ TargPrintNode(GNode *gn, int pass)
if (OP_NOP(gn->type))
return;
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");
- }
+ printf("# %d unmade children\n", gn->unmade);
if (! (gn->type & (OP_JOIN|OP_USE|OP_EXEC))) {
if (!is_out_of_date(gn->mtime)) {
printf("# last modified %s: %s\n",
- time_to_string(gn->mtime),
- (gn->made == UNMADE ? "unmade" :
- (gn->made == MADE ? "made" :
- (gn->made == UPTODATE ? "up-to-date" :
- "error when made"))));
+ time_to_string(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"))));
+ (gn->made == MADE ? "made" :
+ (gn->made == UPTODATE ? "up-to-date" :
+ (gn->made == ERROR ? "error when made" :
+ "aborted"))));
} else {
printf("# unmade\n");
}
@@ -516,8 +431,12 @@ Targ_PrintGraph(int pass) /* Which pass this is. 1 => no processing
printf("#\n# Files that are only sources:\n");
for (gn = ohash_first(&targets, &i); gn != NULL;
gn = ohash_next(&targets, &i))
- TargPrintOnlySrc(gn);
+ TargPrintOnlySrc(gn);
Var_Dump();
printf("\n");
+#ifdef DEBUG_DIRECTORY_CACHE
+ Dir_PrintDirectories();
+ printf("\n");
+#endif
Suff_PrintAll();
}
diff --git a/usr.bin/make/targ.h b/usr.bin/make/targ.h
index 86d2bb7ed0e..312f2d69939 100644
--- a/usr.bin/make/targ.h
+++ b/usr.bin/make/targ.h
@@ -1,7 +1,7 @@
#ifndef TARG_H
#define TARG_H
/* $OpenPackages$ */
-/* $OpenBSD: targ.h,v 1.2 2007/09/16 12:09:36 espie Exp $ */
+/* $OpenBSD: targ.h,v 1.3 2007/09/17 12:42:09 espie Exp $ */
/*
* Copyright (c) 2001 Marc Espie.
@@ -51,14 +51,32 @@ extern GNode *Targ_NewGNi(const char *, const char *);
#define Targ_NewGN(n) Targ_NewGNi(n, NULL);
extern GNode *Targ_FindNodei(const char *, const char *, int);
#define Targ_FindNode(n, i) Targ_FindNodei(n, NULL, i)
+
+
+
+/* set of helpers for constant nodes */
+extern GNode *Targ_FindNodeih(const char *, const char *, uint32_t, int);
+
+extern inline GNode *
+Targ_FindNodeh(const char *, size_t, uint32_t, int);
+extern inline GNode *
+Targ_FindNodeh(const char *name, size_t n, uint32_t hv, int flags)
+{
+ return Targ_FindNodeih(name, name + n - 1, hv, flags);
+}
+#define Targ_FindConstantNode(n, f) Targ_FindNodeh(n, sizeof(n), K_##n, f)
+
extern void Targ_FindList(Lst, Lst);
extern bool Targ_Ignore(GNode *);
extern bool Targ_Silent(GNode *);
extern bool Targ_Precious(GNode *);
-extern void Targ_SetMain(GNode *);
extern void Targ_PrintCmd(void *);
extern void Targ_PrintType(int);
extern void Targ_PrintGraph(int);
+extern GNode *begin_node, *end_node, *interrupt_node, *DEFAULT;
+struct ohash_info;
+
+extern struct ohash_info gnode_info;
#endif