aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--src/librarian.c246
-rw-r--r--src/util.h81
3 files changed, 165 insertions, 164 deletions
diff --git a/Makefile b/Makefile
index 2a83fb1..9ff57c1 100644
--- a/Makefile
+++ b/Makefile
@@ -43,7 +43,7 @@ bin/librarian: obj/librarian.o
@mkdir -p bin
${CC} ${FLAGS} -o $@ $^ ${LDFLAGS}
-obj/%.o: src/%.c
+obj/%.o: src/%.c src/*.h
mkdir -p obj
${CC} ${FLAGS} -c -o $@ ${CPPFLAGS} ${CFLAGS} $<
diff --git a/src/librarian.c b/src/librarian.c
index 48a09b1..755d9f5 100644
--- a/src/librarian.c
+++ b/src/librarian.c
@@ -22,6 +22,7 @@
* DEALINGS IN THE SOFTWARE.
*/
#define _POSIX_C_SOURCE 200809L
+#include "util.h"
#include <stdio.h>
#include <ctype.h>
#include <string.h>
@@ -30,10 +31,6 @@
#include <dirent.h>
#include <unistd.h>
#include <fcntl.h>
-#include <assert.h>
-
-#define t(...) do { if (__VA_ARGS__) goto fail; } while (0)
-
/**
@@ -163,13 +160,9 @@ static int found_file_name_cmp(const void *a, const void *b)
*/
static int is_variable(const char *s)
{
- for (; *s; s++) {
- if (isupper(*s)) ;
- else if (isdigit(*s)) ;
- else if (strchr("_-", *s)) ;
- else
+ for (; *s; s++)
+ if (!isupper(*s) && !isdigit(*s) && !strchr("_-", *s))
return 0;
- }
return 1;
}
@@ -219,8 +212,7 @@ static int parse_library(char *s, struct library *lib)
lib->upper = p;
break;
default:
- assert(0);
- abort();
+ NEVER_REACHED;
break;
}
@@ -243,7 +235,6 @@ static int version_subcmp(char *a, char *b)
{
char *ap;
char *bp;
- char ac, bc;
int r;
while (*a || *b) {
@@ -253,12 +244,9 @@ static int version_subcmp(char *a, char *b)
bp = b + strspn(b, "0123456789");
while (*a == '0') a++;
while (*b == '0') b++;
- ac = *ap, bc = *bp;
- *ap = '\0', *bp = '\0';
- if (ap - a < bp - b) return *ap = ac, *bp = bc, -1;
- if (ap - a > bp - b) return *ap = ac, *bp = bc, +1;
- r = strcmp(a, b);
- *ap = ac, *bp = bc;
+ if (ap - a < bp - b) return -1;
+ if (ap - a > bp - b) return +1;
+ TEMP_NUL(ap, TEMP_NUL(bp, r = strcmp(a, b)));
a = isdigit(*a) ? (ap + 1) : a;
b = isdigit(*b) ? (bp + 1) : b;
if (r) return r;
@@ -266,10 +254,7 @@ static int version_subcmp(char *a, char *b)
/* Compare letter (non-digit) part. */
ap = a + strcspn(a, "0123456789");
bp = b + strcspn(b, "0123456789");
- ac = *ap, bc = *bp;
- *ap = '\0', *bp = '\0';
- r = strcmp(a, b);
- *ap = ac, *bp = bc;
+ TEMP_NUL(ap, TEMP_NUL(bp, r = strcmp(a, b)));
a = *a && !isdigit(*a) ? (ap + 1) : a;
b = *b && !isdigit(*b) ? (bp + 1) : b;
if (r) return r;
@@ -290,49 +275,35 @@ static int version_subcmp(char *a, char *b)
*/
static int version_cmp(char *a, char *b)
{
-#define COMPARE \
- if (ap && bp) { \
- ac = *ap, bc = *bp; \
- *ap = *bp = '\0'; \
- r = version_subcmp(a, b); \
- *ap = ac, *bp = bc; \
- a = ap + 1, b = bp + 1; \
- } else if (ap) { \
- ac = *ap, *ap = '\0'; \
- r = version_subcmp(a, nil); \
- *ap = ac, a = ap + 1; \
- } else if (bp) { \
- bc = *bp, *bp = '\0'; \
- r = version_subcmp(nil, b); \
- *bp = bc, b = bp + 1; \
- } \
+#define COMPARE \
+ if (ap && bp) { \
+ TEMP_NUL(ap, TEMP_NUL(bp, r = version_subcmp(a, b))); \
+ } else if (ap) { \
+ TEMP_NUL(ap, r = version_subcmp(a, nil)); \
+ } else if (bp) { \
+ TEMP_NUL(bp, r = version_subcmp(nil, b)); \
+ } \
+ a = ap ? (ap + 1) : a; \
+ b = bp ? (bp + 1) : b; \
if (r) return r
+#define END_AT(C) ap = strchr(a, (C)), bp = strchr(b, (C))
char *ap;
char *bp;
- char ac, bc;
int r = 0;
static char nil[1] = { '\0' };
/* Compare epoch. */
- ap = strchr(a, ':');
- bp = strchr(b, ':');
+ END_AT(':');
COMPARE;
/* Compare non-epoch */
- for (;;) {
- ap = strchr(a, '.');
- bp = strchr(b, '.');
- if (!ap && !bp)
- break;
+ while (END_AT('.'), (ap || bp)) {
COMPARE;
}
- ap = strchr(a, '\0');
- bp = strchr(b, '\0');
+ END_AT('\0');
COMPARE;
return 0;
-
-#undef COMPARE
}
@@ -371,10 +342,10 @@ static char *locate_in_dir(struct library *lib, char *path, int oldest)
DIR *d = NULL;
struct dirent *f;
char *p;
- char *old = NULL;
+ void *new;
char *best = NULL;
char *best_ver;
- int r, saved_errno;
+ int r;
d = opendir(path);
t (d == NULL);
@@ -389,20 +360,15 @@ static char *locate_in_dir(struct library *lib, char *path, int oldest)
*p++ = '=';
if (!test_library_version(p, lib))
continue;
- if (best == NULL) {
- old = best, best = strdup(f->d_name);
- } else {
- best_ver = strrchr(best, '=');
- assert(best_ver && !strchr(best_ver, '/'));
+ if (best != NULL) {
+ GET_VERSION(best_ver, best);
r = version_cmp(p, best_ver + 1);
- if (oldest ? (r < 0) : (r > 0))
- old = best, best = strdup(f->d_name);
- }
- if (best == NULL) {
- best = old;
- goto fail;
+ if (!(oldest ? (r < 0) : (r > 0)))
+ continue;
}
- free(old);
+ new = strdup(f->d_name);
+ t (new == NULL);
+ free(best), best = new;
}
t (errno);
@@ -419,12 +385,11 @@ static char *locate_in_dir(struct library *lib, char *path, int oldest)
return p;
fail:
- saved_errno = errno;
+ RETURN (NULL) {
free(best);
if (d != NULL)
closedir(d);
- errno = saved_errno;
- return NULL;
+ }
}
@@ -448,7 +413,7 @@ static char *locate(struct library *lib, char *path, int oldest)
char *old;
char *best_ver;
char *found_ver;
- int r, saved_errno;
+ int r;
for (p = path; end; *e = (end ? ':' : '\0'), p = end + 1) {
end = strchr(p, ':');
@@ -465,10 +430,8 @@ static char *locate(struct library *lib, char *path, int oldest)
if (best == NULL) {
old = best, best = found;
} else {
- best_ver = strrchr(best, '=');
- found_ver = strrchr(found, '=');
- assert(best_ver && !strchr(best_ver, '/'));
- assert(found_ver && !strchr(found_ver, '/'));
+ GET_VERSION(best_ver, best);
+ GET_VERSION(found_ver, found);
r = version_cmp(found_ver + 1, best_ver + 1);
if (oldest ? (r < 0) : (r > 0))
old = best, best = found;
@@ -479,10 +442,8 @@ static char *locate(struct library *lib, char *path, int oldest)
return errno = 0, best;
fail:
- saved_errno = errno;
+ RETURN (NULL)
free(best);
- errno = saved_errno;
- return NULL;
}
@@ -507,7 +468,6 @@ static int find_librarian_files(struct library *libraries, size_t n, char *path,
char *best_ver;
char *found_ver;
const char *last = NULL;
- void *new;
size_t ffc = found_files_count;
int r;
struct found_file f;
@@ -515,9 +475,7 @@ static int find_librarian_files(struct library *libraries, size_t n, char *path,
qsort(libraries, n, sizeof(*libraries), library_name_cmp);
qsort(found_files, ffc, sizeof(*found_files), found_file_name_cmp);
- new = realloc(found_files, (ffc + n) * sizeof(*found_files));
- t (new == NULL);
- found_files = new;
+ REALLOC(found_files, ffc + n);
for (i = 0; i < n; i++) {
f.name = libraries[i].name;
@@ -532,31 +490,23 @@ static int find_librarian_files(struct library *libraries, size_t n, char *path,
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);
- r = oldest ? (r < 0) : (r > 0);
- if (r)
- free(best);
+ GET_VERSION(best_ver, best);
+ GET_VERSION(found_ver, found);
+ r = version_cmp(found + 1, best_ver + 1);
+ if (!(oldest ? (r < 0) : (r > 0)))
+ continue;
+ free(best);
} else {
- r = 1, found_files_count++;
- }
- if (r) {
- found_ver = strrchr(found, '=');
- assert(found_ver && !strchr(found_ver, '/'));
- found_files[found_files_count - 1].name = f.name;
- found_files[found_files_count - 1].version = found_ver + 1;
- found_files[found_files_count - 1].path = best = found;
+ last = f.name, found_files_count++;
}
- last = f.name;
+ GET_VERSION(found_ver, found);
+ found_files[found_files_count - 1].name = f.name;
+ found_files[found_files_count - 1].version = found_ver + 1;
+ found_files[found_files_count - 1].path = best = found;
continue;
not_this_range:
- if (i + 1 == n)
- goto not_found;
- if (strcmp(f.name, libraries[i + 1].name))
+ if ((i + 1 == n) || strcmp(f.name, libraries[i + 1].name))
goto not_found;
continue;
}
@@ -592,10 +542,9 @@ fail:
*/
static char *find_variable(const char *path, const char *var)
{
- int fd = -1, saved_errno;
+ int fd = -1;
size_t ptr = 0, size = 0, len;
char *buffer = NULL;
- void *new;
char *p;
char *q;
char *sought = NULL;
@@ -605,12 +554,7 @@ static char *find_variable(const char *path, const char *var)
t (fd == -1);
for (;;) {
- if (ptr == size) {
- size = size ? (size << 1) : 512;
- new = realloc(buffer, size);
- t (new == NULL);
- buffer = new;
- }
+ MAYBE_GROW(buffer, ptr, size, 512);
n = read(fd, buffer + ptr, size - ptr);
t (n < 0);
if (n == 0)
@@ -619,9 +563,7 @@ static char *find_variable(const char *path, const char *var)
}
close(fd), fd = -1;
- new = realloc(buffer, ptr + 3);
- t (new == NULL);
- buffer = new;
+ REALLOC(buffer, ptr + 3);
buffer[ptr++] = '\n';
buffer[ptr++] = '\0';
memmove(buffer + 1, buffer, ptr);
@@ -656,13 +598,12 @@ static char *find_variable(const char *path, const char *var)
return p;
fail:
- saved_errno = errno;
+ RETURN (NULL) {
if (fd >= 0)
close(fd);
free(buffer);
free(sought);
- errno = saved_errno;
- return NULL;
+ }
}
@@ -684,10 +625,8 @@ static char *get_variables(const char **vars, const char **vars_end, size_t file
size_t ptr = 0;
size_t size = 0;
size_t len = 0;
- void *new;
char *rc;
char *p;
- int saved_errno;
while (files_start < found_files_count) {
path = found_files[files_start++].path;
@@ -696,12 +635,7 @@ static char *get_variables(const char **vars, const char **vars_end, size_t file
t (!part && errno);
if (!part || !*part)
continue;
- if (ptr == size) {
- size = size ? (size << 1) : 8;
- new = realloc(parts, size * sizeof(*parts));
- t (new == NULL);
- parts = new;
- }
+ MAYBE_GROW(parts, ptr, size, 8);
len += strlen(part) + 1;
parts[ptr++] = part;
}
@@ -722,12 +656,11 @@ static char *get_variables(const char **vars, const char **vars_end, size_t file
return rc;
fail:
- saved_errno = errno;
+ RETURN (NULL) {
while (ptr--)
free(parts[ptr]);
free(parts);
- errno = saved_errno;
- return NULL;
+ }
}
@@ -746,7 +679,8 @@ int main(int argc, char *argv[])
const char **variables = (const char **)argv;
const char **variables_last = variables;
struct library *libraries = NULL;
- struct library *libraries_last;
+ size_t libraries_ptr = 0;
+ size_t libraries_size = 0;
const char *path_;
char *path = NULL;
int rc;
@@ -759,46 +693,38 @@ int main(int argc, char *argv[])
size_t free_this_ptr = 0;
size_t free_this_size = 0;
const char *deps_string = "deps";
- void *new;
/* Parse arguments. */
argv0 = argv ? (argc--, *argv++) : "pp";
- while (argc) {
+ while (argc--) {
if (!dashed && !strcmp(*argv, "--")) {
dashed = 1;
argv++;
- argc--;
} else if (!dashed && (**argv == '-')) {
arg = *argv++;
- argc--;
if (!*arg)
goto usage;
for (arg++; *arg; arg++) {
- if (*arg == 'd')
- f_deps = 1;
- else if (*arg == 'l')
- f_locate = 1;
- else if (*arg == 'o')
- f_oldest = 1;
- else
- goto usage;
+ if (*arg == 'd') f_deps = 1;
+ else if (*arg == 'l') f_locate = 1;
+ else if (*arg == 'o') f_oldest = 1;
+ else goto usage;
}
} else {
*args_last++ = *argv++;
- argc--;
}
}
if (f_deps && f_locate)
goto usage;
/* Parse VARIABLE and LIBRARY arguments. */
- libraries = malloc((size_t)(args_last - args) * sizeof(*libraries));
- libraries_last = libraries;
+ libraries_size = (size_t)(args_last - args);
+ libraries = malloc(libraries_size * sizeof(*libraries));
t (libraries == NULL);
for (; args != args_last; args++) {
if (is_variable(*args))
*variables_last++ = *args;
- else if (parse_library(*args, libraries_last++))
+ else if (parse_library(*args, libraries + libraries_ptr++))
goto usage;
}
@@ -812,7 +738,7 @@ int main(int argc, char *argv[])
/* Find librarian files. */
for (start_libs = 0;;) {
start_files = found_files_count;
- n = (size_t)(libraries_last - libraries) - start_libs;
+ n = libraries_ptr - start_libs;
if (n == 0)
break;
if (find_librarian_files(libraries + start_libs, n, path, f_oldest)) {
@@ -820,28 +746,21 @@ int main(int argc, char *argv[])
goto not_found;
}
start_libs += n;
- if (f_locate)
+ if (f_locate || !f_deps)
break;
- if (f_deps) {
- data = get_variables(&deps_string, 1 + &deps_string, start_files);
- t (data == NULL);
- for (end = s = data; end; s = end + 1) {
- while (isspace(*s))
- s++;
- end = strpbrk(s, " \t\r\n\f\v");
- if (end)
- *end = '\0';
- if (*s && parse_library(s, libraries_last++))
- goto not_found;
- }
- if (free_this_ptr == free_this_size) {
- free_this_size = free_this_size ? (free_this_size << 1) : 4;
- new = realloc(free_this, free_this_size * sizeof(void*));
- t (new == NULL);
- free_this = new;
- }
- free_this[free_this_ptr++] = data;
+ data = get_variables(&deps_string, 1 + &deps_string, start_files);
+ t (data == NULL);
+ for (end = s = data; end; s = end + 1) {
+ while (isspace(*s))
+ s++;
+ if ((end = strpbrk(s, " \t\r\n\f\v")))
+ *end = '\0';
+ MAYBE_GROW(libraries, libraries_ptr, libraries_size, 1);
+ if (*s && parse_library(s, libraries + libraries_ptr++))
+ goto not_found;
}
+ MAYBE_GROW(free_this, free_this_ptr, free_this_size, 4);
+ free_this[free_this_ptr++] = data, data = NULL;
}
if (f_locate) {
while (found_files_count)
@@ -868,6 +787,7 @@ usage:
fprintf(stderr, "%s: Invalid arguments, see `man 1 librarian'.\n", argv0);
rc = 3;
goto cleanup;
+
cleanup:
while (found_files_count--)
free(found_files[found_files_count].path);
diff --git a/src/util.h b/src/util.h
new file mode 100644
index 0000000..fb78e17
--- /dev/null
+++ b/src/util.h
@@ -0,0 +1,81 @@
+/**
+ * MIT/X Consortium License
+ *
+ * Copyright © 2015 Mattias Andrée <maandree@member.fsf.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+
+#define t(...) do { if (__VA_ARGS__) goto fail; } while (0)
+
+
+#define REALLOC(PTR, SIZE) \
+ do { \
+ void *new__; \
+ new__ = realloc(PTR, (SIZE) * sizeof(*(PTR))); \
+ t (new__ == NULL); \
+ (PTR) = new__; \
+ } while (0)
+
+
+#define GROW(PTR, SIZE, DEFAULT) \
+ do { \
+ (SIZE) = (SIZE) ? ((SIZE) << 1) : (DEFAULT); \
+ REALLOC(PTR, SIZE); \
+ } while (0)
+
+
+#define MAYBE_GROW(PTR, USED, SIZE, DEFAULT) \
+ do { \
+ if ((USED) == (SIZE)) \
+ GROW(PTR, SIZE, DEFAULT); \
+ } while (0)
+
+
+#define GET_VERSION(VER, PATH) \
+ do { \
+ (VER) = strrchr((PATH), '='); \
+ assert((VER) && !strchr((VER), '/')); \
+ } while (0)
+
+
+#define NEVER_REACHED \
+ do { \
+ assert(0); \
+ abort(); \
+ } while (0)
+
+
+#define RETURN(R) \
+ for (int errno__ = errno, x__ = 0;; errno = errno__, x__++) \
+ if (x__) return (R); else
+
+
+#define TEMP_NUL(P, ACTION) \
+ do { \
+ char P##__c = *(P); \
+ *(P) = '\0'; \
+ ACTION; \
+ *(P) = P##__c; \
+ } while (0)
+