commit - 0c9a7e9d9f2c0efc643a722ca46b8144fadf531f
commit + b7ba71f0ee2562b0d5877b72d4de351a8e78a119
blob - 918cc0e92e3b84fb7583803f03d886355ceb6c5a
blob + 82af7ac31f556849d0d60cf77d5570d2d911e6b4
--- diff/Makefile
+++ diff/Makefile
diff_output.c \
diff_output_plain.c \
diff_output_unidiff.c \
+ diff_output_edscript.c \
${END}
MAN = ${PROG}.1
blob - 1bf72dd40864c6752c57ff4ca4ff782b973d8768
blob + 33779b232e5c0a49cb587d8763bf9deb96411d0d
--- diff/diff.c
+++ diff/diff.c
#include <diff_output.h>
__dead void usage(void);
-int diffreg(char *, char *, bool, bool, int);
+int diffreg(char *, char *, bool, bool, int, bool);
FILE * openfile(const char *, char **, struct stat *);
__dead void
{
int ch, rc;
bool do_patience = false, ignore_whitespace = false;
+ bool edscript = false;
int context_lines = 3;
while ((ch = getopt(argc, argv, "pwU:e")) != -1) {
case 'U':
context_lines = atoi(optarg);
break;
+ case 'e':
+ edscript = true;
+ break;
default:
usage();
}
usage();
rc = diffreg(argv[0], argv[1], do_patience, ignore_whitespace,
- context_lines);
+ context_lines, edscript);
if (rc != DIFF_RC_OK) {
fprintf(stderr, "diff: %s\n", strerror(rc));
return 1;
int
diffreg(char *file1, char *file2, bool do_patience, bool ignore_whitespace,
- int context_lines)
+ int context_lines, bool edscript)
{
char *str1, *str2;
FILE *f1, *f2;
#if 0
rc = diff_output_plain(stdout, &info, result);
#else
- rc = diff_output_unidiff(NULL, stdout, &info, result, context_lines);
+ if (edscript)
+ rc = diff_output_edscript(NULL, stdout, &info, result);
+ else {
+ rc = diff_output_unidiff(NULL, stdout, &info, result,
+ context_lines);
+ }
#endif
diff_result_free(result);
blob - 20767052a7fd8ba51f93706796155ffdbfb04a82
blob + eb5ea9058a20bee4cbe0ab59e51b057ac8067878
--- include/diff_output.h
+++ include/diff_output.h
FILE *dest, const struct diff_input_info *info,
const struct diff_result *result,
unsigned int context_lines);
+int diff_output_edscript(struct diff_output_info **output_info,
+ FILE *dest, const struct diff_input_info *info,
+ const struct diff_result *result);
int diff_chunk_get_left_start(const struct diff_chunk *c,
const struct diff_result *r,
int context_lines);
blob - 8bc527e0f06aeeca1e930f349552b5503cdae9c8
blob + 0549afc893dd068df20d061b9a9cc67d1251a9da
--- lib/GNUmakefile
+++ lib/GNUmakefile
diff_output.c \
diff_output_plain.c \
diff_output_unidiff.c \
+ diff_output_edscript.c \
$(END)
# Compat sources
blob - /dev/null
blob + 4ee960cab7a4020d7f2a8ed9b40e0a1bc9ae768a (mode 644)
--- /dev/null
+++ lib/diff_output_edscript.c
+/* Produce ed(1) script output from a diff_result. */
+/*
+ * Copyright (c) 2020 Neels Hofmeyr <neels@hofmeyr.de>
+ * Copyright (c) 2020 Stefan Sperling <stsp@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+
+#include <arraylist.h>
+#include <diff_main.h>
+#include <diff_output.h>
+
+#include "diff_internal.h"
+
+static int
+output_edscript_chunk(struct diff_output_info *outinfo,
+ FILE *dest, const struct diff_input_info *info,
+ const struct diff_result *result,
+ struct diff_chunk_context *cc, enum diff_chunk_type chunk_type)
+{
+ off_t outoff = 0, *offp;
+ int left_start, left_len, right_start, right_len;
+ int rc;
+
+ left_len = cc->left.end - cc->left.start;
+ if (left_len < 0)
+ return EINVAL;
+ else if (left_len == 0 && cc->left.start > 0)
+ left_start = cc->left.start;
+ else
+ left_start = cc->left.start + 1;
+
+ right_len = cc->right.end - cc->right.start;
+ if (right_len < 0)
+ return EINVAL;
+ else if (right_len == 0 && cc->right.start > 0)
+ right_start = cc->right.start;
+ else
+ right_start = cc->right.start + 1;
+
+ if (chunk_type == CHUNK_MINUS) {
+ if (left_len == 1) {
+ rc = fprintf(dest, "%dd%d", left_start, right_start);
+ } else {
+ rc = fprintf(dest, "%d,%dd%d\n", left_start,
+ cc->left.end, right_start);
+ }
+ } else if (chunk_type == CHUNK_PLUS) {
+ if (right_len == 1) {
+ rc = fprintf(dest, "%da%d\n", left_start, right_start);
+ } else {
+ rc = fprintf(dest, "%da%d,%d\n", left_start,
+ right_start, cc->right.end);
+ }
+ } else
+ return EINVAL;
+
+ if (rc < 0)
+ return errno;
+ if (outinfo) {
+ ARRAYLIST_ADD(offp, outinfo->line_offsets);
+ if (offp == NULL)
+ return ENOMEM;
+ outoff += rc;
+ *offp = outoff;
+ }
+
+ return DIFF_RC_OK;
+}
+
+int
+diff_output_edscript(struct diff_output_info **output_info,
+ FILE *dest, const struct diff_input_info *info,
+ const struct diff_result *result)
+{
+ struct diff_output_info *outinfo = NULL;
+ int i, rc;
+
+ if (!result)
+ return EINVAL;
+ if (result->rc != DIFF_RC_OK)
+ return result->rc;
+
+ if (output_info) {
+ *output_info = diff_output_info_alloc();
+ if (*output_info == NULL)
+ return ENOMEM;
+ outinfo = *output_info;
+ }
+
+ for (i = 0; i < result->chunks.len; i++) {
+ struct diff_chunk *chunk = &result->chunks.head[i];
+ enum diff_chunk_type t = diff_chunk_type(chunk);
+ struct diff_chunk_context cc = {};
+
+ if (t != CHUNK_MINUS && t != CHUNK_PLUS)
+ continue;
+
+ diff_chunk_context_get(&cc, result, i, 0);
+
+ if (diff_range_empty(&cc.chunk))
+ continue;
+
+ rc = output_edscript_chunk(outinfo, dest, info, result, &cc, t);
+ if (rc != DIFF_RC_OK)
+ return rc;
+ }
+
+ return DIFF_RC_OK;
+}