version 1.4, 1996/11/30 21:09:00 |
version 1.5, 1997/04/01 07:28:17 |
|
|
/* $OpenBSD$ */ |
/* $OpenBSD$ */ |
/* $NetBSD: make.c,v 1.10 1996/11/06 17:59:15 christos Exp $ */ |
/* $NetBSD: make.c,v 1.14 1997/03/28 22:31:21 christos Exp $ */ |
|
|
/* |
/* |
* Copyright (c) 1988, 1989, 1990, 1993 |
* Copyright (c) 1988, 1989, 1990, 1993 |
|
|
* |
* |
* Make_OODate Determine if a target is out-of-date. |
* Make_OODate Determine if a target is out-of-date. |
* |
* |
* Make_HandleUse See if a child is a .USE node for a parent |
* Make_HandleUse See if a child is a .USE node for a parent |
* and perform the .USE actions if so. |
* and perform the .USE actions if so. |
|
* |
|
* Make_ExpandUse Expand .USE nodes and return the new list of |
|
* targets. |
*/ |
*/ |
|
|
#include "make.h" |
#include "make.h" |
|
|
* TRUE, there's a cycle in the graph */ |
* TRUE, there's a cycle in the graph */ |
|
|
static int MakeAddChild __P((ClientData, ClientData)); |
static int MakeAddChild __P((ClientData, ClientData)); |
|
static int MakeFindChild __P((ClientData, ClientData)); |
static int MakeAddAllSrc __P((ClientData, ClientData)); |
static int MakeAddAllSrc __P((ClientData, ClientData)); |
static int MakeTimeStamp __P((ClientData, ClientData)); |
static int MakeTimeStamp __P((ClientData, ClientData)); |
static int MakeHandleUse __P((ClientData, ClientData)); |
static int MakeHandleUse __P((ClientData, ClientData)); |
|
|
ClientData pgn; /* the current parent */ |
ClientData pgn; /* the current parent */ |
ClientData cgn; /* the child we've just examined */ |
ClientData cgn; /* the child we've just examined */ |
{ |
{ |
return Make_TimeStamp((GNode *) pgn, (GNode *) cgn); |
return (Make_TimeStamp((GNode *) pgn, (GNode *) cgn)); |
} |
} |
|
|
/*- |
/*- |
|
|
{ |
{ |
GNode *gn = (GNode *) gnp; |
GNode *gn = (GNode *) gnp; |
Lst l = (Lst) lp; |
Lst l = (Lst) lp; |
|
|
if (!gn->make && !(gn->type & OP_USE)) { |
if (!gn->make && !(gn->type & OP_USE)) { |
(void)Lst_EnQueue (l, (ClientData)gn); |
(void)Lst_EnQueue (l, (ClientData)gn); |
} |
} |
return (0); |
return (0); |
} |
} |
|
|
|
/*- |
|
*----------------------------------------------------------------------- |
|
* MakeFindChild -- |
|
* Function used by Make_Run to find the pathname of a child |
|
* that was already made. |
|
* |
|
* Results: |
|
* Always returns 0 |
|
* |
|
* Side Effects: |
|
* The path and mtime of the node and the cmtime of the parent are |
|
* updated |
|
*----------------------------------------------------------------------- |
|
*/ |
|
static int |
|
MakeFindChild (gnp, pgnp) |
|
ClientData gnp; /* the node to find */ |
|
ClientData pgnp; |
|
{ |
|
GNode *gn = (GNode *) gnp; |
|
GNode *pgn = (GNode *) pgnp; |
|
|
|
(void) Dir_MTime(gn); |
|
if (pgn->cmtime < gn->mtime) |
|
pgn->cmtime = gn->mtime; |
|
gn->made = UPTODATE; |
|
|
|
return (0); |
|
} |
|
|
/*- |
/*- |
*----------------------------------------------------------------------- |
*----------------------------------------------------------------------- |
* Make_HandleUse -- |
* Make_HandleUse -- |
|
|
register GNode *cgn; /* The .USE node */ |
register GNode *cgn; /* The .USE node */ |
register GNode *pgn; /* The target of the .USE node */ |
register GNode *pgn; /* The target of the .USE node */ |
{ |
{ |
register GNode *gn; /* A child of the .USE node */ |
|
register LstNode ln; /* An element in the children list */ |
register LstNode ln; /* An element in the children list */ |
|
|
if (cgn->type & (OP_USE|OP_TRANSFORM)) { |
if (cgn->type & (OP_USE|OP_TRANSFORM)) { |
|
|
|
|
if (Lst_Open (cgn->children) == SUCCESS) { |
if (Lst_Open (cgn->children) == SUCCESS) { |
while ((ln = Lst_Next (cgn->children)) != NILLNODE) { |
while ((ln = Lst_Next (cgn->children)) != NILLNODE) { |
gn = (GNode *)Lst_Datum (ln); |
register GNode *tgn, *gn = (GNode *)Lst_Datum (ln); |
|
|
|
/* |
|
* Expand variables in the .USE node's name |
|
* and save the unexpanded form. |
|
* We don't need to do this for commands. |
|
* They get expanded properly when we execute. |
|
*/ |
|
if (gn->uname == NULL) { |
|
gn->uname = gn->name; |
|
} else { |
|
if (gn->name) |
|
free(gn->name); |
|
} |
|
gn->name = Var_Subst(NULL, gn->uname, pgn, FALSE); |
|
if (gn->name && gn->uname && strcmp(gn->name, gn->uname) != 0) { |
|
/* See if we have a target for this node. */ |
|
tgn = Targ_FindNode(gn->name, TARG_NOCREATE); |
|
if (tgn != NILGNODE) |
|
gn = tgn; |
|
} |
|
|
if (Lst_Member (pgn->children, gn) == NILLNODE) { |
if (Lst_Member (pgn->children, gn) == NILLNODE) { |
(void) Lst_AtEnd (pgn->children, gn); |
(void) Lst_AtEnd (pgn->children, gn); |
(void) Lst_AtEnd (gn->parents, pgn); |
(void) Lst_AtEnd (gn->parents, pgn); |
|
|
* children the parent has. This is used by Make_Run to decide |
* children the parent has. This is used by Make_Run to decide |
* whether to queue the parent or examine its children... |
* whether to queue the parent or examine its children... |
*/ |
*/ |
if (cgn->type & OP_USE) { |
if ((cgn->type & OP_USE) && |
pgn->unmade -= 1; |
(ln = Lst_Member (pgn->children, (ClientData) cgn)) != NILLNODE) { |
|
Lst_Remove(pgn->children, ln); |
|
pgn->unmade--; |
} |
} |
} |
} |
return (0); |
return (0); |
|
|
ClientData pgn; /* the current parent */ |
ClientData pgn; /* the current parent */ |
ClientData cgn; /* the child we've just examined */ |
ClientData cgn; /* the child we've just examined */ |
{ |
{ |
return Make_HandleUse((GNode *) pgn, (GNode *) cgn); |
return (Make_HandleUse((GNode *) pgn, (GNode *) cgn)); |
} |
} |
|
|
/*- |
/*- |
|
|
char *child; |
char *child; |
char *p1 = NULL; |
char *p1 = NULL; |
|
|
if (OP_NOP(cgn->type)) { |
if (OP_NOP(cgn->type) || |
|
(child = Var_Value(TARGET, cgn, &p1)) == NULL) { |
/* |
/* |
* this node is only source; use the specific pathname for it |
* this node is only source; use the specific pathname for it |
*/ |
*/ |
child = cgn->path ? cgn->path : cgn->name; |
child = cgn->path ? cgn->path : cgn->name; |
} |
} |
else |
|
child = Var_Value(TARGET, cgn, &p1); |
|
Var_Append (ALLSRC, child, pgn); |
Var_Append (ALLSRC, child, pgn); |
if (pgn->type & OP_JOIN) { |
if (pgn->type & OP_JOIN) { |
if (cgn->made == MADE) { |
if (cgn->made == MADE) { |
|
|
return (0); |
return (0); |
} |
} |
|
|
|
|
/*- |
/*- |
*----------------------------------------------------------------------- |
*----------------------------------------------------------------------- |
* Make_Run -- |
* Make_ExpandUse -- |
* Initialize the nodes to remake and the list of nodes which are |
* Expand .USE nodes and create a new targets list |
* ready to be made by doing a breadth-first traversal of the graph |
|
* starting from the nodes in the given list. Once this traversal |
|
* is finished, all the 'leaves' of the graph are in the toBeMade |
|
* queue. |
|
* Using this queue and the Job module, work back up the graph, |
|
* calling on MakeStartJobs to keep the job table as full as |
|
* possible. |
|
* |
|
* Results: |
* Results: |
* TRUE if work was done. FALSE otherwise. |
* The new list of targets. |
* |
* |
* Side Effects: |
* Side Effects: |
* The make field of all nodes involved in the creation of the given |
* numNodes is set to the number of elements in the list of targets. |
* targets is set to 1. The toBeMade list is set to contain all the |
|
* 'leaves' of these subgraphs. |
|
*----------------------------------------------------------------------- |
*----------------------------------------------------------------------- |
*/ |
*/ |
Boolean |
Lst |
Make_Run (targs) |
Make_ExpandUse (targs) |
Lst targs; /* the initial list of targets */ |
Lst targs; /* the initial list of targets */ |
{ |
{ |
register GNode *gn; /* a temporary pointer */ |
register GNode *gn; /* a temporary pointer */ |
register Lst examine; /* List of targets to examine */ |
register Lst examine; /* List of targets to examine */ |
int errors; /* Number of errors the Job module reports */ |
register Lst ntargs; /* List of new targets to be made */ |
|
|
toBeMade = Lst_Init (FALSE); |
ntargs = Lst_Init (FALSE); |
|
|
examine = Lst_Duplicate(targs, NOCOPY); |
examine = Lst_Duplicate(targs, NOCOPY); |
numNodes = 0; |
numNodes = 0; |
|
|
/* |
/* |
* Apply any .USE rules before looking for implicit dependencies |
* Apply any .USE rules before looking for implicit dependencies |
* to make sure everything has commands that should... |
* to make sure everything has commands that should... |
|
* Make sure that the TARGET is set, so that we can make |
|
* expansions. |
*/ |
*/ |
|
Var_Set (TARGET, gn->name, gn); |
Lst_ForEach (gn->children, MakeHandleUse, (ClientData)gn); |
Lst_ForEach (gn->children, MakeHandleUse, (ClientData)gn); |
Suff_FindDeps (gn); |
Suff_FindDeps (gn); |
|
|
if (gn->unmade != 0) { |
if (gn->unmade != 0 && (gn->type & OP_MADE) == 0) { |
Lst_ForEach (gn->children, MakeAddChild, (ClientData)examine); |
Lst_ForEach (gn->children, MakeAddChild, (ClientData)examine); |
} else { |
} else { |
(void)Lst_EnQueue (toBeMade, (ClientData)gn); |
(void)Lst_EnQueue (ntargs, (ClientData)gn); |
|
if (gn->type & OP_MADE) |
|
Lst_ForEach (gn->children, MakeFindChild, (ClientData)gn); |
} |
} |
} |
} |
} |
} |
|
|
Lst_Destroy (examine, NOFREE); |
Lst_Destroy (examine, NOFREE); |
|
return (ntargs); |
|
} |
|
|
|
/*- |
|
*----------------------------------------------------------------------- |
|
* Make_Run -- |
|
* Initialize the nodes to remake and the list of nodes which are |
|
* ready to be made by doing a breadth-first traversal of the graph |
|
* starting from the nodes in the given list. Once this traversal |
|
* is finished, all the 'leaves' of the graph are in the toBeMade |
|
* queue. |
|
* Using this queue and the Job module, work back up the graph, |
|
* calling on MakeStartJobs to keep the job table as full as |
|
* possible. |
|
* |
|
* Results: |
|
* TRUE if work was done. FALSE otherwise. |
|
* |
|
* Side Effects: |
|
* The make field of all nodes involved in the creation of the given |
|
* targets is set to 1. The toBeMade list is set to contain all the |
|
* 'leaves' of these subgraphs. |
|
*----------------------------------------------------------------------- |
|
*/ |
|
Boolean |
|
Make_Run (targs) |
|
Lst targs; /* the initial list of targets */ |
|
{ |
|
int errors; /* Number of errors the Job module reports */ |
|
|
|
toBeMade = Make_ExpandUse (targs); |
|
|
if (queryFlag) { |
if (queryFlag) { |
/* |
/* |