Browse Source

tools: don't assume modules are immediately below ccan/ dir.

Removing this assumption should allow nested modules.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Rusty Russell 13 years ago
parent
commit
10e5e329a1

+ 1 - 0
tools/Makefile

@@ -11,6 +11,7 @@ DEP_OBJS = ccan/err/err.o \
 	ccan/talloc/talloc.o \
 	ccan/talloc/talloc.o \
 	ccan/time/time.o \
 	ccan/time/time.o \
 	tools/read_config_header.o \
 	tools/read_config_header.o \
+	tools/ccan_dir.o \
 	tools/compile.o \
 	tools/compile.o \
 	tools/depends.o \
 	tools/depends.o \
 	tools/tools.o
 	tools/tools.o

+ 15 - 5
tools/ccan_dir.c

@@ -1,4 +1,5 @@
 #include <ccan/talloc/talloc.h>
 #include <ccan/talloc/talloc.h>
+#include <ccan/err/err.h>
 #include "tools.h"
 #include "tools.h"
 #include <assert.h>
 #include <assert.h>
 #include <string.h>
 #include <string.h>
@@ -22,10 +23,19 @@ static unsigned int ccan_dir_prefix(const char *fulldir)
 
 
 const char *find_ccan_dir(const char *base)
 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;
 }
 }

+ 1 - 1
tools/ccanlint/licenses.c

@@ -208,7 +208,7 @@ struct doc_section *find_license_tag(const struct manifest *m)
 	struct doc_section *d;
 	struct doc_section *d;
 
 
 	list_for_each(get_ccan_file_docs(m->info_file), d, list) {
 	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;
 			continue;
 		if (streq(d->type, "license"))
 		if (streq(d->type, "license"))
 			return d;
 			return d;

+ 1 - 1
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 using #DONT_USE_CPLUSPLUS_RESERVED_NAMES\n"
 		   "#define virtual #DONT_USE_CPLUSPLUS_RESERVED_NAMES\n"
 		   "#define virtual #DONT_USE_CPLUSPLUS_RESERVED_NAMES\n"
 		   "#include <ccan/%s/%s.h>\n",
 		   "#include <ccan/%s/%s.h>\n",
-				   m->basename, m->basename);
+				   m->modname, m->basename);
 	if (write(fd, contents, strlen(contents)) != strlen(contents))
 	if (write(fd, contents, strlen(contents)) != strlen(contents))
 		err(1, "writing to temporary file %s", tmpsrc);
 		err(1, "writing to temporary file %s", tmpsrc);
 	close(fd);
 	close(fd);

+ 2 - 2
tools/ccanlint/tests/depends_accurate.c

@@ -22,7 +22,7 @@ static bool has_dep(struct manifest *m, char **deps, bool *used,
 	unsigned int i;
 	unsigned int i;
 
 
 	/* We can include ourselves, of course. */
 	/* We can include ourselves, of course. */
-	if (streq(depname + strlen("ccan/"), m->basename))
+	if (streq(depname + strlen("ccan/"), m->modname))
 		return true;
 		return true;
 
 
 	for (i = 0; deps[i]; i++) {
 	for (i = 0; deps[i]; i++) {
@@ -48,7 +48,7 @@ static bool check_dep_includes(struct manifest *m,
 		char *mod;
 		char *mod;
 		if (!strreg(f, lines[i],
 		if (!strreg(f, lines[i],
 			    "^[ \t]*#[ \t]*include[ \t]*[<\"]"
 			    "^[ \t]*#[ \t]*include[ \t]*[<\"]"
-			    "(ccan/+[^/]+)/", &mod))
+			    "(ccan/+.+)/+[^/]+.h", &mod))
 			continue;
 			continue;
 
 
 		if (has_dep(m, deps, used, mod))
 		if (has_dep(m, deps, used, mod))

+ 2 - 2
tools/ccanlint/tests/depends_build.c

@@ -47,7 +47,7 @@ static char *build_subdir_objs(struct manifest *m,
 			return talloc_asprintf(m,
 			return talloc_asprintf(m,
 					       "Dependency %s"
 					       "Dependency %s"
 					       " did not build:\n%s",
 					       " did not build:\n%s",
-					       m->basename, output);
+					       m->modname, output);
 		}
 		}
 	}
 	}
 	return NULL;
 	return NULL;
@@ -94,7 +94,7 @@ static void check_depends_built(struct manifest *m,
 							       "Dependency %s"
 							       "Dependency %s"
 							       " did not"
 							       " did not"
 							       " build:\n%s",
 							       " build:\n%s",
-							       i->basename,
+							       i->modname,
 							       errstr);
 							       errstr);
 				return;
 				return;
 			}
 			}

