Index: sbin/rcorder/rcorder.c =================================================================== --- sbin/rcorder/rcorder.c +++ sbin/rcorder/rcorder.c @@ -150,13 +150,15 @@ static void crunch_all_files(void); static void initialize(void); static void generate_ordering(void); +static void generate_parallel(void); +static int parallel = 0; int main(int argc, char *argv[]) { int ch; - while ((ch = getopt(argc, argv, "dk:s:")) != -1) + while ((ch = getopt(argc, argv, "dk:ps:")) != -1) switch (ch) { case 'd': #ifdef DEBUG @@ -168,6 +170,9 @@ case 'k': strnode_add(&keep_list, optarg, 0); break; + case 'p': + parallel = 1; + break; case 's': strnode_add(&skip_list, optarg, 0); break; @@ -186,7 +191,11 @@ DPRINTF((stderr, "initialize\n")); crunch_all_files(); DPRINTF((stderr, "crunch_all_files\n")); - generate_ordering(); + if (parallel) { + generate_parallel(); + } else { + generate_ordering(); + } DPRINTF((stderr, "generate_ordering\n")); exit(exit_code); @@ -763,7 +772,7 @@ /* if we were already in progress, don't print again */ if (was_set == 0 && skip_ok(fnode) && keep_ok(fnode)) - printf("%s\n", fnode->filename); + printf("%s%s", fnode->filename, parallel ? " " : "\n"); if (fnode->next != NULL) { fnode->next->last = fnode->last; @@ -781,6 +790,74 @@ #endif } +static bool +unsatisfied_req(const struct filenode *fnode) +{ + Hash_Entry *entry; + provnode *head; + f_reqnode *r; + int ndeps = 0; + + for (r = fnode->req_list; r != NULL; r = r->next) { + entry = r->entry; + head = Hash_GetValue(entry); + if (head == NULL) { + warnx("requirement `%s' in file `%s' has no providers.", + Hash_GetKey(entry), fnode->filename); + continue; + } + + for (head = head->next; head != NULL; head = head->next) { + DPRINTF((stderr, "%s has dependency %s\n", fnode->filename, head->fnode->filename)); + //return (TRUE); + ndeps++; + } + } + + if (ndeps > 0) + return (TRUE); + + return (FALSE); +} + +static void +generate_parallel(void) +{ + static filenode *fnode, *fnode_next; + int nodes_done; + bool ignore_deps; + + ignore_deps = FALSE; + do { + nodes_done = 0; + for (fnode = fn_head->next; fnode != NULL; fnode = fnode_next) { + fnode_next = fnode->next; + if (ignore_deps) { + warnx("cycle detected; ignoring dependencies " + "for %s", fnode->filename); + ignore_deps = FALSE; + } else if (unsatisfied_req(fnode)) { + DPRINTF((stderr, "%s has dependencies; " + "skipping\n", fnode->filename)); + continue; + } + nodes_done++; + do_file(fnode); + } + if (nodes_done > 0) { + printf("\n"); + } else { + /* + * There are no more leaf nodes, ie nodes with no + * dependencies. This means the graph is cyclic. + * It's hard to handle this in a sensible way; just + * ignore dependencies for the next node and try again. + */ + ignore_deps = TRUE; + } + } while (fn_head->next != NULL); +} + static void generate_ordering(void) {