=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/make/parse.c,v retrieving revision 1.122 retrieving revision 1.123 diff -u -r1.122 -r1.123 --- src/usr.bin/make/parse.c 2019/12/21 15:29:25 1.122 +++ src/usr.bin/make/parse.c 2019/12/22 16:53:40 1.123 @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.c,v 1.122 2019/12/21 15:29:25 espie Exp $ */ +/* $OpenBSD: parse.c,v 1.123 2019/12/22 16:53:40 espie Exp $ */ /* $NetBSD: parse.c,v 1.29 1997/03/10 21:20:04 christos Exp $ */ /* @@ -131,6 +131,7 @@ static void ParseLinkSrc(GNode *, GNode *); static int ParseDoOp(GNode **, unsigned int); +static void ParseDoSpecial(GNode *, unsigned int); static int ParseAddDep(GNode *, GNode *); static void ParseDoSrc(struct growableArray *, struct growableArray *, int, const char *, const char *); @@ -282,65 +283,81 @@ * Apply the parsed operator to the given target node. Used in a * 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. + * operators are incompatible, a major error is taken, and the find + * stops early * * Side Effects: - * The type field of the node is altered to reflect any new bits in - * the op. + * The node gets the right dependency operator. + * Cohorts may be created for double dep. *--------------------------------------------------------------------- */ static int ParseDoOp(GNode **gnp, unsigned int op) { 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)) { - /* 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; + assert(op == (op & OP_OPMASK)); - 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); + /* if the node didn't already appear on the left hand side (no known + * dependency operator), we don't need to do much. */ + if (!OP_NOP(gn->type)) { + /* + * 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 != (gn->type & OP_OPMASK)) { + 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; + } - /* Replace the node in the targets list with the new copy */ - *gnp = cohort; - gn = cohort; + if (op == 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(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. */ + /* Preserve possible special flags already applied to the operator */ gn->type |= op; return 1; } +static void +ParseDoSpecial(GNode *gn, unsigned int special_op) +{ + gn->type |= special_op; +} + /*- *--------------------------------------------------------------------- * ParseAddDep -- @@ -404,7 +421,7 @@ 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); + Array_ForEach(targets, ParseDoSpecial, gn->special_op); return; } else { assert((gn->special & SPECIAL_MASK) == SPECIAL_WAIT);