X-Git-Url: https://git.ozlabs.org/?p=ccan;a=blobdiff_plain;f=tools%2Fccanlint%2Fccanlint.c;h=1164c314ec3446637bfab88b69c972753b3fdab7;hp=001ee689df834b2e1cdc48b839d9d84a8f71d482;hb=822bce88355ced4b80ea8a0044d12cb90eaa234a;hpb=650c775ff00cccd03fc84e7789a03c51d9839004 diff --git a/tools/ccanlint/ccanlint.c b/tools/ccanlint/ccanlint.c index 001ee689..1164c314 100644 --- a/tools/ccanlint/ccanlint.c +++ b/tools/ccanlint/ccanlint.c @@ -1,6 +1,6 @@ /* * ccanlint: assorted checks and advice for a ccan package - * Copyright (C) 2008 Rusty Russell + * Copyright (C) 2008 Rusty Russell, Idris Soule * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -19,6 +19,7 @@ #include "ccanlint.h" #include #include +#include #include #include #include @@ -26,12 +27,9 @@ #include static unsigned int verbose = 0; -static LIST_HEAD(tests); - -static void init_tests(void) -{ -#include "generated-init-tests" -} +static LIST_HEAD(compulsory_tests); +static LIST_HEAD(normal_tests); +static LIST_HEAD(finished_tests); static void usage(const char *name) { @@ -67,7 +65,7 @@ bool ask(const char *question) && toupper(reply[0]) == 'Y'; } -static bool run_test(const struct ccanlint *i, +static bool run_test(struct ccanlint *i, bool summary, unsigned int *score, unsigned int *total_score, @@ -75,16 +73,22 @@ static bool run_test(const struct ccanlint *i, { void *result; unsigned int this_score; + const struct dependent *d; if (i->total_score) *total_score += i->total_score; - + //one less test to run through + list_for_each(&i->dependencies, d, node) + d->dependent->num_depends--; result = i->check(m); if (!result) { if (verbose) printf(" %s: OK\n", i->name); if (i->total_score) *score += i->total_score; + + list_del(&i->list); + list_add_tail(&finished_tests, &i->list); return true; } @@ -100,6 +104,8 @@ static bool run_test(const struct ccanlint *i, if (verbose) indent_print(i->describe(m, result)); + list_del(&i->list); + list_add_tail(&finished_tests, &i->list); return false; } @@ -107,17 +113,98 @@ static bool run_test(const struct ccanlint *i, if (i->handle) i->handle(m, result); - + list_del(&i->list); + list_add_tail(&finished_tests, &i->list); return false; } +static void register_test(struct ccanlint *test, ...) +{ + va_list ap; + struct ccanlint *depends; + struct dependent *dchild; + + if (!test->total_score) + list_add(&compulsory_tests, &test->list); + else + list_add(&normal_tests, &test->list); + + va_start(ap, test); + /* Careful: we might have been initialized by a dependent. */ + if (test->dependencies.n.next == NULL) + list_head_init(&test->dependencies); + + //dependent(s) args (if any), last one is NULL + while ((depends = va_arg(ap, struct ccanlint *)) != NULL) { + dchild = malloc(sizeof(*dchild)); + dchild->dependent = test; + /* The thing we depend on might not be initialized yet! */ + if (depends->dependencies.n.next == NULL) + list_head_init(&depends->dependencies); + list_add_tail(&depends->dependencies, &dchild->node); + test->num_depends++; + } + va_end(ap); +} + +/** + * get_next_test - retrieves the next test to be processed + **/ +static inline struct ccanlint *get_next_test(struct list_head *test) +{ + struct ccanlint *i; + + if (list_empty(test)) + return NULL; + + list_for_each(test, i, list) { + if (i->num_depends == 0) + return i; + } + errx(1, "Can't make process; test dependency cycle"); +} + +static void init_tests(void) +{ + const struct ccanlint *i; + +#undef REGISTER_TEST +#define REGISTER_TEST(name, ...) register_test(&name, __VA_ARGS__) +#include "generated-init-tests" + + if (!verbose) + return; + + printf("\nCompulsory Tests\n"); + list_for_each(&compulsory_tests, i, list) { + printf("%s depends on %u others\n", i->name, i->num_depends); + if (!list_empty(&i->dependencies)) { + const struct dependent *d; + printf("These depend on us:\n"); + list_for_each(&i->dependencies, d, node) + printf("\t%s\n", d->dependent->name); + } + } + + printf("\nNormal Tests\n"); + list_for_each(&normal_tests, i, list) { + printf("%s depends on %u others\n", i->name, i->num_depends); + if (!list_empty(&i->dependencies)) { + const struct dependent *d; + printf("These depend on us:\n"); + list_for_each(&i->dependencies, d, node) + printf("\t%s\n", d->dependent->name); + } + } +} + int main(int argc, char *argv[]) { int c; bool summary = false; unsigned int score, total_score; struct manifest *m; - const struct ccanlint *i; + struct ccanlint *i; /* I'd love to use long options, but that's not standard. */ /* FIXME: getopt_long ccan package? */ @@ -148,17 +235,19 @@ int main(int argc, char *argv[]) /* If you don't pass the compulsory tests, you don't even get a score */ if (verbose) printf("Compulsory tests:\n"); - list_for_each(&tests, i, list) - if (!i->total_score && !run_test(i, summary, NULL, NULL, m)) + + while ((i = get_next_test(&compulsory_tests)) != NULL) { + if (!run_test(i, summary, &score, &total_score, m)) exit(1); + } if (verbose) printf("\nNormal tests:\n"); score = total_score = 0; - list_for_each(&tests, i, list) + while ((i = get_next_test(&normal_tests)) != NULL) { if (i->total_score) run_test(i, summary, &score, &total_score, m); - + } printf("Total score: %u/%u\n", score, total_score); return 0;