summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc Espie <espie@cvs.openbsd.org>2007-09-16 10:39:08 +0000
committerMarc Espie <espie@cvs.openbsd.org>2007-09-16 10:39:08 +0000
commit92619b2927c391fb7e94d552e365b85540a5c4c0 (patch)
treeb727578db4f88a0e10abd1ba59e091bcdbc2696f
parent2cd743898ff20f9b51a56a61f2005ff0a77a263e (diff)
first step towards sanity: take the functions common to parallel/not parallel
make outside of make.c and job.c, and create an engine.c file to hold them.
-rw-r--r--usr.bin/make/Makefile4
-rw-r--r--usr.bin/make/compat.c4
-rw-r--r--usr.bin/make/engine.c511
-rw-r--r--usr.bin/make/engine.h68
-rw-r--r--usr.bin/make/job.c139
-rw-r--r--usr.bin/make/make.c329
6 files changed, 588 insertions, 467 deletions
diff --git a/usr.bin/make/Makefile b/usr.bin/make/Makefile
index 9fb976b96a2..afc59ae3895 100644
--- a/usr.bin/make/Makefile
+++ b/usr.bin/make/Makefile
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.45 2007/09/16 10:20:17 espie Exp $
+# $OpenBSD: Makefile,v 1.46 2007/09/16 10:39:07 espie Exp $
PROG= make
CFLAGS+= -I${.OBJDIR} -I${.CURDIR}
@@ -16,7 +16,7 @@ CFLAGS+=${CDEFS}
HOSTCFLAGS+=${CDEFS}
SRCS= arch.c buf.c cmd_exec.c compat.c cond.c dir.c direxpand.c \
- error.c for.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
diff --git a/usr.bin/make/compat.c b/usr.bin/make/compat.c
index 8a20b3d54d9..f0a33bd2a5b 100644
--- a/usr.bin/make/compat.c
+++ b/usr.bin/make/compat.c
@@ -1,5 +1,5 @@
/* $OpenPackages$ */
-/* $OpenBSD: compat.c,v 1.54 2007/09/16 09:46:14 espie Exp $ */
+/* $OpenBSD: compat.c,v 1.55 2007/09/16 10:39:07 espie Exp $ */
/* $NetBSD: compat.c,v 1.14 1996/11/06 17:59:01 christos Exp $ */
/*
@@ -51,7 +51,7 @@
#include "config.h"
#include "defines.h"
#include "dir.h"
-#include "job.h"
+#include "engine.h"
#include "compat.h"
#include "suff.h"
#include "var.h"
diff --git a/usr.bin/make/engine.c b/usr.bin/make/engine.c
new file mode 100644
index 00000000000..a2ff9aff252
--- /dev/null
+++ b/usr.bin/make/engine.c
@@ -0,0 +1,511 @@
+/* $OpenBSD: engine.c,v 1.1 2007/09/16 10:39:07 espie Exp $ */
+/*
+ * Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
+ * Copyright (c) 1988, 1989 by Adam de Boor
+ * Copyright (c) 1989 by Berkeley Softworks
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Adam de Boor.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <limits.h>
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include "config.h"
+#include "defines.h"
+#include "dir.h"
+#include "engine.h"
+#include "arch.h"
+#include "gnode.h"
+#include "targ.h"
+#include "var.h"
+#include "extern.h"
+#include "lst.h"
+#include "timestamp.h"
+#include "make.h"
+#include "main.h"
+
+static void MakeTimeStamp(void *, void *);
+static void MakeAddAllSrc(void *, void *);
+
+/*-
+ *-----------------------------------------------------------------------
+ * 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, /* The target whose commands need
+ * verifying */
+ void (*abortProc)(char *, ...)) /* Function to abort with message */
+{
+ if (OP_NOP(gn->type) && Lst_IsEmpty(&gn->commands) &&
+ (gn->type & OP_LIB) == 0) {
+ /*
+ * No commands. Look for .DEFAULT rule from which we might infer
+ * commands
+ */
+ if (DEFAULT != NULL && !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. If
+ * a .DEFAULT was given, we substitute its commands for gn's
+ * commands and set the IMPSRC variable to be the target's name
+ * The DEFAULT node acts like a transformation rule, in that
+ * gn also inherits any attributes or sources attached to
+ * .DEFAULT itself.
+ */
+ Make_HandleUse(DEFAULT, gn);
+ Varq_Set(IMPSRC_INDEX, Varq_Value(TARGET_INDEX, gn), gn);
+ } else if (is_out_of_date(Dir_MTime(gn))) {
+ /*
+ * The node wasn't the target of an operator we have no .DEFAULT
+ * rule to go on and the target doesn't already exist. There's
+ * nothing more we can do for this branch. If the -k flag wasn't
+ * given, we stop in our tracks, otherwise we just don't update
+ * this node's parents so they never get examined.
+ */
+ static const char msg[] = "make: don't know how to make";
+
+ if (gn->type & OP_OPTIONAL) {
+ (void)fprintf(stdout, "%s %s(ignored)\n", msg, gn->name);
+ (void)fflush(stdout);
+ } else if (keepgoing) {
+ (void)fprintf(stdout, "%s %s(continuing)\n", msg, gn->name);
+ (void)fflush(stdout);
+ return false;
+ } else {
+ (*abortProc)("%s %s. Stop in %s.", msg, gn->name,
+ Var_Value(".CURDIR"));
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+/*-
+ *-----------------------------------------------------------------------
+ * 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, /* the node of the file to touch */
+ bool silent) /* true if should not print messages */
+{
+ int streamID; /* ID of stream opened to do the touch */
+
+ if (gn->type & (OP_JOIN|OP_USE|OP_EXEC|OP_OPTIONAL)) {
+ /*
+ * .JOIN, .USE, .ZEROTIME and .OPTIONAL targets are "virtual" targets
+ * and, as such, shouldn't really be created.
+ */
+ return;
+ }
+
+ if (!silent) {
+ (void)fprintf(stdout, "touch %s\n", gn->name);
+ (void)fflush(stdout);
+ }
+
+ if (noExecute) {
+ return;
+ }
+
+ if (gn->type & OP_ARCHV) {
+ Arch_Touch(gn);
+ } else if (gn->type & OP_LIB) {
+ Arch_TouchLib(gn);
+ } else {
+ const char *file = gn->path != NULL ? gn->path : gn->name;
+
+ if (set_times(file) == -1){
+ streamID = open(file, O_RDWR | O_CREAT, 0666);
+
+ if (streamID >= 0) {
+ char c;
+
+ /*
+ * Read and write a byte to the file to change the
+ * modification time, then close the file.
+ */
+ if (read(streamID, &c, 1) == 1) {
+ (void)lseek(streamID, 0, SEEK_SET);
+ (void)write(streamID, &c, 1);
+ }
+
+ (void)close(streamID);
+ } else {
+ (void)fprintf(stdout, "*** 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 *pgn, /* the current parent */
+ GNode *cgn) /* the child we've just examined */
+{
+ if (is_strictly_before(pgn->cmtime, cgn->mtime))
+ pgn->cmtime = cgn->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 */
+ GNode *pgn) /* The target of the .USE node */
+{
+ GNode *gn; /* A child of the .USE node */
+ LstNode ln; /* An element in the children list */
+
+ if (cgn->type & (OP_USE|OP_TRANSFORM)) {
+ if ((cgn->type & OP_USE) || Lst_IsEmpty(&pgn->commands)) {
+ /* .USE or transformation and target has no commands -- append
+ * the child's commands to the parent. */
+ Lst_Concat(&pgn->commands, &cgn->commands);
+ }
+
+ for (ln = Lst_First(&cgn->children); ln != NULL; ln = Lst_Adv(ln)) {
+ gn = (GNode *)Lst_Datum(ln);
+
+ if (Lst_AddNew(&pgn->children, gn)) {
+ Lst_AtEnd(&gn->parents, pgn);
+ pgn->unmade += 1;
+ }
+ }
+
+ pgn->type |= cgn->type & ~(OP_OPMASK|OP_USE|OP_TRANSFORM);
+
+ /*
+ * This child node is now "made", so we decrement the count of
+ * unmade children in the parent... We also remove the child
+ * from the parent's list to accurately reflect the number of decent
+ * children the parent has. This is used by Make_Run to decide
+ * whether to queue the parent or examine its children...
+ */
+ if (cgn->type & OP_USE) {
+ pgn->unmade--;
+ }
+ }
+}
+
+/*-
+ *-----------------------------------------------------------------------
+ * 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 */
+{
+ GNode *cgn = (GNode *)cgnp;
+ GNode *pgn = (GNode *)pgnp;
+ if ((cgn->type & (OP_EXEC|OP_USE|OP_INVISIBLE)) == 0) {
+ const char *child;
+
+ if (OP_NOP(cgn->type) ||
+ (child = Varq_Value(TARGET_INDEX, cgn)) == NULL) {
+ /*
+ * this node is only source; use the specific pathname for it
+ */
+ child = cgn->path != NULL ? cgn->path : cgn->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))
+ {
+ /*
+ * 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.
+ *
+ */
+ Varq_Append(OODATE_INDEX, child, pgn);
+ }
+ }
+}
+
+/*-
+ *-----------------------------------------------------------------------
+ * 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)
+{
+ Lst_ForEach(&gn->children, MakeAddAllSrc, gn);
+
+ if (Varq_Value(OODATE_INDEX, gn) == NULL)
+ Varq_Set(OODATE_INDEX, "", gn);
+ if (Varq_Value(ALLSRC_INDEX, gn) == NULL)
+ Varq_Set(ALLSRC_INDEX, "", gn);
+
+ if (gn->type & OP_JOIN)
+ Varq_Set(TARGET_INDEX, Varq_Value(ALLSRC_INDEX, gn), 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 */
+{
+ Make_TimeStamp((GNode *)pgn, (GNode *)cgn);
+}
+
+/*-
+ *-----------------------------------------------------------------------
+ * 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 */
+{
+ bool oodate;
+
+ /*
+ * Certain types of targets needn't even be sought as their datedness
+ * doesn't depend on their modification time...
+ */
+ if ((gn->type & (OP_JOIN|OP_USE|OP_EXEC)) == 0) {
+ (void)Dir_MTime(gn);
+ if (DEBUG(MAKE)) {
+ if (!is_out_of_date(gn->mtime)) {
+ printf("modified %s...", Targ_FmtTime(gn->mtime));
+ } else {
+ printf("non-existent...");
+ }
+ }
+ }
+
+ /*
+ * A target is remade in one of the following circumstances:
+ * its modification time is smaller than that of its youngest child
+ * and it would actually be run (has commands or type OP_NOP)
+ * it's the object of a force operator
+ * it has no children, was on the lhs of an operator and doesn't exist
+ * already.
+ *
+ * Libraries are only considered out-of-date if the archive module says
+ * they are.
+ *
+ * These weird rules are brought to you by Backward-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)) {
+ 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
+ */
+
+ oodate = Arch_LibOODate(gn) ||
+ (is_out_of_date(gn->cmtime) && (gn->type & OP_DOUBLEDEP));
+ } else if (gn->type & OP_JOIN) {
+ /*
+ * A target with the .JOIN attribute is only considered
+ * out-of-date if any of its children was out-of-date.
+ */
+ if (DEBUG(MAKE)) {
+ printf(".JOIN node...");
+ }
+ oodate = gn->childMade;
+ } else if (gn->type & (OP_FORCE|OP_EXEC|OP_PHONY)) {
+ /*
+ * A node which is the object of the force (!) operator or which has
+ * the .EXEC attribute is always considered out-of-date.
+ */
+ if (DEBUG(MAKE)) {
+ if (gn->type & OP_FORCE) {
+ printf("! operator...");
+ } else if (gn->type & OP_PHONY) {
+ printf(".PHONY node...");
+ } 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->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.
+ */
+ if (DEBUG(MAKE)) {
+ if (is_strictly_before(gn->mtime, gn->cmtime)) {
+ printf("modified before source...");
+ } else if (is_out_of_date(gn->mtime)) {
+ printf("non-existent and no sources...");
+ } else {
+ printf(":: operator and no sources...");
+ }
+ }
+ oodate = true;
+ } else {
+#if 0
+ /* WHY? */
+ if (DEBUG(MAKE)) {
+ printf("source %smade...", gn->childMade ? "" : "not ");
+ }
+ oodate = gn->childMade;
+#else
+ oodate = false;
+#endif /* 0 */
+ }
+
+ /*
+ * If the target isn't out-of-date, the parents need to know its
+ * modification time. Note that targets that appear to be out-of-date
+ * but aren't, because they have no commands and aren't of type OP_NOP,
+ * have their mtime stay below their children's mtime to keep parents from
+ * thinking they're out-of-date.
+ */
+ if (!oodate)
+ Lst_ForEach(&gn->parents, MakeTimeStamp, gn);
+
+ return oodate;
+}
+
diff --git a/usr.bin/make/engine.h b/usr.bin/make/engine.h
new file mode 100644
index 00000000000..dc53d5dae97
--- /dev/null
+++ b/usr.bin/make/engine.h
@@ -0,0 +1,68 @@
+#ifndef ENGINE_H
+#define ENGINE_H
+/* $OpenBSD: engine.h,v 1.1 2007/09/16 10:39:07 espie Exp $ */
+
+/*
+ * Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
+ * Copyright (c) 1988, 1989 by Adam de Boor
+ * Copyright (c) 1989 by Berkeley Softworks
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Adam de Boor.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)job.h 8.1 (Berkeley) 6/6/93
+ */
+
+/* ok = Job_CheckCommands(node, abort);
+ * verify the integrity of a node's commands, pulling stuff off
+ * .DEFAULT and other places if necessary.
+ */
+extern bool Job_CheckCommands(GNode *, void (*abortProc)(char *, ...));
+/* Job_Touch(node, besilent);
+ * touch the path corresponding to a node or update the corresponding
+ * archive object.
+ */
+extern void Job_Touch(GNode *, bool);
+/* Make_TimeStamp(parent, child);
+ * ensure parent is at least as recent as child.
+ */
+extern void Make_TimeStamp(GNode *, GNode *);
+/* Make_HandleUse(user_node, usee_node);
+ * let user_node inherit the commands from usee_node
+ */
+extern void Make_HandleUse(GNode *, GNode *);
+
+/* old = Make_OODate(node);
+ * check if a given node is out-of-date.
+ */
+extern bool Make_OODate(GNode *);
+/* Make_DoAllVar(node);
+ * fill all dynamic variables for a node.
+ */
+extern void Make_DoAllVar(GNode *);
+#endif
diff --git a/usr.bin/make/job.c b/usr.bin/make/job.c
index 618f2a5c88b..91a54dc553b 100644
--- a/usr.bin/make/job.c
+++ b/usr.bin/make/job.c
@@ -1,5 +1,5 @@
/* $OpenPackages$ */
-/* $OpenBSD: job.c,v 1.62 2007/06/12 16:33:27 cnst Exp $ */
+/* $OpenBSD: job.c,v 1.63 2007/09/16 10:39:07 espie Exp $ */
/* $NetBSD: job.c,v 1.16 1996/11/06 17:59:08 christos Exp $ */
/*
@@ -99,7 +99,6 @@
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
-#include <limits.h>
#include <signal.h>
#include <stddef.h>
#include <stdio.h>
@@ -108,21 +107,18 @@
#include <unistd.h>
#include "config.h"
#include "defines.h"
-#include "dir.h"
#include "job.h"
+#include "engine.h"
#include "pathnames.h"
-#include "arch.h"
#include "var.h"
#include "targ.h"
#include "error.h"
-#include "str.h"
#include "lst.h"
#include "extern.h"
#include "gnode.h"
#include "memory.h"
#include "make.h"
-#include "timestamp.h"
-#include "main.h"
+#include "str.h"
#define TMPPAT "/tmp/makeXXXXXXXXXX"
@@ -1112,135 +1108,6 @@ JobFinish(Job *job, /* job to finish */
/*-
*-----------------------------------------------------------------------
- * 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, /* the node of the file to touch */
- bool silent) /* true if should not print messages */
-{
- int streamID; /* ID of stream opened to do the touch */
-
- if (gn->type & (OP_JOIN|OP_USE|OP_EXEC|OP_OPTIONAL)) {
- /*
- * .JOIN, .USE, .ZEROTIME and .OPTIONAL targets are "virtual" targets
- * and, as such, shouldn't really be created.
- */
- return;
- }
-
- if (!silent) {
- (void)fprintf(stdout, "touch %s\n", gn->name);
- (void)fflush(stdout);
- }
-
- if (noExecute) {
- return;
- }
-
- if (gn->type & OP_ARCHV) {
- Arch_Touch(gn);
- } else if (gn->type & OP_LIB) {
- Arch_TouchLib(gn);
- } else {
- const char *file = gn->path != NULL ? gn->path : gn->name;
-
- if (set_times(file) == -1){
- streamID = open(file, O_RDWR | O_CREAT, 0666);
-
- if (streamID >= 0) {
- char c;
-
- /*
- * Read and write a byte to the file to change the
- * modification time, then close the file.
- */
- if (read(streamID, &c, 1) == 1) {
- (void)lseek(streamID, 0, SEEK_SET);
- (void)write(streamID, &c, 1);
- }
-
- (void)close(streamID);
- } else {
- (void)fprintf(stdout, "*** couldn't touch %s: %s",
- file, strerror(errno));
- (void)fflush(stdout);
- }
- }
- }
-}
-
-/*-
- *-----------------------------------------------------------------------
- * 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, /* The target whose commands need
- * verifying */
- void (*abortProc)(char *, ...)) /* Function to abort with message */
-{
- if (OP_NOP(gn->type) && Lst_IsEmpty(&gn->commands) &&
- (gn->type & OP_LIB) == 0) {
- /*
- * No commands. Look for .DEFAULT rule from which we might infer
- * commands
- */
- if (DEFAULT != NULL && !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. If
- * a .DEFAULT was given, we substitute its commands for gn's
- * commands and set the IMPSRC variable to be the target's name
- * The DEFAULT node acts like a transformation rule, in that
- * gn also inherits any attributes or sources attached to
- * .DEFAULT itself.
- */
- Make_HandleUse(DEFAULT, gn);
- Varq_Set(IMPSRC_INDEX, Varq_Value(TARGET_INDEX, gn), gn);
- } else if (is_out_of_date(Dir_MTime(gn))) {
- /*
- * The node wasn't the target of an operator we have no .DEFAULT
- * rule to go on and the target doesn't already exist. There's
- * nothing more we can do for this branch. If the -k flag wasn't
- * given, we stop in our tracks, otherwise we just don't update
- * this node's parents so they never get examined.
- */
- static const char msg[] = "make: don't know how to make";
-
- if (gn->type & OP_OPTIONAL) {
- (void)fprintf(stdout, "%s %s(ignored)\n", msg, gn->name);
- (void)fflush(stdout);
- } else if (keepgoing) {
- (void)fprintf(stdout, "%s %s(continuing)\n", msg, gn->name);
- (void)fflush(stdout);
- return false;
- } else {
- (*abortProc)("%s %s. Stop in %s.", msg, gn->name,
- Var_Value(".CURDIR"));
- return false;
- }
- }
- }
- return true;
-}
-
-/*-
- *-----------------------------------------------------------------------
* JobExec --
* Execute the shell for the given job. Called from JobStart and
* JobRestart.
diff --git a/usr.bin/make/make.c b/usr.bin/make/make.c
index 7bd82289f21..c097a816a6e 100644
--- a/usr.bin/make/make.c
+++ b/usr.bin/make/make.c
@@ -1,5 +1,5 @@
/* $OpenPackages$ */
-/* $OpenBSD: make.c,v 1.36 2007/09/16 09:46:14 espie Exp $ */
+/* $OpenBSD: make.c,v 1.37 2007/09/16 10:39:07 espie Exp $ */
/* $NetBSD: make.c,v 1.10 1996/11/06 17:59:15 christos Exp $ */
/*
@@ -75,7 +75,6 @@
#include "defines.h"
#include "dir.h"
#include "job.h"
-#include "arch.h"
#include "suff.h"
#include "var.h"
#include "targ.h"
@@ -84,6 +83,7 @@
#include "gnode.h"
#include "extern.h"
#include "timestamp.h"
+#include "engine.h"
#include "lst.h"
static LIST toBeMade; /* The current fringe of the graph. These
@@ -96,184 +96,11 @@ static int numNodes; /* Number of nodes to be processed. If this
* true, there's a cycle in the graph */
static void MakeAddChild(void *, void *);
-static void MakeAddAllSrc(void *, void *);
-static void MakeTimeStamp(void *, void *);
static void MakeHandleUse(void *, void *);
static bool MakeStartJobs(void);
static void MakePrintStatus(void *, void *);
/*-
*-----------------------------------------------------------------------
- * 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 *pgn, /* the current parent */
- GNode *cgn) /* the child we've just examined */
-{
- if (is_strictly_before(pgn->cmtime, cgn->mtime))
- pgn->cmtime = cgn->mtime;
-}
-
-/* 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 */
-{
- Make_TimeStamp((GNode *)pgn, (GNode *)cgn);
-}
-
-/*-
- *-----------------------------------------------------------------------
- * 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 */
-{
- bool oodate;
-
- /*
- * Certain types of targets needn't even be sought as their datedness
- * doesn't depend on their modification time...
- */
- if ((gn->type & (OP_JOIN|OP_USE|OP_EXEC)) == 0) {
- (void)Dir_MTime(gn);
- if (DEBUG(MAKE)) {
- if (!is_out_of_date(gn->mtime)) {
- printf("modified %s...", Targ_FmtTime(gn->mtime));
- } else {
- printf("non-existent...");
- }
- }
- }
-
- /*
- * A target is remade in one of the following circumstances:
- * its modification time is smaller than that of its youngest child
- * and it would actually be run (has commands or type OP_NOP)
- * it's the object of a force operator
- * it has no children, was on the lhs of an operator and doesn't exist
- * already.
- *
- * Libraries are only considered out-of-date if the archive module says
- * they are.
- *
- * These weird rules are brought to you by Backward-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)) {
- 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
- */
-
- oodate = Arch_LibOODate(gn) ||
- (is_out_of_date(gn->cmtime) && (gn->type & OP_DOUBLEDEP));
- } else if (gn->type & OP_JOIN) {
- /*
- * A target with the .JOIN attribute is only considered
- * out-of-date if any of its children was out-of-date.
- */
- if (DEBUG(MAKE)) {
- printf(".JOIN node...");
- }
- oodate = gn->childMade;
- } else if (gn->type & (OP_FORCE|OP_EXEC|OP_PHONY)) {
- /*
- * A node which is the object of the force (!) operator or which has
- * the .EXEC attribute is always considered out-of-date.
- */
- if (DEBUG(MAKE)) {
- if (gn->type & OP_FORCE) {
- printf("! operator...");
- } else if (gn->type & OP_PHONY) {
- printf(".PHONY node...");
- } 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->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.
- */
- if (DEBUG(MAKE)) {
- if (is_strictly_before(gn->mtime, gn->cmtime)) {
- printf("modified before source...");
- } else if (is_out_of_date(gn->mtime)) {
- printf("non-existent and no sources...");
- } else {
- printf(":: operator and no sources...");
- }
- }
- oodate = true;
- } else {
-#if 0
- /* WHY? */
- if (DEBUG(MAKE)) {
- printf("source %smade...", gn->childMade ? "" : "not ");
- }
- oodate = gn->childMade;
-#else
- oodate = false;
-#endif /* 0 */
- }
-
- /*
- * If the target isn't out-of-date, the parents need to know its
- * modification time. Note that targets that appear to be out-of-date
- * but aren't, because they have no commands and aren't of type OP_NOP,
- * have their mtime stay below their children's mtime to keep parents from
- * thinking they're out-of-date.
- */
- if (!oodate)
- Lst_ForEach(&gn->parents, MakeTimeStamp, gn);
-
- return oodate;
-}
-
-/*-
- *-----------------------------------------------------------------------
* MakeAddChild --
* Function used by Make_Run to add a child to the list l.
* It will only add the child if its make field is false.
@@ -294,64 +121,6 @@ MakeAddChild(
Lst_EnQueue(l, gn);
}
-/*-
- *-----------------------------------------------------------------------
- * 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 */
- GNode *pgn) /* The target of the .USE node */
-{
- GNode *gn; /* A child of the .USE node */
- LstNode ln; /* An element in the children list */
-
- if (cgn->type & (OP_USE|OP_TRANSFORM)) {
- if ((cgn->type & OP_USE) || Lst_IsEmpty(&pgn->commands)) {
- /* .USE or transformation and target has no commands -- append
- * the child's commands to the parent. */
- Lst_Concat(&pgn->commands, &cgn->commands);
- }
-
- for (ln = Lst_First(&cgn->children); ln != NULL; ln = Lst_Adv(ln)) {
- gn = (GNode *)Lst_Datum(ln);
-
- if (Lst_AddNew(&pgn->children, gn)) {
- Lst_AtEnd(&gn->parents, pgn);
- pgn->unmade += 1;
- }
- }
-
- pgn->type |= cgn->type & ~(OP_OPMASK|OP_USE|OP_TRANSFORM);
-
- /*
- * This child node is now "made", so we decrement the count of
- * unmade children in the parent... We also remove the child
- * from the parent's list to accurately reflect the number of decent
- * children the parent has. This is used by Make_Run to decide
- * whether to queue the parent or examine its children...
- */
- if (cgn->type & OP_USE) {
- pgn->unmade--;
- }
- }
-}
static void
MakeHandleUse(
void *pgn, /* the current parent */
@@ -485,100 +254,6 @@ Make_Update(GNode *cgn) /* the child node */
/*-
*-----------------------------------------------------------------------
- * 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 */
-{
- GNode *cgn = (GNode *)cgnp;
- GNode *pgn = (GNode *)pgnp;
- if ((cgn->type & (OP_EXEC|OP_USE|OP_INVISIBLE)) == 0) {
- const char *child;
-
- if (OP_NOP(cgn->type) ||
- (child = Varq_Value(TARGET_INDEX, cgn)) == NULL) {
- /*
- * this node is only source; use the specific pathname for it
- */
- child = cgn->path != NULL ? cgn->path : cgn->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))
- {
- /*
- * 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.
- *
- */
- Varq_Append(OODATE_INDEX, child, pgn);
- }
- }
-}
-
-/*-
- *-----------------------------------------------------------------------
- * 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)
-{
- Lst_ForEach(&gn->children, MakeAddAllSrc, gn);
-
- if (Varq_Value(OODATE_INDEX, gn) == NULL)
- Varq_Set(OODATE_INDEX, "", gn);
- if (Varq_Value(ALLSRC_INDEX, gn) == NULL)
- Varq_Set(ALLSRC_INDEX, "", gn);
-
- if (gn->type & OP_JOIN)
- Varq_Set(TARGET_INDEX, Varq_Value(ALLSRC_INDEX, gn), gn);
-}
-
-/*-
- *-----------------------------------------------------------------------
* MakeStartJobs --
* Start as many jobs as possible.
*