aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/librarian.c101
1 files changed, 87 insertions, 14 deletions
diff --git a/src/librarian.c b/src/librarian.c
index 5ee0970..8ed9f74 100644
--- a/src/librarian.c
+++ b/src/librarian.c
@@ -78,12 +78,43 @@ struct library {
};
+/**
+ * Structure for already located librarian files.
+ */
+struct found_file {
+ /**
+ * The name of the library.
+ */
+ const char *name;
+
+ /**
+ * The found version of the library.
+ */
+ char *version;
+
+ /**
+ * The path name of the librarian file.
+ */
+ char *path;
+};
+
+
/**
* The name of the process.
*/
static const char *argv0;
+/**
+ * Sorted list of already located librarian files.
+ */
+static struct found_file *found_files = NULL;
+
+/**
+ * The number of elements in `found_files`.
+ */
+static size_t found_files_count = 0;
+
/**
@@ -104,6 +135,23 @@ static int library_name_cmp(const void *a, const void *b)
/**
+ * Compares the name of two `struct found_file`.
+ *
+ * @param a:const struct found_file * One of the files.
+ * @param b:const struct found_file * The other file.
+ * @return <0: `a` < `b`.
+ * =0: `a` = `b`.
+ * >0: `a` > `b`.
+ */
+static int found_file_name_cmp(const void *a, const void *b)
+{
+ const struct found_file *fa = a;
+ const struct found_file *fb = b;
+ return strcmp(fa->name, fb->name);
+}
+
+
+/**
* Determine whether a string is the
* name of a non-reserved variable.
*
@@ -452,40 +500,64 @@ static char **find_librarian_files(struct library *libraries, size_t n, char *pa
char *found_ver;
const char *last = NULL;
char **rc = NULL;
+ void *new;
size_t ptr = 0;
int r, saved_errno;
+ struct found_file f;
+ struct found_file *have;
qsort(libraries, n, sizeof(*libraries), library_name_cmp);
+ qsort(found_files, found_files_count, sizeof(*found_files), found_file_name_cmp);
rc = malloc((n + 1) * sizeof(*rc));
t (rc == NULL);
+ new = realloc(found_files, (found_files_count + n) * sizeof(*found_files));
+ t (new == NULL);
+ found_files = new;
for (i = 0; i < n; i++) {
- /* TODO skip dependees */
+ f.name = libraries[i].name;
+ have = bsearch(&f, found_files, found_files_count, sizeof(*found_files), found_file_name_cmp);
+ if (have) {
+ if (test_library_version(have->version, libraries + i))
+ continue;
+ goto not_this_range;
+ }
found = locate(libraries + i, path, oldest);
t (!found && errno);
- if (found == NULL) {
- if (i + 1 == n)
- goto not_found;
- if (strcmp(libraries[i].name, libraries[i + 1].name))
- goto not_found;
- continue;
- }
- if (last && !strcmp(libraries[i].name, last)) {
+ if (found == NULL)
+ goto not_this_range;
+ if (last && !strcmp(f.name, last)) {
best_ver = strrchr(best, '=');
found_ver = strrchr(found, '=');
assert(best_ver && !strchr(best_ver, '/'));
assert(found_ver && !strchr(found_ver, '/'));
r = version_cmp(found + 1, best_ver + 1);
- if (oldest ? (r < 0) : (r > 0)) {
+ r = oldest ? (r < 0) : (r > 0);
+ if (r)
free(best);
- rc[ptr - 1] = best = found;
- }
} else {
- rc[ptr++] = best = found;
+ r = 1, ptr++;
+ }
+ if (r) {
+ rc[ptr - 1] = best = found;
+ found_ver = strrchr(found, '=');
+ assert(found_ver && !strchr(found_ver, '/'));
+ found_files[found_files_count + ptr - 1].name = f.name;
+ found_files[found_files_count + ptr - 1].version = found_ver + 1;
+ found_files[found_files_count + ptr - 1].path = found;
}
- last = libraries[i].name;
+ last = f.name;
+ continue;
+
+ not_this_range:
+ if (i + 1 == n)
+ goto not_found;
+ if (strcmp(f.name, libraries[i + 1].name))
+ goto not_found;
+ continue;
}
+ found_files_count += ptr;
rc[ptr++] = NULL;
return rc;
@@ -616,6 +688,7 @@ cleanup:
for (; *file; file++)
free(*file);
free(files);
+ free(found_files);
free(libraries);
free(path);
return rc;