+ char *cmd, **lines;
+
+ cmd = talloc_asprintf(ctx, "%s libs", get_info(ctx, dir));
+ lines = lines_from_cmd(cmd, "%s", cmd);
+ /* Strip final NULL. */
+ if (lines)
+ lines = talloc_realloc(NULL, lines, char *,
+ talloc_array_length(lines)-1);
+ return lines;
+}
+
+/* O(n^2) but n is small. */
+static char **add_deps(char **deps1, char **deps2)
+{
+ unsigned int i, len;
+
+ len = talloc_array_length(deps1);
+
+ for (i = 0; deps2[i]; i++) {
+ if (have_dep(deps1, deps2[i]))
+ continue;
+ deps1 = talloc_realloc(NULL, deps1, char *, len + 1);
+ deps1[len-1] = talloc_steal(deps1, deps2[i]);
+ deps1[len++] = NULL;
+ }
+ return deps1;
+}
+
+char **get_libs(const void *ctx, const char *dir, const char *style,
+ char *(*get_info)(const void *ctx, const char *dir))
+{
+ char **deps, **libs;
+ unsigned int i, len;
+
+ libs = get_one_libs(ctx, dir, get_info);
+ len = talloc_array_length(libs);
+
+ if (style) {
+ deps = get_deps(ctx, dir, style, true, get_info);
+ if (streq(style, "testdepends"))
+ deps = add_deps(deps,
+ get_deps(ctx, dir, "depends", true,
+ get_info));
+
+ for (i = 0; deps[i]; i++) {
+ char **newlibs, *subdir;
+ size_t newlen;
+
+ if (!strstarts(deps[i], "ccan/"))
+ continue;
+
+ subdir = talloc_asprintf(ctx, "%s/%s",
+ talloc_dirname(ctx, dir),
+ deps[i] + strlen("ccan/"));
+
+ newlibs = get_one_libs(ctx, subdir, get_info);
+ newlen = talloc_array_length(newlibs);
+ libs = talloc_realloc(ctx, libs, char *, len + newlen);
+ memcpy(&libs[len], newlibs,
+ sizeof(newlibs[0])*newlen);
+ len += newlen;
+ }
+ }
+
+ /* Append NULL entry. */
+ libs = talloc_realloc(ctx, libs, char *, len + 1);
+ libs[len] = NULL;
+ return libs;
+}
+
+/* FIXME: This is O(n^2), which is dumb. */
+static char **uniquify_deps(char **deps)
+{
+ unsigned int i, j, num;
+
+ if (!deps)
+ return NULL;
+
+ num = talloc_array_length(deps) - 1;
+ for (i = 0; i < num; i++) {
+ for (j = i + 1; j < num; j++) {
+ if (streq(deps[i], deps[j])) {
+ memmove(&deps[j], &deps[j+1],
+ (num - j - 1) * sizeof(char *));
+ num--;
+ }
+ }