From: Rusty Russell Date: Thu, 22 Nov 2012 00:32:19 +0000 (+1030) Subject: tools: don't assume modules are immediately below ccan/ dir. X-Git-Url: http://git.ozlabs.org/?p=ccan;a=commitdiff_plain;h=10e5e329a1a8804ff6461e1724071364cf6be572 tools: don't assume modules are immediately below ccan/ dir. Removing this assumption should allow nested modules. Signed-off-by: Rusty Russell --- diff --git a/tools/Makefile b/tools/Makefile index c60f0696..d3d1904e 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -11,6 +11,7 @@ DEP_OBJS = ccan/err/err.o \ ccan/talloc/talloc.o \ ccan/time/time.o \ tools/read_config_header.o \ + tools/ccan_dir.o \ tools/compile.o \ tools/depends.o \ tools/tools.o diff --git a/tools/ccan_dir.c b/tools/ccan_dir.c index 0bb9b144..56148868 100644 --- a/tools/ccan_dir.c +++ b/tools/ccan_dir.c @@ -1,4 +1,5 @@ #include +#include #include "tools.h" #include #include @@ -22,10 +23,19 @@ static unsigned int ccan_dir_prefix(const char *fulldir) const char *find_ccan_dir(const char *base) { - unsigned int prefix = ccan_dir_prefix(base); + static char *ccan_dir; - if (!prefix) - return NULL; - - return talloc_strndup(NULL, base, prefix); + if (!ccan_dir) { + if (base[0] != '/') { + const char *tmpctx = talloc_getcwd(NULL); + find_ccan_dir(talloc_asprintf(tmpctx, "%s/%s", + tmpctx, base)); + talloc_free(tmpctx); + } else { + unsigned int prefix = ccan_dir_prefix(base); + if (prefix) + ccan_dir = talloc_strndup(NULL, base, prefix); + } + } + return ccan_dir; } diff --git a/tools/ccanlint/licenses.c b/tools/ccanlint/licenses.c index ff786de8..ac62ad34 100644 --- a/tools/ccanlint/licenses.c +++ b/tools/ccanlint/licenses.c @@ -208,7 +208,7 @@ struct doc_section *find_license_tag(const struct manifest *m) struct doc_section *d; list_for_each(get_ccan_file_docs(m->info_file), d, list) { - if (!streq(d->function, m->basename)) + if (!streq(d->function, m->modname)) continue; if (streq(d->type, "license")) return d; diff --git a/tools/ccanlint/tests/avoids_cpp_reserved.c b/tools/ccanlint/tests/avoids_cpp_reserved.c index 72b3604e..e094f270 100644 --- a/tools/ccanlint/tests/avoids_cpp_reserved.c +++ b/tools/ccanlint/tests/avoids_cpp_reserved.c @@ -85,7 +85,7 @@ static void check_headers_no_cpp(struct manifest *m, "#define using #DONT_USE_CPLUSPLUS_RESERVED_NAMES\n" "#define virtual #DONT_USE_CPLUSPLUS_RESERVED_NAMES\n" "#include \n", - m->basename, m->basename); + m->modname, m->basename); if (write(fd, contents, strlen(contents)) != strlen(contents)) err(1, "writing to temporary file %s", tmpsrc); close(fd); diff --git a/tools/ccanlint/tests/depends_accurate.c b/tools/ccanlint/tests/depends_accurate.c index 2a47d0eb..83a19e2c 100644 --- a/tools/ccanlint/tests/depends_accurate.c +++ b/tools/ccanlint/tests/depends_accurate.c @@ -22,7 +22,7 @@ static bool has_dep(struct manifest *m, char **deps, bool *used, unsigned int i; /* We can include ourselves, of course. */ - if (streq(depname + strlen("ccan/"), m->basename)) + if (streq(depname + strlen("ccan/"), m->modname)) return true; for (i = 0; deps[i]; i++) { @@ -48,7 +48,7 @@ static bool check_dep_includes(struct manifest *m, char *mod; if (!strreg(f, lines[i], "^[ \t]*#[ \t]*include[ \t]*[<\"]" - "(ccan/+[^/]+)/", &mod)) + "(ccan/+.+)/+[^/]+.h", &mod)) continue; if (has_dep(m, deps, used, mod)) diff --git a/tools/ccanlint/tests/depends_build.c b/tools/ccanlint/tests/depends_build.c index b578d4b5..3cfb9c44 100644 --- a/tools/ccanlint/tests/depends_build.c +++ b/tools/ccanlint/tests/depends_build.c @@ -47,7 +47,7 @@ static char *build_subdir_objs(struct manifest *m, return talloc_asprintf(m, "Dependency %s" " did not build:\n%s", - m->basename, output); + m->modname, output); } } return NULL; @@ -94,7 +94,7 @@ static void check_depends_built(struct manifest *m, "Dependency %s" " did not" " build:\n%s", - i->basename, + i->modname, errstr); return; } diff --git a/tools/ccanlint/tests/depends_build_without_features.c b/tools/ccanlint/tests/depends_build_without_features.c index faa3b21d..b75ebefd 100644 --- a/tools/ccanlint/tests/depends_build_without_features.c +++ b/tools/ccanlint/tests/depends_build_without_features.c @@ -45,7 +45,7 @@ static void check_depends_built_without_features(struct manifest *m, "Dependency %s" " did not" " build:\n%s", - i->basename, + i->modname, errstr); return; } diff --git a/tools/ccanlint/tests/depends_exist.c b/tools/ccanlint/tests/depends_exist.c index 76750fb1..3d50a063 100644 --- a/tools/ccanlint/tests/depends_exist.c +++ b/tools/ccanlint/tests/depends_exist.c @@ -19,7 +19,7 @@ static bool have_dep(struct manifest *m, const char *dep) struct manifest *i; list_for_each(&m->deps, i, list) - if (streq(i->basename, dep + strlen("ccan/"))) + if (streq(i->modname, dep + strlen("ccan/"))) return true; return false; @@ -80,7 +80,7 @@ static void check_test_depends_exist(struct manifest *m, bool needs_tap; /* We may need libtap for testing, unless we're "tap" */ - if (streq(m->basename, "tap")) { + if (streq(m->modname, "tap")) { needs_tap = false; } else if (list_empty(&m->run_tests) && list_empty(&m->api_tests)) { needs_tap = false; diff --git a/tools/ccanlint/tests/examples_compile.c b/tools/ccanlint/tests/examples_compile.c index ac9476fd..ce1d9769 100644 --- a/tools/ccanlint/tests/examples_compile.c +++ b/tools/ccanlint/tests/examples_compile.c @@ -30,27 +30,27 @@ static void add_mod(struct manifest ***deps, struct manifest *m) (*deps)[num] = m; } -static bool have_mod(struct manifest *deps[], const char *basename) +static bool have_mod(struct manifest *deps[], const char *modname) { unsigned int i; for (i = 0; i < talloc_get_size(deps) / sizeof(*deps); i++) - if (strcmp(deps[i]->basename, basename) == 0) + if (strcmp(deps[i]->modname, modname) == 0) return true; return false; } -static void add_dep(struct manifest ***deps, const char *basename) +static void add_dep(struct manifest ***deps, const char *modname) { unsigned int i; struct manifest *m; char *errstr; - if (have_mod(*deps, basename)) + if (have_mod(*deps, modname)) return; m = get_manifest(*deps, talloc_asprintf(*deps, "%s/ccan/%s", - ccan_dir, basename)); + ccan_dir, modname)); errstr = build_submodule(m, cflags, COMPILE_NORMAL); if (errstr) errx(1, "%s", errstr); @@ -79,7 +79,7 @@ static struct manifest **get_example_deps(struct manifest *m, struct manifest **deps = talloc_array(f, struct manifest *, 0); /* This one for a start. */ - add_dep(&deps, m->basename); + add_dep(&deps, m->modname); /* Other modules implied by includes. */ for (lines = get_ccan_file_lines(f); *lines; lines++) { @@ -362,7 +362,7 @@ static char *mangle(struct manifest *m, char **lines) "#include \n" "#include \n" "#include \n", - m->basename, m->basename); + m->modname, m->basename); ret = talloc_asprintf_append(ret, "/* Useful dummy functions. */\n" "extern int somefunc(void);\n" diff --git a/tools/ccanlint/tests/headers_idempotent.c b/tools/ccanlint/tests/headers_idempotent.c index bf8c9f2d..4e41d058 100644 --- a/tools/ccanlint/tests/headers_idempotent.c +++ b/tools/ccanlint/tests/headers_idempotent.c @@ -46,10 +46,10 @@ static void handle_idem(struct manifest *m, struct score *score) /* Main header gets CCAN_FOO_H, others CCAN_FOO_XXX_H */ if (strstarts(e->file->name, m->basename) || strlen(e->file->name) == strlen(m->basename) + 2) - name = talloc_asprintf(score, "CCAN_%s_H", m->basename); + name = talloc_asprintf(score, "CCAN_%s_H", m->modname); else name = talloc_asprintf(score, "CCAN_%s_%s", - m->basename, e->file->name); + m->modname, e->file->name); fix_name(name); q = talloc_asprintf(score, diff --git a/tools/ccanlint/tests/info_documentation_exists.c b/tools/ccanlint/tests/info_documentation_exists.c index 93954c76..0c0ed451 100644 --- a/tools/ccanlint/tests/info_documentation_exists.c +++ b/tools/ccanlint/tests/info_documentation_exists.c @@ -47,7 +47,7 @@ static void create_info_template_doc(struct manifest *m, struct score *score) " *\n" " * Followed by an Example: section with a standalone\n" " * (trivial and usually useless) program\n" - " */\n", m->basename, m->basename) < 0) { + " */\n", m->modname, m->basename) < 0) { unlink_noerr("_info.new"); err(1, "Writing to _info.new to insert documentation"); } @@ -83,7 +83,7 @@ static void check_info_documentation_exists(struct manifest *m, score->pass = true; list_for_each(infodocs, d, list) { - if (!streq(d->function, m->basename)) + if (!streq(d->function, m->modname)) continue; if (streq(d->type, "summary")) summary = true; diff --git a/tools/ccanlint/tests/info_exists.c b/tools/ccanlint/tests/info_exists.c index 330749ba..a667c081 100644 --- a/tools/ccanlint/tests/info_exists.c +++ b/tools/ccanlint/tests/info_exists.c @@ -68,7 +68,7 @@ static void create_info_template(struct manifest *m, struct score *score) if (!info) err(1, "Trying to create a template _info in %s", filename); - if (fprintf(info, template, m->basename) < 0) { + if (fprintf(info, template, m->modname) < 0) { unlink_noerr(filename); err(1, "Writing template into %s", filename); } diff --git a/tools/ccanlint/tests/license_depends_compat.c b/tools/ccanlint/tests/license_depends_compat.c index 6517a7fc..f04b4638 100644 --- a/tools/ccanlint/tests/license_depends_compat.c +++ b/tools/ccanlint/tests/license_depends_compat.c @@ -36,7 +36,7 @@ static void check_license_depends_compat(struct manifest *m, score_file_error(score, i->info_file, 0, "Dependency ccan/%s has" " incompatible license '%s'", - i->basename, + i->modname, licenses[i->license].name); score->pass = false; } diff --git a/tools/ccanlint/tests/license_exists.c b/tools/ccanlint/tests/license_exists.c index 53071c63..6305d61c 100644 --- a/tools/ccanlint/tests/license_exists.c +++ b/tools/ccanlint/tests/license_exists.c @@ -11,48 +11,72 @@ #include #include -static const char *expected_link(enum license license) +/* We might need more ../ for nested modules. */ +static const char *link_prefix(struct manifest *m) { + char *prefix = talloc_strdup(m, "../../"); + unsigned int i; + + for (i = 0; i < strcount(m->modname, "/"); i++) + prefix = talloc_append_string(prefix, "../"); + + return talloc_append_string(prefix, "licenses/"); +} + +static const char *expected_link(const char *prefix, enum license license) +{ + const char *shortname; + switch (license) { case LICENSE_LGPLv2_PLUS: case LICENSE_LGPLv2: - return "../../licenses/LGPL-2.1"; + shortname = "LGPL-2.1"; + break; case LICENSE_LGPLv3: case LICENSE_LGPL: - return "../../licenses/LGPL-3"; + shortname = "LGPL-3"; + break; case LICENSE_GPLv2_PLUS: case LICENSE_GPLv2: - return "../../licenses/GPL-2"; + shortname = "GPL-2"; + break; case LICENSE_GPLv3: case LICENSE_GPL: - return "../../licenses/GPL-3"; + shortname = "GPL-3"; + break; case LICENSE_BSD: - return "../../licenses/BSD-3CLAUSE"; + shortname = "BSD-3CLAUSE"; + break; case LICENSE_MIT: - return "../../licenses/BSD-MIT"; + shortname = "BSD-MIT"; + break; case LICENSE_CC0: - return "../../licenses/CC0"; + shortname = "CC0"; + break; default: return NULL; } + + return talloc_append_string(talloc_strdup(prefix, prefix), shortname); } static void handle_license_link(struct manifest *m, struct score *score) { struct doc_section *d = find_license_tag(m); + const char *prefix = link_prefix(m); const char *link = talloc_asprintf(m, "%s/LICENSE", m->dir); - const char *ldest = expected_link(m->license); + const char *ldest = expected_link(prefix, m->license); char *q; printf( "Most modules want a copy of their license, so usually we create a\n" - "LICENSE symlink into ../../licenses to avoid too many copies.\n"); + "LICENSE symlink into %s to avoid too many copies.\n", prefix); /* FIXME: make ask printf-like */ q = talloc_asprintf(m, "Set up link to %s (license is %s)?", @@ -73,6 +97,7 @@ static void check_has_license(struct manifest *m, char *license = talloc_asprintf(m, "%s/LICENSE", m->dir); const char *expected; struct doc_section *d; + const char *prefix = link_prefix(m); d = find_license_tag(m); if (!d) { @@ -93,7 +118,7 @@ static void check_has_license(struct manifest *m, /* If they have a license tag at all, we pass. */ score->pass = true; - expected = expected_link(m->license); + expected = expected_link(prefix, m->license); len = readlink(license, buf, sizeof(buf)); if (len < 0) { @@ -129,11 +154,10 @@ static void check_has_license(struct manifest *m, buf[len] = '\0'; - if (!strstarts(buf, "../../licenses/")) { + if (!strstarts(buf, prefix)) { score->error = talloc_asprintf(score, - "Expected symlink to" - " ../../licenses/..." - " not %s", buf); + "Expected symlink into" + " %s not %s", prefix, buf); return; } diff --git a/tools/ccanlint/tests/main_header_compiles.c b/tools/ccanlint/tests/main_header_compiles.c index b4a12e13..c6c51837 100644 --- a/tools/ccanlint/tests/main_header_compiles.c +++ b/tools/ccanlint/tests/main_header_compiles.c @@ -51,7 +51,7 @@ static void check_includes_build(struct manifest *m, err(1, "Creating temporary file %s", tmpsrc); contents = talloc_asprintf(tmpsrc, "#include \n", - m->basename, m->basename); + m->modname, m->basename); if (write(fd, contents, strlen(contents)) != strlen(contents)) err(1, "writing to temporary file %s", tmpsrc); close(fd); diff --git a/tools/ccanlint/tests/main_header_exists.c b/tools/ccanlint/tests/main_header_exists.c index f039a188..cdb01149 100644 --- a/tools/ccanlint/tests/main_header_exists.c +++ b/tools/ccanlint/tests/main_header_exists.c @@ -29,7 +29,7 @@ static void check_has_main_header(struct manifest *m, "You have no %s/%s.h header file.\n\n" "CCAN modules have a name, the same as the directory name. They're\n" "expected to have an interface in the header of the same name.\n", - m->basename, m->basename); + m->modname, m->basename); } struct ccanlint main_header_exists = { diff --git a/tools/ccanlint/tests/module_links.c b/tools/ccanlint/tests/module_links.c index d665ba7d..5c25e612 100644 --- a/tools/ccanlint/tests/module_links.c +++ b/tools/ccanlint/tests/module_links.c @@ -58,10 +58,9 @@ static void check_use_build(struct manifest *m, { char *contents; char *tmpfile, *cmdout; - char *basename = talloc_asprintf(m, "%s/example.c", m->dir); int fd; - tmpfile = temp_file(m, ".c", basename); + tmpfile = temp_file(m, ".c", "example.c"); fd = open(tmpfile, O_WRONLY | O_CREAT | O_EXCL, 0600); if (fd < 0) @@ -73,7 +72,7 @@ static void check_use_build(struct manifest *m, "{\n" " return 0;\n" "}\n", - m->basename, m->basename); + m->modname, m->basename); if (write(fd, contents, strlen(contents)) != strlen(contents)) err(1, "Failure writing to temporary file %s", tmpfile); close(fd); diff --git a/tools/ccanlint/tests/objects_build_with_stringchecks.c b/tools/ccanlint/tests/objects_build_with_stringchecks.c index 9aa6fd84..c2fe1b6c 100644 --- a/tools/ccanlint/tests/objects_build_with_stringchecks.c +++ b/tools/ccanlint/tests/objects_build_with_stringchecks.c @@ -112,7 +112,7 @@ static void build_objects_with_stringchecks(struct manifest *m, tmp = temp_file(score, ".c", i->fullname); tmpfd = start_file(tmp); line = talloc_asprintf(score, "#include \n", - m->basename, m->basename); + m->modname, m->basename); write_str(tmpfd, line); close(tmpfd); test_compile(score, i, tmp, flags, &errors, &warnings); diff --git a/tools/ccanlint/tests/tests_exist.c b/tools/ccanlint/tests/tests_exist.c index efa99753..a90ce0c0 100644 --- a/tools/ccanlint/tests/tests_exist.c +++ b/tools/ccanlint/tests/tests_exist.c @@ -69,12 +69,12 @@ static void handle_no_tests(struct manifest *m, struct score *score) if (!run) err(1, "Trying to create a test/run.c"); - fprintf(run, "#include \n", m->basename, m->basename); + fprintf(run, "#include \n", m->modname, m->basename); if (!list_empty(&m->c_files)) { fputs("/* Include the C files directly. */\n", run); list_for_each(&m->c_files, i, list) fprintf(run, "#include \n", - m->basename, i->name); + m->modname, i->name); } fprintf(run, "%s", "#include \n\n" diff --git a/tools/depends.c b/tools/depends.c index 3dcd9d38..a7c353c2 100644 --- a/tools/depends.c +++ b/tools/depends.c @@ -40,7 +40,7 @@ lines_from_cmd(const void *ctx, const char *format, ...) * temp_file helps here. */ char *compile_info(const void *ctx, const char *dir) { - char *info_c_file, *info, *ccandir, *compiled, *output; + char *info_c_file, *info, *compiled, *output; size_t len; int fd; @@ -59,12 +59,8 @@ char *compile_info(const void *ctx, const char *dir) if (close(fd) != 0) return NULL; - ccandir = talloc_dirname(ctx, dir); - if (strrchr(ccandir, '/')) - *strrchr(ccandir, '/') = '\0'; - compiled = temp_file(ctx, "", "info"); - if (compile_and_link(ctx, info_c_file, ccandir, "", + if (compile_and_link(ctx, info_c_file, find_ccan_dir(dir), "", CCAN_COMPILER, CCAN_CFLAGS " -I.", "", compiled, &output)) return compiled; @@ -209,8 +205,7 @@ get_all_deps(const void *ctx, const char *dir, const char *style, continue; subdir = talloc_asprintf(ctx, "%s/%s", - talloc_dirname(ctx, dir), - deps[i] + strlen("ccan/")); + find_ccan_dir(dir), deps[i]); newdeps = get_one(ctx, subdir, "depends", get_info); /* Should be short, so brute-force out dups. */ @@ -285,8 +280,7 @@ char **get_libs(const void *ctx, const char *dir, const char *style, continue; subdir = talloc_asprintf(ctx, "%s/%s", - talloc_dirname(ctx, dir), - deps[i] + strlen("ccan/")); + find_ccan_dir(dir), deps[i]); newlibs = get_one_libs(ctx, subdir, get_info); newlen = talloc_array_length(newlibs); diff --git a/tools/doc_extract-core.c b/tools/doc_extract-core.c index 74643a04..7788fd07 100644 --- a/tools/doc_extract-core.c +++ b/tools/doc_extract-core.c @@ -71,7 +71,8 @@ static unsigned int is_summary_line(const char *line) { unsigned int id_len; - id_len = strspn(line, IDENT_CHARS" "); + /* We allow /, because it can be in (nested) module names. */ + id_len = strspn(line, IDENT_CHARS" /"); if (id_len == 0) return 0; if (strspn(line, " ") == id_len) diff --git a/tools/manifest.c b/tools/manifest.c index 4cf540bd..cf4c987e 100644 --- a/tools/manifest.c +++ b/tools/manifest.c @@ -239,6 +239,7 @@ struct manifest *get_manifest(const void *ctx, const char *dir) list_head_init(&m->deps); list_head_init(&m->test_deps); + /* Trim trailing /. */ len = strlen(m->dir); while (len && m->dir[len-1] == '/') m->dir[--len] = '\0'; @@ -248,6 +249,9 @@ struct manifest *get_manifest(const void *ctx, const char *dir) errx(1, "I don't expect to be run from the root directory"); m->basename++; + assert(strstarts(m->dir, find_ccan_dir(m->dir))); + m->modname = m->dir + strlen(find_ccan_dir(m->dir)) + strlen("ccan/"); + add_files(m, ""); /* Nicer to run tests in a predictable order. */ diff --git a/tools/manifest.h b/tools/manifest.h index 04f88d9e..3b6eb207 100644 --- a/tools/manifest.h +++ b/tools/manifest.h @@ -13,7 +13,9 @@ enum compile_type { struct manifest { char *dir; - /* The module name, ie. final element of dir name */ + /* The name of the module, ie. elements of dir name after ccan/. */ + char *modname; + /* The final element of dir name */ char *basename; struct ccan_file *info_file;