version 1.44, 2006/10/27 21:00:19 |
version 1.45, 2006/11/17 22:07:39 |
Line 244 Targ_NewGN(const char *name) |
|
Line 244 Targ_NewGN(const char *name) |
|
} |
} |
gn->unmade = 0; |
gn->unmade = 0; |
gn->unmade_cohorts = 0; |
gn->unmade_cohorts = 0; |
|
gn->cohort_num[0] = 0; |
gn->centurion = NULL; |
gn->centurion = NULL; |
gn->made = UNMADE; |
gn->made = UNMADE; |
gn->flags = 0; |
gn->flags = 0; |
gn->order = 0; |
|
gn->mtime = gn->cmtime = 0; |
gn->mtime = gn->cmtime = 0; |
gn->iParents = Lst_Init(FALSE); |
gn->iParents = Lst_Init(FALSE); |
gn->cohorts = Lst_Init(FALSE); |
gn->cohorts = Lst_Init(FALSE); |
gn->parents = Lst_Init(FALSE); |
gn->parents = Lst_Init(FALSE); |
gn->ancestors = Lst_Init(FALSE); |
|
gn->children = Lst_Init(FALSE); |
gn->children = Lst_Init(FALSE); |
gn->successors = Lst_Init(FALSE); |
gn->order_pred = Lst_Init(FALSE); |
gn->preds = Lst_Init(FALSE); |
gn->order_succ = Lst_Init(FALSE); |
gn->recpreds = Lst_Init(FALSE); |
|
Hash_InitTable(&gn->context, 0); |
Hash_InitTable(&gn->context, 0); |
gn->commands = Lst_Init(FALSE); |
gn->commands = Lst_Init(FALSE); |
gn->suffix = NULL; |
gn->suffix = NULL; |
Line 302 TargFreeGN(ClientData gnp) |
|
Line 300 TargFreeGN(ClientData gnp) |
|
Lst_Destroy(gn->iParents, NOFREE); |
Lst_Destroy(gn->iParents, NOFREE); |
Lst_Destroy(gn->cohorts, NOFREE); |
Lst_Destroy(gn->cohorts, NOFREE); |
Lst_Destroy(gn->parents, NOFREE); |
Lst_Destroy(gn->parents, NOFREE); |
Lst_Destroy(gn->ancestors, NOFREE); |
|
Lst_Destroy(gn->children, NOFREE); |
Lst_Destroy(gn->children, NOFREE); |
Lst_Destroy(gn->successors, NOFREE); |
Lst_Destroy(gn->order_succ, NOFREE); |
Lst_Destroy(gn->preds, NOFREE); |
Lst_Destroy(gn->order_pred, NOFREE); |
Lst_Destroy(gn->recpreds, NOFREE); |
|
Hash_DeleteTable(&gn->context); |
Hash_DeleteTable(&gn->context); |
Lst_Destroy(gn->commands, NOFREE); |
Lst_Destroy(gn->commands, NOFREE); |
free(gn); |
free(gn); |
Line 341 Targ_FindNode(const char *name, int flag |
|
Line 337 Targ_FindNode(const char *name, int flag |
|
Boolean isNew; /* Set TRUE if Hash_CreateEntry had to create */ |
Boolean isNew; /* Set TRUE if Hash_CreateEntry had to create */ |
/* an entry for the node */ |
/* an entry for the node */ |
|
|
|
if (!(flags & (TARG_CREATE | TARG_NOHASH))) { |
if (flags & TARG_CREATE) { |
|
he = Hash_CreateEntry(&targets, name, &isNew); |
|
if (isNew) { |
|
gn = Targ_NewGN(name); |
|
Hash_SetValue(he, gn); |
|
Var_Append(".ALLTARGETS", name, VAR_GLOBAL); |
|
(void)Lst_AtEnd(allTargets, gn); |
|
} |
|
} else { |
|
he = Hash_FindEntry(&targets, name); |
he = Hash_FindEntry(&targets, name); |
|
if (he == NULL) |
|
return (NILGNODE); |
|
return (GNode *)Hash_GetValue(he); |
} |
} |
|
|
if (he == NULL) { |
if (!(flags & TARG_NOHASH)) { |
return (NILGNODE); |
he = Hash_CreateEntry(&targets, name, &isNew); |
} else { |
if (!isNew) |
return ((GNode *)Hash_GetValue(he)); |
return (GNode *)Hash_GetValue(he); |
} |
} |
|
|
|
gn = Targ_NewGN(name); |
|
if (!(flags & TARG_NOHASH)) |
|
Hash_SetValue(he, gn); |
|
Var_Append(".ALLTARGETS", name, VAR_GLOBAL); |
|
(void)Lst_AtEnd(allTargets, gn); |
|
return gn; |
} |
} |
|
|
/*- |
/*- |
Line 511 Targ_SetMain(GNode *gn) |
|
Line 508 Targ_SetMain(GNode *gn) |
|
mainTarg = gn; |
mainTarg = gn; |
} |
} |
|
|
#define PrintWait (ClientData)1 |
|
#define PrintPath (ClientData)2 |
|
|
|
static int |
static int |
TargPrintName(ClientData gnp, ClientData pflags) |
TargPrintName(ClientData gnp, ClientData pflags) |
{ |
{ |
static int last_order; |
|
GNode *gn = (GNode *)gnp; |
GNode *gn = (GNode *)gnp; |
|
|
if (pflags == PrintWait && gn->order > last_order) |
fprintf(debug_file, "%s%s ", gn->name, gn->cohort_num); |
fprintf(debug_file, ".WAIT "); |
|
last_order = gn->order; |
|
|
|
fprintf(debug_file, "%s ", gn->name); |
|
|
|
#ifdef notdef |
|
if (pflags == PrintPath) { |
|
if (gn->path) { |
|
fprintf(debug_file, "[%s] ", gn->path); |
|
} |
|
if (gn == mainTarg) { |
|
fprintf(debug_file, "(MAIN NAME) "); |
|
} |
|
} |
|
#endif /* notdef */ |
|
|
|
return 0; |
return 0; |
} |
} |
Line 620 Targ_PrintType(int type) |
|
Line 598 Targ_PrintType(int type) |
|
} |
} |
} |
} |
|
|
|
static const char * |
|
made_name(enum enum_made made) |
|
{ |
|
switch (made) { |
|
case UNMADE: return "unmade"; |
|
case DEFERRED: return "deferred"; |
|
case REQUESTED: return "requested"; |
|
case BEINGMADE: return "being made"; |
|
case MADE: return "made"; |
|
case UPTODATE: return "up-to-date"; |
|
case ERROR: return "error when made"; |
|
case ABORTED: return "aborted"; |
|
case ENDCYCLE: return "end cycle"; |
|
default: return "unknown enum_made value"; |
|
} |
|
} |
|
|
/*- |
/*- |
*----------------------------------------------------------------------- |
*----------------------------------------------------------------------- |
* TargPrintNode -- |
* TargPrintNode -- |
Line 631 Targ_PrintNode(ClientData gnp, ClientDat |
|
Line 626 Targ_PrintNode(ClientData gnp, ClientDat |
|
{ |
{ |
GNode *gn = (GNode *)gnp; |
GNode *gn = (GNode *)gnp; |
int pass = passp ? *(int *)passp : 0; |
int pass = passp ? *(int *)passp : 0; |
|
|
|
fprintf(debug_file, "# %s%s, flags %x, type %x, made %d\n", |
|
gn->name, gn->cohort_num, gn->flags, gn->type, gn->made); |
|
if (gn->flags == 0) |
|
return 0; |
|
|
if (!OP_NOP(gn->type)) { |
if (!OP_NOP(gn->type)) { |
fprintf(debug_file, "#\n"); |
fprintf(debug_file, "#\n"); |
if (gn == mainTarg) { |
if (gn == mainTarg) { |
fprintf(debug_file, "# *** MAIN TARGET ***\n"); |
fprintf(debug_file, "# *** MAIN TARGET ***\n"); |
} |
} |
if (pass == 2) { |
if (pass >= 2) { |
if (gn->unmade) { |
if (gn->unmade) { |
fprintf(debug_file, "# %d unmade children\n", gn->unmade); |
fprintf(debug_file, "# %d unmade children\n", gn->unmade); |
} else { |
} else { |
Line 646 Targ_PrintNode(ClientData gnp, ClientDat |
|
Line 647 Targ_PrintNode(ClientData gnp, ClientDat |
|
if (gn->mtime != 0) { |
if (gn->mtime != 0) { |
fprintf(debug_file, "# last modified %s: %s\n", |
fprintf(debug_file, "# last modified %s: %s\n", |
Targ_FmtTime(gn->mtime), |
Targ_FmtTime(gn->mtime), |
(gn->made == UNMADE ? "unmade" : |
made_name(gn->made)); |
(gn->made == MADE ? "made" : |
|
(gn->made == UPTODATE ? "up-to-date" : |
|
"error when made")))); |
|
} else if (gn->made != UNMADE) { |
} else if (gn->made != UNMADE) { |
fprintf(debug_file, "# non-existent (maybe): %s\n", |
fprintf(debug_file, "# non-existent (maybe): %s\n", |
(gn->made == MADE ? "made" : |
made_name(gn->made)); |
(gn->made == UPTODATE ? "up-to-date" : |
|
(gn->made == ERROR ? "error when made" : |
|
"aborted")))); |
|
} else { |
} else { |
fprintf(debug_file, "# unmade\n"); |
fprintf(debug_file, "# unmade\n"); |
} |
} |
Line 674 Targ_PrintNode(ClientData gnp, ClientDat |
|
Line 669 Targ_PrintNode(ClientData gnp, ClientDat |
|
Lst_ForEach(gn->parents, TargPrintName, NULL); |
Lst_ForEach(gn->parents, TargPrintName, NULL); |
fprintf(debug_file, "\n"); |
fprintf(debug_file, "\n"); |
} |
} |
if (!Lst_IsEmpty (gn->children)) { |
if (!Lst_IsEmpty (gn->order_pred)) { |
fprintf(debug_file, "# children: "); |
fprintf(debug_file, "# order_pred: "); |
Lst_ForEach(gn->children, TargPrintName, NULL); |
Lst_ForEach(gn->order_pred, TargPrintName, NULL); |
fprintf(debug_file, "\n"); |
fprintf(debug_file, "\n"); |
} |
} |
if (!Lst_IsEmpty (gn->preds)) { |
if (!Lst_IsEmpty (gn->order_succ)) { |
fprintf(debug_file, "# preds: "); |
fprintf(debug_file, "# order_succ: "); |
Lst_ForEach(gn->preds, TargPrintName, NULL); |
Lst_ForEach(gn->order_succ, TargPrintName, NULL); |
fprintf(debug_file, "\n"); |
|
} |
|
if (!Lst_IsEmpty (gn->recpreds)) { |
|
fprintf(debug_file, "# recpreds: "); |
|
Lst_ForEach(gn->recpreds, TargPrintName, NULL); |
|
fprintf(debug_file, "\n"); |
|
} |
|
if (!Lst_IsEmpty (gn->successors)) { |
|
fprintf(debug_file, "# successors: "); |
|
Lst_ForEach(gn->successors, TargPrintName, NULL); |
|
fprintf(debug_file, "\n"); |
fprintf(debug_file, "\n"); |
} |
} |
|
|
Line 705 Targ_PrintNode(ClientData gnp, ClientDat |
|
Line 690 Targ_PrintNode(ClientData gnp, ClientDat |
|
fprintf(debug_file, ":: "); break; |
fprintf(debug_file, ":: "); break; |
} |
} |
Targ_PrintType(gn->type); |
Targ_PrintType(gn->type); |
Lst_ForEach(gn->children, TargPrintName, PrintWait); |
Lst_ForEach(gn->children, TargPrintName, NULL); |
fprintf(debug_file, "\n"); |
fprintf(debug_file, "\n"); |
Lst_ForEach(gn->commands, Targ_PrintCmd, NULL); |
Lst_ForEach(gn->commands, Targ_PrintCmd, NULL); |
fprintf(debug_file, "\n\n"); |
fprintf(debug_file, "\n\n"); |
|
|
TargPrintOnlySrc(ClientData gnp, ClientData dummy) |
TargPrintOnlySrc(ClientData gnp, ClientData dummy) |
{ |
{ |
GNode *gn = (GNode *)gnp; |
GNode *gn = (GNode *)gnp; |
if (OP_NOP(gn->type)) |
if (!OP_NOP(gn->type)) |
fprintf(debug_file, "#\t%s [%s]\n", gn->name, gn->path ? gn->path : gn->name); |
return 0; |
|
|
return (dummy ? 0 : 0); |
fprintf(debug_file, "#\t%s [%s] ", |
|
gn->name, gn->path ? gn->path : gn->name); |
|
Targ_PrintType(gn->type); |
|
fprintf(debug_file, "\n"); |
|
|
|
return 0; |
} |
} |
|
|
/*- |
/*- |
Line 775 Targ_PrintGraph(int pass) |
|
Line 765 Targ_PrintGraph(int pass) |
|
|
|
/*- |
/*- |
*----------------------------------------------------------------------- |
*----------------------------------------------------------------------- |
* TargAppendAncestor - |
|
* Appends a single ancestor to a node's list of ancestors, |
|
* ignoring duplicates. |
|
* |
|
* Input: |
|
* ancestorgnp An ancestor to be added to a list. |
|
* thisgnp The node whose ancestor list will be changed. |
|
* |
|
* Results: |
|
* Always returns 0, for the benefit of Lst_ForEach(). |
|
* |
|
* Side Effects: |
|
* May modify the ancestors list of the node we are |
|
* examining. |
|
*----------------------------------------------------------------------- |
|
*/ |
|
static int |
|
TargAppendAncestor(ClientData ancestorgnp, ClientData thisgnp) |
|
{ |
|
GNode *ancestorgn = (GNode *)ancestorgnp; |
|
GNode *thisgn = (GNode *)thisgnp; |
|
|
|
if (Lst_Member(thisgn->ancestors, ancestorgn) == NILLNODE) { |
|
(void)Lst_AtEnd(thisgn->ancestors, ancestorgn); |
|
} |
|
return (0); |
|
} |
|
|
|
/*- |
|
*----------------------------------------------------------------------- |
|
* TargAppendParentAncestors - |
|
* Appends all ancestors of a parent node to the ancestor list of a |
|
* given node, ignoring duplicates. |
|
* |
|
* Input: |
|
* parentgnp A parent node whose ancestor list will be |
|
* propagated to another node. |
|
* thisgnp The node whose ancestor list will be changed. |
|
* |
|
* Results: |
|
* Always returns 0, for the benefit of Lst_ForEach(). |
|
* |
|
* Side Effects: |
|
* May modify the ancestors list of the node we are |
|
* examining. |
|
*----------------------------------------------------------------------- |
|
*/ |
|
static int |
|
TargAppendParentAncestors(ClientData parentgnp, ClientData thisgnp) |
|
{ |
|
GNode *parentgn = (GNode *)parentgnp; |
|
GNode *thisgn = (GNode *)thisgnp; |
|
|
|
Lst_ForEach(parentgn->ancestors, TargAppendAncestor, thisgn); |
|
return (0); |
|
} |
|
|
|
/*- |
|
*----------------------------------------------------------------------- |
|
* TargInitAncestors - |
|
* Initialises the ancestor list of a node and all the |
|
* node's ancestors. |
|
* |
|
* Input: |
|
* thisgnp The node that we are examining. |
|
* |
|
* Results: |
|
* Always returns 0, for the benefit of Lst_ForEach(). |
|
* |
|
* Side Effects: |
|
* May initialise the ancestors list of the node we are |
|
* examining and all its ancestors. Does nothing if the |
|
* list has already been initialised. |
|
*----------------------------------------------------------------------- |
|
*/ |
|
static int |
|
TargInitAncestors(ClientData thisgnp, ClientData junk __unused) |
|
{ |
|
GNode *thisgn = (GNode *)thisgnp; |
|
|
|
if (Lst_IsEmpty (thisgn->ancestors)) { |
|
/* |
|
* Add our parents to our ancestor list before recursing, to |
|
* ensure that loops in the dependency graph will not result in |
|
* infinite recursion. |
|
*/ |
|
Lst_ForEach(thisgn->parents, TargAppendAncestor, thisgn); |
|
Lst_ForEach(thisgn->iParents, TargAppendAncestor, thisgn); |
|
/* Recursively initialise our parents' ancestor lists */ |
|
Lst_ForEach(thisgn->parents, TargInitAncestors, NULL); |
|
Lst_ForEach(thisgn->iParents, TargInitAncestors, NULL); |
|
/* Our parents' ancestors are also our ancestors */ |
|
Lst_ForEach(thisgn->parents, TargAppendParentAncestors, thisgn); |
|
Lst_ForEach(thisgn->iParents, TargAppendParentAncestors, thisgn); |
|
} |
|
return (0); |
|
} |
|
|
|
/*- |
|
*----------------------------------------------------------------------- |
|
* TargHasAncestor - |
|
* Checks whether one node is an ancestor of another node. |
|
* |
|
* If called with both arguments pointing to the |
|
* same node, checks whether the node is part of a cycle |
|
* in the graph. |
|
* |
|
* Input: |
|
* thisgnp The node whose ancestor list we are examining. |
|
* seekgnp The node that we are seeking in the |
|
* ancestor list. |
|
* |
|
* Results: |
|
* TRUE if seekgn is an ancestor of thisgn; FALSE if not. |
|
* |
|
* Side Effects: |
|
* Initialises the ancestors list in thisgnp and all its ancestors. |
|
*----------------------------------------------------------------------- |
|
*/ |
|
static Boolean |
|
TargHasAncestor(ClientData thisgnp, ClientData seekgnp) |
|
{ |
|
GNode *thisgn = (GNode *)thisgnp; |
|
GNode *seekgn = (GNode *)seekgnp; |
|
|
|
TargInitAncestors(thisgn, NULL); |
|
if (Lst_Member(thisgn->ancestors, seekgn) != NILLNODE) { |
|
return (TRUE); |
|
} |
|
return (FALSE); |
|
} |
|
|
|
/*- |
|
*----------------------------------------------------------------------- |
|
* TargPropagateRecpredChild -- |
|
* Create a new predecessor/successor relationship between a pair |
|
* of nodes, and recursively propagate the relationship to all |
|
* children of the successor node. |
|
* |
|
* If there is already a predecessor/successor relationship |
|
* in the opposite direction, or if there is already an |
|
* ancestor/descendent relationship in the oposite direction, then |
|
* we avoid adding the new relationship, because that would cause a |
|
* cycle in the graph. |
|
* |
|
* Input: |
|
* succgnp Successor node. |
|
* predgnp Predecessor node. |
|
* |
|
* Results: |
|
* Always returns 0, for the benefit of Lst_ForEach(). |
|
* |
|
* Side Effects: |
|
* preds/successors information is modified for predgnp, succgnp, |
|
* and recursively for all children of succgnp. |
|
*----------------------------------------------------------------------- |
|
*/ |
|
static int |
|
TargPropagateRecpredChild(ClientData succgnp, ClientData predgnp) |
|
{ |
|
GNode *succgn = (GNode *)succgnp; |
|
GNode *predgn = (GNode *)predgnp; |
|
Boolean debugmore = FALSE; /* how much debugging? */ |
|
|
|
/* Ignore if succgn == predgn */ |
|
if (succgn == predgn) { |
|
if (DEBUG(TARG) && debugmore) { |
|
fprintf(debug_file, "# TargPropagateRecpredChild: not propagating %s - %s (identical)\n", |
|
predgn->name, succgn->name); |
|
} |
|
return (0); |
|
} |
|
/* Pre-existing pred/successor relationship |
|
* in the opposite direction takes precedence. */ |
|
if (Lst_Member(succgn->successors, predgn) != NILLNODE) { |
|
if (DEBUG(TARG) && debugmore) { |
|
fprintf(debug_file, "# TargPropagateRecpredChild: not propagating %s - %s (opposite)\n", |
|
predgn->name, succgn->name); |
|
} |
|
return (0); |
|
} |
|
/* Pre-existing descendent/ancestor relationship in the opposite |
|
* direction takes precedence. */ |
|
if (TargHasAncestor(succgn, predgn)) { |
|
if (DEBUG(TARG) && debugmore) { |
|
fprintf(debug_file, "# TargPropagateRecpredChild: not propagating %s - %s (ancestor)\n", |
|
predgn->name, succgn->name); |
|
} |
|
return (0); |
|
} |
|
/* Note the new pred/successor relationship. */ |
|
if (DEBUG(TARG)) { |
|
fprintf(debug_file, "# TargPropagateRecpredChild: propagating %s - %s\n", |
|
predgn->name, succgn->name); |
|
} |
|
if (Lst_Member(succgn->preds, predgn) == NILLNODE) { |
|
(void)Lst_AtEnd(succgn->preds, predgn); |
|
(void)Lst_AtEnd(predgn->successors, succgn); |
|
} |
|
/* Recurse, provided there's not a cycle. */ |
|
if (! TargHasAncestor(succgn, succgn)) { |
|
Lst_ForEach(succgn->children, TargPropagateRecpredChild, predgn); |
|
} |
|
return (0); |
|
} |
|
|
|
/*- |
|
*----------------------------------------------------------------------- |
|
* TargPropagateRecpred -- |
|
* Recursively propagate information about a single predecessor |
|
* node, from a single successor node to all children of the |
|
* successor node. |
|
* |
|
* Input: |
|
* predgnp Predecessor node. |
|
* succgnp Successor node. |
|
* |
|
* Results: |
|
* Always returns 0, for the benefit of Lst_ForEach(). |
|
* |
|
* Side Effects: |
|
* preds/successors information is modified for predgnp, succgnp, |
|
* and recursively for all children of succgnp. |
|
* |
|
* The real work is done by TargPropagateRecpredChild(), which |
|
* will be called for each child of the successor node. |
|
*----------------------------------------------------------------------- |
|
*/ |
|
static int |
|
TargPropagateRecpred(ClientData predgnp, ClientData succgnp) |
|
{ |
|
GNode *predgn = (GNode *)predgnp; |
|
GNode *succgn = (GNode *)succgnp; |
|
|
|
Lst_ForEach(succgn->children, TargPropagateRecpredChild, predgn); |
|
return (0); |
|
} |
|
|
|
/*- |
|
*----------------------------------------------------------------------- |
|
* TargPropagateNode -- |
* TargPropagateNode -- |
* Propagate information from a single node to related nodes if |
* Propagate information from a single node to related nodes if |
* appropriate. |
* appropriate. |
|
|
TargPropagateNode(ClientData gnp, ClientData junk __unused) |
TargPropagateNode(ClientData gnp, ClientData junk __unused) |
{ |
{ |
GNode *gn = (GNode *)gnp; |
GNode *gn = (GNode *)gnp; |
|
|
if (gn->type & OP_DOUBLEDEP) |
if (gn->type & OP_DOUBLEDEP) |
Lst_ForEach(gn->cohorts, TargPropagateCohort, gnp); |
Lst_ForEach(gn->cohorts, TargPropagateCohort, gnp); |
Lst_ForEach(gn->recpreds, TargPropagateRecpred, gnp); |
|
return (0); |
return (0); |
} |
} |
|
|