summary refs log tree commit diff
path: root/seq.c
diff options
context:
space:
mode:
Diffstat (limited to 'seq.c')
-rw-r--r--seq.c198
1 files changed, 198 insertions, 0 deletions
diff --git a/seq.c b/seq.c
index 26b0328..ab74023 100644
--- a/seq.c
+++ b/seq.c
@@ -99,3 +99,201 @@ blaze822_seq_load(char *map)
 
 	return 0;
 }
+
+char *
+blaze822_seq_cur()
+{
+        static char b[PATH_MAX];
+	// XXX env
+        int r = readlink("map.cur", b, sizeof b - 1);
+        if (r < 0)
+		return 0;
+        b[r] = 0;
+        return b;
+}
+
+int
+blaze822_seq_setcur(char *s)
+{
+	// XXX env
+	if (unlink("map.cur-") < 0 && errno != ENOENT)
+		return -1;
+	if (symlink(s, "map.cur-") < 0)
+		return -1;
+	if (rename("map.cur-", "map.cur") < 0)
+		return -1;
+	return 0;
+}
+
+static char *
+parse_relnum(char *a, long cur, long last, long *out)
+{
+	long base;
+	char *b;
+
+	if (strcmp(a, "+") == 0)
+		a = ".+1";
+	else if (strcmp(a, "-") == 0)
+		a = ".-1";
+	else if (strcmp(a, "$") == 0)
+		a = "-1";
+
+	if (*a == '.') {
+		a++;
+		base = cur;
+	} else if (*a == '-') {
+		base = last + 1;
+	} else {
+		base = 0;
+	}
+	errno = 0;
+	long d = strtol(a, &b, 10);
+	if (errno != 0) {
+		perror("strtol");
+		exit(1);
+	}
+
+	*out = base + d;
+	if (*out <= 0)
+		*out = 1;
+	if (*out > last)
+		*out = last;
+
+	return b;
+}
+
+static int
+parse_range(char *a, long *start, long *stop, long cur, long lines)
+{
+	*start = *stop = 1;
+
+	while (*a && *a != ':') {
+		char *b = parse_relnum(a, cur, lines, start);
+		if (a == b)
+			return 0;
+		a = b;
+	}
+	if (*a == ':') {
+		a++;
+		if (!*a) {
+			*stop = lines;
+		} else {
+			char *b = parse_relnum(a, cur, lines, stop);
+			if (a == b)
+				return 0;
+			a = b;
+		}
+	} else if (!*a) {
+		*stop = *start;
+	} else {
+		return 0;
+	}
+
+	return 1;
+}
+
+void
+find_cur(char *map, struct blaze822_seq_iter *iter)
+{
+	char *s, *t;
+	long cur = 0;
+	const char *curfile = blaze822_seq_cur();
+
+	iter->lines = 0;
+	for (s = map; s; s = t+1) {
+		t = strchr(s, '\n');
+		if (!t)
+			break;
+		while (*s == ' ' || *s == '\t')
+			s++;
+
+//		printf("{%.*s}\n", t-s, s);
+		iter->lines++;
+		if (!cur && curfile &&
+		    strncmp(s, curfile, strlen(curfile)) == 0 &&
+		    (s[strlen(curfile)] == '\n' ||
+		    s[strlen(curfile)] == ' ' ||
+		    s[strlen(curfile)] == '\t'))
+			iter->cur = iter->lines;
+	}
+}
+
+char *
+blaze822_seq_next(char *map, char *range, struct blaze822_seq_iter *iter)
+{
+	if (!map)
+		return 0;
+
+	if (!iter->lines)  // count total lines
+		find_cur(map, iter);
+
+	if (!iter->start) {
+		if (!parse_range(range, &iter->start, &iter->stop,
+				 iter->cur, iter->lines)) {
+			fprintf(stderr, "can't parse range: %s\n", range);
+			return 0;
+		}
+
+		iter->s = map;
+		iter->line = 1;
+	}
+
+	while (iter->line < iter->start) {
+		char *t = strchr(iter->s, '\n');
+		if (!t)
+			return 0;
+		iter->line++;
+		iter->s = t + 1;
+	}
+
+	if (iter->line > iter->stop) {
+		iter->start = iter->stop = 0;  // reset iteration
+		return 0;
+	}
+
+	char *t = strchr(iter->s, '\n');
+	if (!t)
+		return 0;
+	iter->cur = iter->line;
+	iter->line++;
+	char *r = strndup(iter->s, t-iter->s);
+	iter->s = t + 1;
+	return r;
+}
+
+
+int
+blaze822_loop(int argc, char *argv[], void (*cb)(char *))
+{
+	char *line = 0;
+	size_t linelen = 0;
+	ssize_t rd;
+	int i = 0;
+
+	if (argc == 0 || (argc == 1 && strcmp(argv[0], "-") == 0)) {
+		while ((rd = getdelim(&line, &linelen, '\n', stdin)) != -1) {
+			if (line[rd-1] == '\n')
+				line[rd-1] = 0;
+			cb(line);
+			i++;
+		}
+		free(line);
+		return i;
+	}
+
+	char *map = blaze822_seq_open(0);
+	struct blaze822_seq_iter iter = { 0 };
+	int j = 0;
+	for (i = 0; i < argc; i++) {
+		if (strchr(argv[i], '/')) {  // a file name
+			cb(argv[i]);
+		} else {
+			while ((line = blaze822_seq_next(map, argv[i], &iter))) {
+				cb(line);
+				free(line);
+				j++;
+			}
+		}
+	}
+	return j;
+}