version 1.122, 2019/12/21 15:29:25 |
version 1.123, 2019/12/22 16:53:40 |
|
|
|
|
static void ParseLinkSrc(GNode *, GNode *); |
static void ParseLinkSrc(GNode *, GNode *); |
static int ParseDoOp(GNode **, unsigned int); |
static int ParseDoOp(GNode **, unsigned int); |
|
static void ParseDoSpecial(GNode *, unsigned int); |
static int ParseAddDep(GNode *, GNode *); |
static int ParseAddDep(GNode *, GNode *); |
static void ParseDoSrc(struct growableArray *, struct growableArray *, int, |
static void ParseDoSrc(struct growableArray *, struct growableArray *, int, |
const char *, const char *); |
const char *, const char *); |
|
|
* Apply the parsed operator to the given target node. Used in a |
* Apply the parsed operator to the given target node. Used in a |
* Array_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 |
* been found and their operator parsed. If the previous and new |
* operators are incompatible, a major error is taken. |
* operators are incompatible, a major error is taken, and the find |
|
* stops early |
* |
* |
* Side Effects: |
* Side Effects: |
* The type field of the node is altered to reflect any new bits in |
* The node gets the right dependency operator. |
* the op. |
* Cohorts may be created for double dep. |
*--------------------------------------------------------------------- |
*--------------------------------------------------------------------- |
*/ |
*/ |
static int |
static int |
ParseDoOp(GNode **gnp, unsigned int op) |
ParseDoOp(GNode **gnp, unsigned int op) |
{ |
{ |
GNode *gn = *gnp; |
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 dependency operator for target %s\n" |
|
"\t(was %s%s, now %s%s)", |
|
gn->name, gn->name, operator_string(gn->type), |
|
gn->name, operator_string(op)); |
|
return 0; |
|
} |
|
|
|
if (op == OP_DOUBLEDEP && ((gn->type & OP_OPMASK) == OP_DOUBLEDEP)) { |
assert(op == (op & OP_OPMASK)); |
/* 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); |
/* if the node didn't already appear on the left hand side (no known |
/* Duplicate links to parents so graph traversal is simple. |
* dependency operator), we don't need to do much. */ |
* Perhaps some type bits should be duplicated? |
if (!OP_NOP(gn->type)) { |
* |
/* |
* Make the cohort invisible as well to avoid duplicating it |
* If the dependency mask of the operator and the node don't |
* into other variables. True, parents of this target won't |
* match and the node has actually had an operator applied to |
* tend to do anything with their local variables, but better |
* it before, and the operator actually has some dependency |
* safe than sorry. */ |
* information in it, complain. */ |
for (ln = Lst_First(&gn->parents); ln != NULL; ln = Lst_Adv(ln)) |
if (op != (gn->type & OP_OPMASK)) { |
ParseLinkSrc(Lst_Datum(ln), cohort); |
Parse_Error(PARSE_FATAL, |
cohort->type = OP_DOUBLEDEP|OP_INVISIBLE; |
"Inconsistent dependency operator for target %s\n" |
Lst_AtEnd(&gn->cohorts, cohort); |
"\t(was %s%s, now %s%s)", |
|
gn->name, gn->name, operator_string(gn->type), |
|
gn->name, operator_string(op)); |
|
return 0; |
|
} |
|
|
/* Replace the node in the targets list with the new copy */ |
if (op == OP_DOUBLEDEP) { |
*gnp = cohort; |
/* If the node was the object of a :: operator, we need |
gn = cohort; |
* 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(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 |
/* Preserve possible special flags already applied to the operator */ |
* just OR the new operator into the old. */ |
|
gn->type |= op; |
gn->type |= op; |
return 1; |
return 1; |
} |
} |
|
|
|
static void |
|
ParseDoSpecial(GNode *gn, unsigned int special_op) |
|
{ |
|
gn->type |= special_op; |
|
} |
|
|
/*- |
/*- |
*--------------------------------------------------------------------- |
*--------------------------------------------------------------------- |
* ParseAddDep -- |
* ParseAddDep -- |
|
|
GNode *gn = Targ_FindNodei(src, esrc, TARG_CREATE); |
GNode *gn = Targ_FindNodei(src, esrc, TARG_CREATE); |
if ((gn->special & SPECIAL_SOURCE) != 0) { |
if ((gn->special & SPECIAL_SOURCE) != 0) { |
if (gn->special_op) { |
if (gn->special_op) { |
Array_FindP(targets, ParseDoOp, gn->special_op); |
Array_ForEach(targets, ParseDoSpecial, gn->special_op); |
return; |
return; |
} else { |
} else { |
assert((gn->special & SPECIAL_MASK) == SPECIAL_WAIT); |
assert((gn->special & SPECIAL_MASK) == SPECIAL_WAIT); |