+ 1 - 1
tools/ccanlint/tests/depends_build_without_features.c

@@ -45,7 +45,7 @@ static void check_depends_built_without_features(struct manifest *m,
 							       "Dependency %s"
 							       "Dependency %s"
 							       " did not"
 							       " did not"
 							       " build:\n%s",
 							       " build:\n%s",
-							       i->basename,
+							       i->modname,
 							       errstr);
 							       errstr);
 				return;
 				return;
 			}
 			}

+ 2 - 2
tools/ccanlint/tests/depends_exist.c

@@ -19,7 +19,7 @@ static bool have_dep(struct manifest *m, const char *dep)
 	struct manifest *i;
 	struct manifest *i;
 
 
 	list_for_each(&m->deps, i, list)
 	list_for_each(&m->deps, i, list)
-		if (streq(i->basename, dep + strlen("ccan/")))
+		if (streq(i->modname, dep + strlen("ccan/")))
 			return true;
 			return true;
 
 
 	return false;
 	return false;
@@ -80,7 +80,7 @@ static void check_test_depends_exist(struct manifest *m,
 	bool needs_tap;
 	bool needs_tap;
 
 
 	/* We may need libtap for testing, unless we're "tap" */
 	/* We may need libtap for testing, unless we're "tap" */
-	if (streq(m->basename, "tap")) {
+	if (streq(m->modname, "tap")) {
 		needs_tap = false;
 		needs_tap = false;
 	} else if (list_empty(&m->run_tests) && list_empty(&m->api_tests)) {
 	} else if (list_empty(&m->run_tests) && list_empty(&m->api_tests)) {
 		needs_tap = false;
 		needs_tap = false;

+ 7 - 7
tools/ccanlint/tests/examples_compile.c

@@ -30,27 +30,27 @@ static void add_mod(struct manifest ***deps, struct manifest *m)
 	(*deps)[num] = 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;
 	unsigned int i;
 
 
 	for (i = 0; i < talloc_get_size(deps) / sizeof(*deps); 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 true;
 	return false;
 	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;
 	unsigned int i;
 	struct manifest *m;
 	struct manifest *m;
 	char *errstr;
 	char *errstr;
 
 
-	if (have_mod(*deps, basename))
+	if (have_mod(*deps, modname))
 		return;
 		return;
 
 
 	m = get_manifest(*deps, talloc_asprintf(*deps, "%s/ccan/%s",
 	m = get_manifest(*deps, talloc_asprintf(*deps, "%s/ccan/%s",
-						ccan_dir, basename));
+						ccan_dir, modname));
 	errstr = build_submodule(m, cflags, COMPILE_NORMAL);
 	errstr = build_submodule(m, cflags, COMPILE_NORMAL);
 	if (errstr)
 	if (errstr)
 		errx(1, "%s", 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);
 	struct manifest **deps = talloc_array(f, struct manifest *, 0);
 
 
 	/* This one for a start. */
 	/* This one for a start. */
-	add_dep(&deps, m->basename);
+	add_dep(&deps, m->modname);
 
 
 	/* Other modules implied by includes. */
 	/* Other modules implied by includes. */
 	for (lines = get_ccan_file_lines(f); *lines; lines++) {
 	for (lines = get_ccan_file_lines(f); *lines; lines++) {
@@ -362,7 +362,7 @@ static char *mangle(struct manifest *m, char **lines)
 			      "#include <sys/stat.h>\n"
 			      "#include <sys/stat.h>\n"
 			      "#include <sys/types.h>\n"
 			      "#include <sys/types.h>\n"
 			      "#include <unistd.h>\n",
 			      "#include <unistd.h>\n",
-			      m->basename, m->basename);
+			      m->modname, m->basename);
 
 
 	ret = talloc_asprintf_append(ret, "/* Useful dummy functions. */\n"
 	ret = talloc_asprintf_append(ret, "/* Useful dummy functions. */\n"
 				     "extern int somefunc(void);\n"
 				     "extern int somefunc(void);\n"

+ 2 - 2
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 */
 		/* Main header gets CCAN_FOO_H, others CCAN_FOO_XXX_H */
 		if (strstarts(e->file->name, m->basename)
 		if (strstarts(e->file->name, m->basename)
 		    || strlen(e->file->name) == strlen(m->basename) + 2)
 		    || 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
 		else
 			name = talloc_asprintf(score, "CCAN_%s_%s",
 			name = talloc_asprintf(score, "CCAN_%s_%s",
-					       m->basename, e->file->name);
+					       m->modname, e->file->name);
 		fix_name(name);
 		fix_name(name);
 
 
 		q = talloc_asprintf(score,
 		q = talloc_asprintf(score,

+ 2 - 2
tools/ccanlint/tests/info_documentation_exists.c

@@ -47,7 +47,7 @@ static void create_info_template_doc(struct manifest *m, struct score *score)
 		    " *\n"
 		    " *\n"
 		    " * Followed by an Example: section with a standalone\n"
 		    " * Followed by an Example: section with a standalone\n"
 		    " * (trivial and usually useless) program\n"
 		    " * (trivial and usually useless) program\n"
-		    " */\n", m->basename, m->basename) < 0) {
+		    " */\n", m->modname, m->basename) < 0) {
 		unlink_noerr("_info.new");
 		unlink_noerr("_info.new");
 		err(1, "Writing to _info.new to insert documentation");
 		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;
 	score->pass = true;
 
 
 	list_for_each(infodocs, d, list) {
 	list_for_each(infodocs, d, list) {
-		if (!streq(d->function, m->basename))
+		if (!streq(d->function, m->modname))
 			continue;
 			continue;
 		if (streq(d->type, "summary"))
 		if (streq(d->type, "summary"))
 			summary = true;
 			summary = true;

+ 1 - 1
tools/ccanlint/tests/info_exists.c

@@ -68,7 +68,7 @@ static void create_info_template(struct manifest *m, struct score *score)
 	if (!info)
 	if (!info)
 		err(1, "Trying to create a template _info in %s", filename);
 		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);
 		unlink_noerr(filename);
 		err(1, "Writing template into %s", filename);
 		err(1, "Writing template into %s", filename);
 	}
 	}

+ 1 - 1
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,
 			score_file_error(score, i->info_file, 0,
 					 "Dependency ccan/%s has"
 					 "Dependency ccan/%s has"
 					 " incompatible license '%s'",
 					 " incompatible license '%s'",
-					 i->basename,
+					 i->modname,
 					 licenses[i->license].name);
 					 licenses[i->license].name);
 			score->pass = false;
 			score->pass = false;
 		}
 		}

+ 39 - 15
tools/ccanlint/tests/license_exists.c

@@ -11,48 +11,72 @@
 #include <ccan/talloc/talloc.h>
 #include <ccan/talloc/talloc.h>
 #include <ccan/str/str.h>
 #include <ccan/str/str.h>
 
 
-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) {
 	switch (license) {
 	case LICENSE_LGPLv2_PLUS:
 	case LICENSE_LGPLv2_PLUS:
 	case LICENSE_LGPLv2:
 	case LICENSE_LGPLv2:
-		return "../../licenses/LGPL-2.1";
+		shortname = "LGPL-2.1";
+		break;
 	case LICENSE_LGPLv3:
 	case LICENSE_LGPLv3:
 	case LICENSE_LGPL:
 	case LICENSE_LGPL:
-		return "../../licenses/LGPL-3";
+		shortname = "LGPL-3";
+		break;
 
 
 	case LICENSE_GPLv2_PLUS:
 	case LICENSE_GPLv2_PLUS:
 	case LICENSE_GPLv2:
 	case LICENSE_GPLv2:
-		return "../../licenses/GPL-2";
+		shortname = "GPL-2";
+		break;
 
 
 	case LICENSE_GPLv3:
 	case LICENSE_GPLv3:
 	case LICENSE_GPL:
 	case LICENSE_GPL:
-		return "../../licenses/GPL-3";
+		shortname = "GPL-3";
+		break;
 
 
 	case LICENSE_BSD:
 	case LICENSE_BSD:
-		return "../../licenses/BSD-3CLAUSE";
+		shortname = "BSD-3CLAUSE";
+		break;
 
 
 	case LICENSE_MIT:
 	case LICENSE_MIT:
-		return "../../licenses/BSD-MIT";
+		shortname = "BSD-MIT";
+		break;
 
 
 	case LICENSE_CC0:
 	case LICENSE_CC0:
-		return "../../licenses/CC0";
+		shortname = "CC0";
+		break;
 
 
 	default:
 	default:
 		return NULL;
 		return NULL;
 	}
 	}
+
+	return talloc_append_string(talloc_strdup(prefix, prefix), shortname);
 }
 }
 
 
 static void handle_license_link(struct manifest *m, struct score *score)
 static void handle_license_link(struct manifest *m, struct score *score)
 {
 {
 	struct doc_section *d = find_license_tag(m);
 	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 *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;
 	char *q;
 
 
 	printf(
 	printf(
 	"Most modules want a copy of their license, so usually we create a\n"
 	"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 */
 	/* FIXME: make ask printf-like */
 	q = talloc_asprintf(m, "Set up link to %s (license is %s)?",
 	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);
 	char *license = talloc_asprintf(m, "%s/LICENSE", m->dir);
 	const char *expected;
 	const char *expected;
 	struct doc_section *d;
 	struct doc_section *d;
+	const char *prefix = link_prefix(m);
 
 
 	d = find_license_tag(m);
 	d = find_license_tag(m);
 	if (!d) {
 	if (!d) {
@@ -93,7 +118,7 @@ static void check_has_license(struct manifest *m,
 	/* If they have a license tag at all, we pass. */
 	/* If they have a license tag at all, we pass. */
 	score->pass = true;
 	score->pass = true;
 
 
-	expected = expected_link(m->license);
+	expected = expected_link(prefix, m->license);
 
 
 	len = readlink(license, buf, sizeof(buf));
 	len = readlink(license, buf, sizeof(buf));
 	if (len < 0) {
 	if (len < 0) {
@@ -129,11 +154,10 @@ static void check_has_license(struct manifest *m,
 
 
 	buf[len] = '\0';
 	buf[len] = '\0';
 
 
-	if (!strstarts(buf, "../../licenses/")) {
+	if (!strstarts(buf, prefix)) {
 		score->error = talloc_asprintf(score,
 		score->error = talloc_asprintf(score,
-					       "Expected symlink to"
-					       " ../../licenses/..."
-					       " not %s", buf);
+					       "Expected symlink into"
+					       " %s not %s", prefix, buf);
 		return;
 		return;
 	}
 	}
 
 

+ 1 - 1
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);
 		err(1, "Creating temporary file %s", tmpsrc);
 
 
 	contents = talloc_asprintf(tmpsrc, "#include <ccan/%s/%s.h>\n",
 	contents = talloc_asprintf(tmpsrc, "#include <ccan/%s/%s.h>\n",
-				   m->basename, m->basename);
+				   m->modname, m->basename);
 	if (write(fd, contents, strlen(contents)) != strlen(contents))
 	if (write(fd, contents, strlen(contents)) != strlen(contents))
 		err(1, "writing to temporary file %s", tmpsrc);
 		err(1, "writing to temporary file %s", tmpsrc);
 	close(fd);
 	close(fd);

+ 1 - 1
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"
 	"You have no %s/%s.h header file.\n\n"
 	"CCAN modules have a name, the same as the directory name.  They're\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",
 	"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 = {
 struct ccanlint main_header_exists = {

+ 2 - 3
tools/ccanlint/tests/module_links.c

@@ -58,10 +58,9 @@ static void check_use_build(struct manifest *m,
 {
 {
 	char *contents;
 	char *contents;
 	char *tmpfile, *cmdout;
 	char *tmpfile, *cmdout;
-	char *basename = talloc_asprintf(m, "%s/example.c", m->dir);
 	int fd;
 	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);
 	fd = open(tmpfile, O_WRONLY | O_CREAT | O_EXCL, 0600);
 	if (fd < 0)
 	if (fd < 0)
@@ -73,7 +72,7 @@ static void check_use_build(struct manifest *m,
 				   "{\n"
 				   "{\n"
 				   "	return 0;\n"
 				   "	return 0;\n"
 				   "}\n",
 				   "}\n",
-				   m->basename, m->basename);
+				   m->modname, m->basename);
 	if (write(fd, contents, strlen(contents)) != strlen(contents))
 	if (write(fd, contents, strlen(contents)) != strlen(contents))
 		err(1, "Failure writing to temporary file %s", tmpfile);
 		err(1, "Failure writing to temporary file %s", tmpfile);
 	close(fd);
 	close(fd);

+ 1 - 1
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);
 		tmp = temp_file(score, ".c", i->fullname);
 		tmpfd = start_file(tmp);
 		tmpfd = start_file(tmp);
 		line = talloc_asprintf(score, "#include <ccan/%s/%s.h>\n",
 		line = talloc_asprintf(score, "#include <ccan/%s/%s.h>\n",
-				       m->basename, m->basename);
+				       m->modname, m->basename);
 		write_str(tmpfd, line);
 		write_str(tmpfd, line);
 		close(tmpfd);
 		close(tmpfd);
 		test_compile(score, i, tmp, flags, &errors, &warnings);
 		test_compile(score, i, tmp, flags, &errors, &warnings);

+ 2 - 2
tools/ccanlint/tests/tests_exist.c

@@ -69,12 +69,12 @@ static void handle_no_tests(struct manifest *m, struct score *score)
 	if (!run)
 	if (!run)
 		err(1, "Trying to create a test/run.c");
 		err(1, "Trying to create a test/run.c");
 
 
-	fprintf(run, "#include <ccan/%s/%s.h>\n", m->basename, m->basename);
+	fprintf(run, "#include <ccan/%s/%s.h>\n", m->modname, m->basename);
 	if (!list_empty(&m->c_files)) {
 	if (!list_empty(&m->c_files)) {
 		fputs("/* Include the C files directly. */\n", run);
 		fputs("/* Include the C files directly. */\n", run);
 		list_for_each(&m->c_files, i, list)
 		list_for_each(&m->c_files, i, list)
 			fprintf(run, "#include <ccan/%s/%s>\n",
 			fprintf(run, "#include <ccan/%s/%s>\n",
-				m->basename, i->name);
+				m->modname, i->name);
 	}
 	}
 	fprintf(run, "%s",
 	fprintf(run, "%s",
 		"#include <ccan/tap/tap.h>\n\n"
 		"#include <ccan/tap/tap.h>\n\n"

+ 4 - 10
tools/depends.c

@@ -40,7 +40,7 @@ lines_from_cmd(const void *ctx, const char *format, ...)
  * temp_file helps here. */
  * temp_file helps here. */
 char *compile_info(const void *ctx, const char *dir)
 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;
 	size_t len;
 	int fd;
 	int fd;
 
 
@@ -59,12 +59,8 @@ char *compile_info(const void *ctx, const char *dir)
 	if (close(fd) != 0)
 	if (close(fd) != 0)
 		return NULL;
 		return NULL;
 
 
-	ccandir = talloc_dirname(ctx, dir);
-	if (strrchr(ccandir, '/'))
-		*strrchr(ccandir, '/') = '\0';
-
 	compiled = temp_file(ctx, "", "info");
 	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.", "",
 			     CCAN_COMPILER, CCAN_CFLAGS " -I.", "",
 			     compiled, &output))
 			     compiled, &output))
 		return compiled;
 		return compiled;
@@ -209,8 +205,7 @@ get_all_deps(const void *ctx, const char *dir, const char *style,
 			continue;
 			continue;
 
 
 		subdir = talloc_asprintf(ctx, "%s/%s",
 		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);
 		newdeps = get_one(ctx, subdir, "depends", get_info);
 
 
 		/* Should be short, so brute-force out dups. */
 		/* 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;
 				continue;
 
 
 			subdir = talloc_asprintf(ctx, "%s/%s",
 			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);
 			newlibs = get_one_libs(ctx, subdir, get_info);
 			newlen = talloc_array_length(newlibs);
 			newlen = talloc_array_length(newlibs);

+ 2 - 1
tools/doc_extract-core.c

@@ -71,7 +71,8 @@ static unsigned int is_summary_line(const char *line)
 {
 {
 	unsigned int id_len;
 	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)
 	if (id_len == 0)
 		return 0;
 		return 0;
 	if (strspn(line, " ") == id_len)
 	if (strspn(line, " ") == id_len)

+ 4 - 0
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->deps);
 	list_head_init(&m->test_deps);
 	list_head_init(&m->test_deps);
 
 
+	/* Trim trailing /. */
 	len = strlen(m->dir);
 	len = strlen(m->dir);
 	while (len && m->dir[len-1] == '/')
 	while (len && m->dir[len-1] == '/')
 		m->dir[--len] = '\0';
 		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");
 		errx(1, "I don't expect to be run from the root directory");
 	m->basename++;
 	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, "");
 	add_files(m, "");
 
 
 	/* Nicer to run tests in a predictable order. */
 	/* Nicer to run tests in a predictable order. */

+ 3 - 1
tools/manifest.h

@@ -13,7 +13,9 @@ enum compile_type {
 
 
 struct manifest {
 struct manifest {
 	char *dir;
 	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;
 	char *basename;
 	struct ccan_file *info_file;
 	struct ccan_file *info_file;