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/time/time.o \
 	tools/read_config_header.o \
+	tools/ccan_dir.o \
 	tools/compile.o \
 	tools/depends.o \
 	tools/tools.o

+ 15 - 5
tools/ccan_dir.c

@@ -1,4 +1,5 @@
 #include <ccan/talloc/talloc.h>
+#include <ccan/err/err.h>
 #include "tools.h"
 #include <assert.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)
 {
-	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;
 
 	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;

+ 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 virtual #DONT_USE_CPLUSPLUS_RESERVED_NAMES\n"
 		   "#include <ccan/%s/%s.h>\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);

+ 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;
 
 	/* 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))

+ 2 - 2
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;
 			}

+ 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"
 							       " did not"
 							       " build:\n%s",
-							       i->basename,
+							       i->modname,
 							       errstr);
 				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;
 
 	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;

+ 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;
 }
 
-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 <sys/stat.h>\n"
 			      "#include <sys/types.h>\n"
 			      "#include <unistd.h>\n",
-			      m->basename, m->basename);
+			      m->modname, m->basename);
 
 	ret = talloc_asprintf_append(ret, "/* Useful dummy functions. */\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 */
 		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,

+ 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"
 		    " * 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;

+ 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)
 		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);
 	}

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

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

@@ -11,48 +11,72 @@
 #include <ccan/talloc/talloc.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) {
 	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;
 	}
 

+ 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);
 
 	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))
 		err(1, "writing to temporary file %s", tmpsrc);
 	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"
 	"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 = {

+ 2 - 3
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);

+ 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);
 		tmpfd = start_file(tmp);
 		line = talloc_asprintf(score, "#include <ccan/%s/%s.h>\n",
-				       m->basename, m->basename);
+				       m->modname, m->basename);
 		write_str(tmpfd, line);
 		close(tmpfd);
 		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)
 		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)) {
 		fputs("/* Include the C files directly. */\n", run);
 		list_for_each(&m->c_files, i, list)
 			fprintf(run, "#include <ccan/%s/%s>\n",
-				m->basename, i->name);
+				m->modname, i->name);
 	}
 	fprintf(run, "%s",
 		"#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. */
 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);

+ 2 - 1
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)

+ 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->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. */

+ 3 - 1
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;