diff options
| author | Mattias Andrée <maandree@operamail.com> | 2015-12-03 07:38:11 +0100 | 
|---|---|---|
| committer | Mattias Andrée <maandree@operamail.com> | 2015-12-03 07:38:11 +0100 | 
| commit | 5760d146f745cf4066aee4b3ae243ca83fb94840 (patch) | |
| tree | 98af3502b6eb8ee139442b3f8dd9c8327e243d6f | |
| parent | future directions (diff) | |
| download | librarian-5760d146f745cf4066aee4b3ae243ca83fb94840.tar.gz librarian-5760d146f745cf4066aee4b3ae243ca83fb94840.tar.bz2 librarian-5760d146f745cf4066aee4b3ae243ca83fb94840.tar.xz  | |
find files
Signed-off-by: Mattias Andrée <maandree@operamail.com>
| -rw-r--r-- | src/librarian.c | 148 | 
1 files changed, 134 insertions, 14 deletions
diff --git a/src/librarian.c b/src/librarian.c index c33011f..5ee0970 100644 --- a/src/librarian.c +++ b/src/librarian.c @@ -87,6 +87,23 @@ static const char *argv0;  /** + * Compares the name of two libraries. + *  + * @param   a:const struct library *  One of the libraries. + * @param   b:const struct library *  The other library. + * @return                            <0: `a` < `b`. + *                                    =0: `a` = `b`. + *                                    >0: `a` > `b`. + */ +static int library_name_cmp(const void *a, const void *b) +{ +	const struct library *la = a; +	const struct library *lb = b; +	return strcmp(la->name, lb->name); +} + + +/**   * Determine whether a string is the   * name of a non-reserved variable.   *  @@ -300,7 +317,7 @@ static char *locate_in_dir(struct library *lib, char *path, int oldest)  	DIR *d = NULL;  	struct dirent *f;  	char *p; -	char *old; +	char *old = NULL;  	char *best = NULL;  	char *best_ver;  	int r, saved_errno; @@ -415,6 +432,88 @@ fail:  /** + * Find librarian files for all libraries. + *  + * @param   libraries  The sought libraries. + * @param   n          The number of elements in `libraries`. + * @param   path       LIBRARIAN_PATH. + * @param   oldest     Are older versions prefered? + * @return             `NULL`-terminated list of librarian files. + *                     `NULL` if all where not found, or on error, + *                     on failure to find librarian files, `errno` + *                     is set to 0. + */ +static char **find_librarian_files(struct library *libraries, size_t n, char *path, int oldest) +{ +	size_t i; +	char *best = NULL; +	char *found; +	char *best_ver; +	char *found_ver; +	const char *last = NULL; +	char **rc = NULL; +	size_t ptr = 0; +	int r, saved_errno; + +	qsort(libraries, n, sizeof(*libraries), library_name_cmp); +	rc = malloc((n + 1) * sizeof(*rc)); +	t (rc == NULL); + +	for (i = 0; i < n; i++) { +		/* TODO skip dependees */ +		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)) { +			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)) { +				free(best); +				rc[ptr - 1] = best = found; +			} +		} else { +			rc[ptr++] = best = found; +		} +		last = libraries[i].name; +	} + +	rc[ptr++] = NULL; +	return rc; + +not_found: +	if (libraries[0].upper == libraries[0].lower) { +		fprintf(stderr, "%s: cannot find library: %s%s%s", argv0, +			libraries[0].name, libraries[0].upper ? "=" : "", +			libraries[0].upper); +	} else { +		fprintf(stderr, "%s: cannot find library: %s%s%s%s%s%s%s", argv0, +			libraries[0].name, +			libraries[0].lower ? ">" : "", libraries[0].lower_closed ? "=" : "", +			libraries[0].lower ? libraries[0].lower : "", +			libraries[0].upper ? "<" : "", libraries[0].upper_closed ? "=" : "", +			libraries[0].upper ? libraries[0].upper : ""); +	} +	errno = 0; +fail: +	saved_errno = errno; +	while (ptr--) +		free(rc[ptr--]); +	free(rc); +	errno = saved_errno; +	return NULL; +} + + +/**   * @return  0: Program was successful.   *          1: An error occurred.   *          2: A library was not found. @@ -422,10 +521,6 @@ fail:   */  int main(int argc, char *argv[])  { -#define CLEANUP           \ -	free(libraries),  \ -	free(path) -  	int dashed = 0, f_deps = 0, f_locate = 0, f_oldest = 0;  	char *arg;  	char **args = argv; @@ -436,6 +531,9 @@ int main(int argc, char *argv[])  	struct library *libraries_last;  	const char *path_;  	char *path = NULL; +	char **files = NULL; +	char **file; +	int rc;  	/* Parse arguments. */  	argv0 = argv ? (argc--, *argv++) : "pp"; @@ -485,19 +583,41 @@ int main(int argc, char *argv[])  	path = strdup(path_);  	t (path == NULL); -	CLEANUP; -	return 0; +	/* Find librarian files. */ +	files = find_librarian_files(libraries, (size_t)(libraries_last - libraries), path, f_oldest); +	if (files == NULL) { +		t (errno); +		goto not_found; +	} +	if (f_locate) { +		for (file = files; *file; file++) +			t (printf("%s\n", *file) < 0); +		goto done; +	} + +	/* TODO */ +done: +	rc = 0; +	goto cleanup;  fail:  	perror(argv0); -	CLEANUP; -	return 1; - +	rc = 1; +	goto cleanup; +not_found: +	rc = 2; +	goto cleanup;  usage:  	fprintf(stderr, "%s: Invalid arguments, see `man 1 librarian'.\n", argv0); -	CLEANUP; -	return 3; - -#undef CLEANUP +	rc = 3; +	goto cleanup; +cleanup: +	if ((file = files)) +		for (; *file; file++) +			free(*file); +	free(files); +	free(libraries); +	free(path); +	return rc;  }  | 
