version 1.113, 2015/11/06 18:41:02 |
version 1.114, 2015/11/29 09:17:12 |
|
|
* set as persistent arrays for performance reasons. |
* set as persistent arrays for performance reasons. |
*/ |
*/ |
static struct growableArray gsources, gtargets; |
static struct growableArray gsources, gtargets; |
|
static struct ohash htargets; |
|
static bool htargets_setup = false; |
#define SOURCES_SIZE 128 |
#define SOURCES_SIZE 128 |
#define TARGETS_SIZE 32 |
#define TARGETS_SIZE 32 |
|
|
|
|
static bool found_delimiter(const char *); |
static bool found_delimiter(const char *); |
static unsigned int handle_special_targets(Lst); |
static unsigned int handle_special_targets(Lst); |
static void dump_targets(void); |
static void dump_targets(void); |
|
static void dedup_targets(struct growableArray *); |
|
static void build_target_group(struct growableArray *, struct ohash *t); |
|
static void reset_target_hash(void); |
|
|
|
|
#define P(k) k, sizeof(k), K_##k |
#define P(k) k, sizeof(k), K_##k |
|
|
* a list of .PATH targets */ |
* a list of .PATH targets */ |
unsigned int tOp; /* operator from special target */ |
unsigned int tOp; /* operator from special target */ |
|
|
|
|
waiting = 0; |
waiting = 0; |
Lst_Init(&paths); |
Lst_Init(&paths); |
|
|
|
|
return; |
return; |
|
|
Array_FindP(>argets, ParseDoOp, op); |
Array_FindP(>argets, ParseDoOp, op); |
|
dedup_targets(>argets); |
|
|
line = cp; |
line = cp; |
|
|
|
|
return false; |
return false; |
} |
} |
|
|
/*** |
/* postprocess group of targets prior to linking stuff with them */ |
*** handle a group of commands |
bool |
***/ |
register_target(GNode *gn, struct ohash *t) |
|
|
static void |
|
register_for_groupling(GNode *gn, struct ohash *temp) |
|
{ |
{ |
unsigned int slot; |
unsigned int slot; |
uint32_t hv; |
uint32_t hv; |
|
|
|
|
hv = ohash_interval(gn->name, &ename); |
hv = ohash_interval(gn->name, &ename); |
|
|
slot = ohash_lookup_interval(temp, gn->name, ename, hv); |
slot = ohash_lookup_interval(t, gn->name, ename, hv); |
gn2 = ohash_find(temp, slot); |
gn2 = ohash_find(t, slot); |
|
|
if (gn2 == NULL) |
if (gn2 == NULL) { |
ohash_insert(temp, slot, gn); |
ohash_insert(t, slot, gn); |
|
return true; |
|
} else |
|
return false; |
} |
} |
|
|
static void |
static void |
build_target_group(struct growableArray *targets) |
build_target_group(struct growableArray *targets, struct ohash *t) |
{ |
{ |
LstNode ln; |
LstNode ln; |
bool seen_target = false; |
bool seen_target = false; |
|
|
/* may be 0 if wildcard expansion resulted in zero match */ |
/* may be 0 if wildcard expansion resulted in zero match */ |
if (targets->n <= 1) |
if (targets->n <= 1) |
return; |
return; |
|
|
|
/* Perform checks to see if we must tie targets together */ |
/* XXX */ |
/* XXX */ |
if (targets->a[0]->type & OP_TRANSFORM) |
if (targets->a[0]->type & OP_TRANSFORM) |
return; |
return; |
|
|
for (ln = Lst_First(&targets->a[0]->commands); ln != NULL; |
for (ln = Lst_First(&targets->a[0]->commands); ln != NULL; |
ln = Lst_Adv(ln)) { |
ln = Lst_Adv(ln)) { |
struct command *cmd = Lst_Datum(ln); |
struct command *cmd = Lst_Datum(ln); |
|
|
if (seen_target) |
if (seen_target) |
return; |
return; |
|
|
/* target list MAY hold duplicates AND targets may already participate |
GNode *gn, *gn2; |
* in groupling lists, so rebuild the circular list "from scratch" |
/* targets may already participate in groupling lists, |
|
* so rebuild the circular list "from scratch" |
*/ |
*/ |
|
|
struct ohash t; |
|
GNode *gn, *gn2; |
|
|
|
ohash_init(&t, 5, &gnode_info); |
|
|
|
for (i = 0; i < targets->n; i++) { |
for (i = 0; i < targets->n; i++) { |
gn = targets->a[i]; |
gn = targets->a[i]; |
register_for_groupling(gn, &t); |
|
for (gn2 = gn->groupling; gn2 != gn; gn2 = gn2->groupling) { |
for (gn2 = gn->groupling; gn2 != gn; gn2 = gn2->groupling) { |
if (!gn2) |
if (!gn2) |
break; |
break; |
register_for_groupling(gn2, &t); |
register_target(gn2, t); |
} |
} |
} |
} |
|
|
for (gn = ohash_first(&t, &i); gn != NULL; gn = ohash_next(&t, &i)) { |
for (gn = ohash_first(t, &i); gn != NULL; gn = ohash_next(t, &i)) { |
gn->groupling = gn2; |
gn->groupling = gn2; |
gn2 = gn; |
gn2 = gn; |
} |
} |
gn = ohash_first(&t, &i); |
gn = ohash_first(t, &i); |
gn->groupling = gn2; |
gn->groupling = gn2; |
|
} |
|
|
ohash_delete(&t); |
static void |
|
reset_target_hash() |
|
{ |
|
if (htargets_setup) |
|
ohash_delete(&htargets); |
|
ohash_init(&htargets, 5, &gnode_info); |
|
htargets_setup = true; |
} |
} |
|
|
|
void |
|
Parse_End() |
|
{ |
|
if (htargets_setup) |
|
ohash_delete(&htargets); |
|
} |
|
|
static void |
static void |
|
dedup_targets(struct growableArray *targets) |
|
{ |
|
unsigned int i, j; |
|
|
|
if (targets->n <= 1) |
|
return; |
|
|
|
reset_target_hash(); |
|
/* first let's de-dup the list */ |
|
for (i = 0, j = 0; i < targets->n; i++) { |
|
GNode *gn = targets->a[i]; |
|
if (register_target(gn, &htargets)) |
|
targets->a[j++] = targets->a[i]; |
|
} |
|
targets->n = j; |
|
} |
|
|
|
|
|
/*** |
|
*** handle a group of commands |
|
***/ |
|
|
|
static void |
finish_commands(struct growableArray *targets) |
finish_commands(struct growableArray *targets) |
{ |
{ |
build_target_group(targets); |
build_target_group(targets, &htargets); |
Array_Every(targets, ParseHasCommands); |
Array_Every(targets, ParseHasCommands); |
} |
} |
|
|
|
|
if (commands_seen) |
if (commands_seen) |
finish_commands(>argets); |
finish_commands(>argets); |
commands_seen = false; |
commands_seen = false; |
Array_Reset(>argets); |
|
if (Parse_As_Var_Assignment(stripped)) |
if (Parse_As_Var_Assignment(stripped)) |
expectingCommands = false; |
expectingCommands = false; |
else { |
else { |