---
LICENSE | 1 +
Makefile | 1 +
diff.c | 207 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 209 insertions(+)
create mode 100644 diff.c
diff --git a/LICENSE b/LICENSE
index cb5a797..2a26979 100644
--- a/LICENSE
+++ b/LICENSE
_AT_@ -59,3 +59,4 @@ Authors/contributors include:
© 2015 Quentin Rameau <quinq_AT_quinq.eu.org>
© 2015 Dionysis Grigoropoulos <info_AT_erethon.com>
© 2015 Wolfgang Corcoran-Mathe <first.lord.of.teal_AT_gmail.com>
+© 2016 Mattias Andrée <maandree_AT_kth.se>
diff --git a/Makefile b/Makefile
index 1c09cac..74e071e 100644
--- a/Makefile
+++ b/Makefile
_AT_@ -89,6 +89,7 @@ BIN =\
cron\
cut\
date\
+ diff\
dirname\
du\
echo\
diff --git a/diff.c b/diff.c
new file mode 100644
index 0000000..21f9849
--- /dev/null
+++ b/diff.c
_AT_@ -0,0 +1,207 @@
+/* See LICENSE file for copyright and license details. */
+#include <stdio.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "util.h"
+
+#define END_OF_PATH 127
+
+#define printf(...) do {if (printf(__VA_ARGS__) < 0) perror("printf"), exit(EXIT_FAILURE); } while(0)
+
+struct file_data {
+ char **lines;
+ size_t line_count;
+ int lf_terminated;
+};
+
+struct output {
+ char colour;
+ char* text;
+};
+
+static struct output *red = 0;
+static struct output *green = 0;
+
+static struct file_data *
+load_lines(const char *pathname)
+{
+ int fd;
+ char *buffer;
+ char *p;
+ char *end;
+ size_t ptr, size, n;
+ ssize_t m;
+ struct file_data* rc;
+
+ fd = open(pathname, O_RDONLY);
+ if (fd == -1)
+ perror(pathname), exit(EXIT_FAILURE);
+
+ ptr = 0;
+ buffer = emalloc((size = 8096) + 1);
+ for (;;) {
+ if (ptr == size)
+ buffer = erealloc(buffer, (size <<= 1) + 1);
+ m = read(fd, buffer + ptr, size - ptr);
+ if (m < 0)
+ perror(pathname), exit(EXIT_FAILURE);
+ if (m == 0)
+ break;
+ ptr += (size_t)m;
+ }
+ buffer[ptr] = 0;
+
+ close(fd);
+
+ for (n = 1, p = buffer;; n += 1) {
+ char *lf = strchr(p, '\n');
+ if (!lf)
+ break;
+ p = lf + 1;
+ }
+ if (strchr(p, '\0') != buffer + ptr)
+ enprintf(1, "%s: file is binary\n", pathname);
+
+ rc = erealloc(buffer, sizeof(*rc) + (n + 1) * sizeof(char *) + (ptr + 1));
+ buffer = ((char *)rc) + sizeof(*rc) + (n + 1) * sizeof(char *);
+ memmove(buffer, rc, ptr);
+ rc->lines = (char **)((char *)rc + sizeof(*rc));
+ rc->lf_terminated = ptr && buffer[ptr - 1] == '\n';
+ rc->line_count = n -= rc->lf_terminated;
+ buffer[ptr - rc->lf_terminated] = 0;
+
+ rc->lines[n] = 0;
+ for (ptr = 0, p = buffer; p; p = end) {
+ end = strchr(p, '\n');
+ if (end)
+ *end++ = 0;
+ rc->lines[ptr++] = p;
+ }
+
+ return rc;
+}
+
+static char *
+diff2(char **a, char **b, size_t an, size_t bn)
+{
+ size_t **matrix = emalloc((an + 1) * sizeof(size_t *) + (an + 1) * (bn + 1) * sizeof(size_t));
+ char **map = emalloc((an + 1) * sizeof(char *) + (an + 1) * (bn + 1) * sizeof(char));
+ size_t ai, bi, ri = 0;
+ char *rc;
+
+ for (ai = 0; ai <= an; ai++) {
+ matrix[ai] = (size_t *)(matrix + an + 1) + ai * (bn + 1);
+ map [ai] = (char *)(map + an + 1) + ai * (bn + 1);
+ matrix[ai][0] = ai;
+ map [ai][0] = 1;
+ }
+ for (bi = 0; bi <= bn; bi++) {
+ matrix[0][bi] = bi;
+ map [0][bi] = 2;
+ }
+ map[0][0] = 0;
+
+ a--, b--;
+
+ for (ai = 1; ai <= an; ai++) {
+ for (bi = 1; bi <= bn; bi++) {
+ size_t d = matrix[ai - 1][bi - 1];
+ size_t u = matrix[ai - 1][bi ];
+ size_t l = matrix[ai ][bi - 1];
+ size_t lu = 1 + (l < u ? l : u);
+ int ch = strcmp(a[ai], b[bi]); /* remember !! if using d += ch */
+ matrix[ai][bi] = (lu < d || ch) ? lu : d;
+ map [ai][bi] = (lu < d || ch) ? 1 + (l < u) : 0;
+ }
+ }
+
+ rc = emalloc(an + bn + 2);
+ rc[ri++] = END_OF_PATH;
+ for (ai = an, bi = bn; ai + bi; ri++) {
+ rc[ri] = map[ai][bi];
+ ai -= rc[ri] != 2;
+ bi -= rc[ri] != 1;
+ }
+
+ free(matrix);
+ free(map);
+ return rc + ri;
+}
+
+static void
+flush_output(struct output *output, size_t n)
+{
+ if (!n)
+ return;
+
+ if (output->colour == 0) {
+ printf("%s%s\n", " ", output->text);
+ } else {
+ size_t colour_n[] = { [1] = 0, [2] = 0 }, i;
+ static size_t last_size = 0;
+
+ if (last_size < n) {
+ red = erealloc(red, n * sizeof(*red));
+ green = erealloc(green, n * sizeof(*green));
+ last_size = n;
+ }
+
+ for (i = 0; i < n; i++)
+ (output[i].colour == 1 ? red : green)[colour_n[(int)(output[i].colour)]++] = output[i];
+
+ for (i = 0, n = colour_n[1]; i < n; i++)
+ printf("\033[31m-%s\033[m\n", red[i].text);
+ for (i = 0, n = colour_n[2]; i < n; i++)
+ printf("\033[32m+%s\033[m\n", green[i].text);
+ }
+}
+
+int
+main(int argc, char *argv[])
+{
+ struct file_data *old;
+ struct file_data *new;
+ char *path;
+ char trace;
+ struct output *output;
+ size_t n, ai, bi;
+ char **a;
+ char **b;
+ int ret = 0;
+
+ argv0 = argv[0];
+
+ old = load_lines(argv[1]);
+ new = load_lines(argv[2]);
+
+ a = old->lines, b = new->lines;
+ path = diff2(a, b, old->line_count, new->line_count);
+
+ output = emalloc((old->line_count + new->line_count) * sizeof(*output));
+ for (n = ai = bi = 0; (trace = *--path) != END_OF_PATH;) {
+ if (trace) {
+ output[n++] = (struct output){ trace, trace == 1 ? a[ai] : b[bi] };
+ } else {
+ flush_output(output, n), n = 0;
+ output[n++] = (struct output){ trace, a[ai] };
+ flush_output(output, n), n = 0;
+ }
+ ai += trace != 2;
+ bi += trace != 1;
+ }
+ flush_output(output, n);
+
+ if (fshut(stdout, "<stdout>"))
+ ret = 2;
+
+ free(red);
+ free(green);
+ free(old);
+ free(new);
+ free(path);
+ free(output);
+ return ret;
+}
--
2.7.0
Received on Wed Jan 27 2016 - 20:18:17 CET
This archive was generated by hypermail 2.3.0 : Wed Jan 27 2016 - 20:24:10 CET