commit - 6478979fd94200850480e7617ee8145fa4604749
commit + 53059b5a7070dbdfa26bef789b72eadd2df818bb
blob - 7675e9a5b6d87c99364a7f47ca7d5992766b7f04
blob + 54d60a231381aaf72bb8c26a0745785fde047082
--- GNUmakefile
+++ GNUmakefile
PROG= diff
SRCS= diff.c diff_atomize_text.c diff_main.c diff_myers.c \
- diff_patience.c diff_output.c
+ diff_patience.c
CFLAGS+= -Wstrict-prototypes -Wunused-variable
blob - 2f08bf923ed470e3adf0386181c4b77937c7800c
blob + 7ebd9a89b9e6bab7a63e823438e51437eae318fd
--- Makefile
+++ Makefile
PROG= diff
SRCS= diff.c diff_atomize_text.c diff_main.c diff_myers.c \
- diff_patience.c diff_output.c
+ diff_patience.c
CFLAGS+= -Wstrict-prototypes -Wunused-variable
blob - 8a5fbac42174d13210c2a2d5ea97001cf95950f4
blob + ad72c6e6b68c69cead06ba566b0252464199114a
--- diff.c
+++ diff.c
#include <err.h>
#include <fcntl.h>
#include <limits.h>
+#include <stdbool.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
+#include "debug.h"
#include "diff_main.h"
#define DEFAULT_CONTEXT 3
#define F_UNIFIED (1 << 0)
+/* Diff output generators and invocation shims. */
+struct diff_input_info {
+ const char *left_path;
+ const char *left_buffer;
+ off_t left_size;
+ const char *right_path;
+ const char *right_buffer;
+ off_t right_size;
+};
+
+
__dead void usage(void);
int diffreg(char *, char *, int, int);
char *mmapfile(const char *, struct stat *);
+enum diff_rc diff_plain(FILE *dest, const struct diff_config *diff_config,
+ const struct diff_input_info *info);
+enum diff_rc diff_unidiff(FILE *dest, const struct diff_config *diff_config,
+ const struct diff_input_info *info,
+ unsigned int context_lines);
+
const struct diff_algo_config myers, patience, myers_divide;
const struct diff_algo_config myers = {
return p;
}
+
+void
+output_lines(FILE *dest, const char *prefix, struct diff_atom *start_atom,
+ unsigned int count)
+{
+ struct diff_atom *atom;
+
+ foreach_diff_atom(atom, start_atom, count) {
+ unsigned int len = atom->len;
+ int i;
+
+ fprintf(dest, "%s", prefix);
+ if (len && atom->at[len - 1] == '\n') {
+ len--;
+ if (len && atom->at[len - 1] == '\r')
+ len--;
+ }
+
+ for (i = 0; i < len; i++) {
+ char c = atom->at[i];
+ if ((c < 0x20 || c >= 0x7f) && c != '\t')
+ fprintf(dest, "\\x%02x", (unsigned char)c);
+ else
+ fprintf(dest, "%c", c);
+ }
+ fprintf(dest, "\n");
+ }
+}
+
+/*
+ * Output all lines of a diff_result.
+ */
+enum diff_rc
+output_plain(FILE *dest, const struct diff_input_info *info,
+ const struct diff_result *result)
+{
+ int i;
+
+ for (i = 0; i < result->chunks.len; i++) {
+ struct diff_chunk *c = &result->chunks.head[i];
+
+ if (c->left_count && c->right_count)
+ output_lines(dest, c->solved ? " " : "?",
+ c->left_start, c->left_count);
+ else if (c->left_count && !c->right_count)
+ output_lines(dest, c->solved ? "-" : "?",
+ c->left_start, c->left_count);
+ else if (c->right_count && !c->left_count)
+ output_lines(dest, c->solved ? "+" : "?",
+ c->right_start, c->right_count);
+ }
+ return DIFF_RC_OK;
+}
+
+enum diff_rc
+diff_plain(FILE *dest, const struct diff_config *diff_config,
+ const struct diff_input_info *info)
+{
+ struct diff_result *result;
+ int left_len, right_len;
+ enum diff_rc rc;
+
+ left_len = info->left_size;
+ right_len = info->right_size;
+ if (left_len < 0 || right_len < 0)
+ return DIFF_RC_EINVAL;
+ result = diff_main(diff_config, info->left_buffer, left_len,
+ info->right_buffer, right_len);
+ if (result == NULL)
+ return DIFF_RC_EINVAL;
+ if (result->rc != DIFF_RC_OK)
+ return result->rc;
+ rc = output_plain(dest, info, result);
+ diff_result_free(result);
+ return rc;
+}
+
+/*
+ * Produce a unidiff output from a diff_result.
+ */
+enum chunk_type {
+ CHUNK_EMPTY,
+ CHUNK_PLUS,
+ CHUNK_MINUS,
+ CHUNK_SAME,
+ CHUNK_WEIRD,
+};
+
+static inline enum chunk_type
+chunk_type(const struct diff_chunk *chunk)
+{
+ if (!chunk->left_count && !chunk->right_count)
+ return CHUNK_EMPTY;
+ if (!chunk->solved)
+ return CHUNK_WEIRD;
+ if (!chunk->right_count)
+ return CHUNK_MINUS;
+ if (!chunk->left_count)
+ return CHUNK_PLUS;
+ if (chunk->left_count != chunk->right_count)
+ return CHUNK_WEIRD;
+ return CHUNK_SAME;
+}
+
+struct chunk_context {
+ struct range chunk;
+ struct range left, right;
+};
+
+static bool
+chunk_context_empty(const struct chunk_context *cc)
+{
+ return range_empty(&cc->chunk);
+}
+
+static void
+chunk_context_get(struct chunk_context *cc, const struct diff_result *r,
+ int chunk_idx, int context_lines)
+{
+ const struct diff_chunk *c = &r->chunks.head[chunk_idx];
+ int left_start, right_start;
+
+ left_start = diff_atom_root_idx(&r->left, c->left_start);
+ right_start = diff_atom_root_idx(&r->right, c->right_start);
+
+ *cc = (struct chunk_context) {
+ .chunk = {
+ .start = chunk_idx,
+ .end = chunk_idx + 1,
+ },
+ .left = {
+ .start = MAX(0, left_start - context_lines),
+ .end = MIN(r->left.atoms.len,
+ left_start + c->left_count + context_lines),
+ },
+ .right = {
+ .start = MAX(0, right_start - context_lines),
+ .end = MIN(r->right.atoms.len,
+ right_start + c->right_count + context_lines),
+ },
+ };
+}
+
+static bool
+chunk_contexts_touch(const struct chunk_context *cc, const struct chunk_context *other)
+{
+ return ranges_touch(&cc->chunk, &other->chunk) ||
+ ranges_touch(&cc->left, &other->left) ||
+ ranges_touch(&cc->right, &other->right);
+}
+
+static void
+chunk_contexts_merge(struct chunk_context *cc, const struct chunk_context *other)
+{
+ ranges_merge(&cc->chunk, &other->chunk);
+ ranges_merge(&cc->left, &other->left);
+ ranges_merge(&cc->right, &other->right);
+}
+
+static void
+output_unidiff_chunk(FILE *dest, bool *header_printed,
+ const struct diff_input_info *info, const struct diff_result *result,
+ const struct chunk_context *cc)
+{
+ const struct diff_chunk *first_chunk, *last_chunk;
+ int chunk_start_line, chunk_end_line, c_idx;
+
+ if (range_empty(&cc->left) && range_empty(&cc->right))
+ return;
+
+ if (!(*header_printed)) {
+ fprintf(dest, "--- %s\n+++ %s\n",
+ info->left_path ? : "a", info->right_path ? : "b");
+ *header_printed = true;
+ }
+
+ fprintf(dest, "@@ -%d,%d +%d,%d @@\n",
+ cc->left.start + 1, cc->left.end - cc->left.start,
+ cc->right.start + 1, cc->right.end - cc->right.start);
+
+ /*
+ * Got the absolute line numbers where to start printing, and the
+ * index of the interesting (non-context) chunk.
+ * To print context lines above the interesting chunk, nipping on
+ * the previous chunk index may be necessary.
+ * It is guaranteed to be only context lines where left == right,
+ * so it suffices to look on the left.
+ */
+ first_chunk = &result->chunks.head[cc->chunk.start];
+ chunk_start_line = diff_atom_root_idx(&result->left,
+ first_chunk->left_start);
+
+ if (cc->left.start < chunk_start_line)
+ output_lines(dest, " ",
+ &result->left.atoms.head[cc->left.start],
+ chunk_start_line - cc->left.start);
+
+ /* Now write out all the joined chunks and contexts between them */
+ for (c_idx = cc->chunk.start; c_idx < cc->chunk.end; c_idx++) {
+ const struct diff_chunk *c = &result->chunks.head[c_idx];
+
+ if (c->left_count && c->right_count)
+ output_lines(dest, c->solved ? " " : "?",
+ c->left_start, c->left_count);
+ else if (c->left_count && !c->right_count)
+ output_lines(dest, c->solved ? "-" : "?",
+ c->left_start, c->left_count);
+ else if (c->right_count && !c->left_count)
+ output_lines(dest, c->solved ? "+" : "?",
+ c->right_start, c->right_count);
+ }
+
+ /* Trailing context? */
+ last_chunk = &result->chunks.head[cc->chunk.end - 1];
+ chunk_end_line = diff_atom_root_idx(&result->left,
+ last_chunk->left_start + last_chunk->left_count);
+ if (cc->left.end > chunk_end_line)
+ output_lines(dest, " ",
+ &result->left.atoms.head[chunk_end_line],
+ cc->left.end - chunk_end_line);
+}
+
+enum diff_rc
+output_unidiff(FILE *dest, const struct diff_input_info *info,
+ const struct diff_result *result, unsigned int context_lines)
+{
+ struct chunk_context cc = {};
+ bool header_printed = false;
+ int i;
+
+ for (i = 0; i < result->chunks.len; i++) {
+ struct diff_chunk *c = &result->chunks.head[i];
+ enum chunk_type t = chunk_type(c);
+ struct chunk_context next;
+
+ if (t != CHUNK_MINUS && t != CHUNK_PLUS)
+ continue;
+
+ if (chunk_context_empty(&cc)) {
+ /*
+ * These are the first lines being printed.
+ * Note down the start point, any number of
+ * subsequent chunks may be joined up to this
+ * unidiff chunk by context lines or by being
+ * directly adjacent.
+ */
+ chunk_context_get(&cc, result, i, context_lines);
+ debug("new chunk to be printed:"
+ " chunk %d-%d left %d-%d right %d-%d\n",
+ cc.chunk.start, cc.chunk.end,
+ cc.left.start, cc.left.end, cc.right.start,
+ cc.right.end);
+ continue;
+ }
+
+ /*
+ * There already is a previous chunk noted down for
+ * being printed. Does it join up with this one?
+ */
+ chunk_context_get(&next, result, i, context_lines);
+ debug("new chunk to be printed: chunk %d-%d left %d-%d right"
+ " %d-%d\n", next.chunk.start, next.chunk.end,
+ next.left.start, next.left.end, next.right.start,
+ next.right.end);
+
+ if (chunk_contexts_touch(&cc, &next)) {
+ /*
+ * This next context touches or overlaps the
+ * previous one, join.
+ */
+ chunk_contexts_merge(&cc, &next);
+ debug("new chunk to be printed touches previous chunk,"
+ " now: left %d-%d right %d-%d\n", cc.left.start,
+ cc.left.end, cc.right.start, cc.right.end);
+ continue;
+ }
+
+ /*
+ * No touching, so the previous context is complete with a
+ * gap between it and this next one. Print the previous
+ * one and start fresh here.
+ */
+ debug("new chunk to be printed does not touch previous chunk;"
+ " print left %d-%d right %d-%d\n", cc.left.start,
+ cc.left.end, cc.right.start, cc.right.end);
+ output_unidiff_chunk(dest, &header_printed, info, result,
+ &cc);
+
+ cc = next;
+ debug("new unprinted chunk is left %d-%d right %d-%d\n",
+ cc.left.start, cc.left.end, cc.right.start, cc.right.end);
+
+ }
+
+ if (!chunk_context_empty(&cc))
+ output_unidiff_chunk(dest, &header_printed, info, result,
+ &cc);
+ return DIFF_RC_OK;
+}
+
+enum diff_rc
+diff_unidiff(FILE *dest, const struct diff_config *diff_config,
+ const struct diff_input_info *info, unsigned int context_lines)
+{
+ struct diff_result *result;
+ int left_len, right_len;
+ enum diff_rc rc;
+
+ left_len = info->left_size;
+ right_len = info->right_size;
+ if (left_len < 0 || right_len < 0)
+ return DIFF_RC_EINVAL;
+ result = diff_main(diff_config, info->left_buffer, left_len,
+ info->right_buffer, right_len);
+ if (result == NULL)
+ return DIFF_RC_EINVAL;
+ if (result->rc != DIFF_RC_OK)
+ return result->rc;
+ rc = output_unidiff(dest, info, result, context_lines);
+ diff_result_free(result);
+ return rc;
+}
blob - 5a3a87d6aedbc79d50939e4730ba8d8e098d73db
blob + 0a10963543eaacf9c45f90cad201f4c1b938fd02
--- diff_main.h
+++ diff_main.h
const uint8_t *left_data, size_t left_len,
const uint8_t *right_data, size_t right_len);
void diff_result_free(struct diff_result *result);
-
-/* Diff output generators and invocation shims. */
-struct diff_input_info {
- const char *left_path;
- const char *left_buffer;
- off_t left_size;
- const char *right_path;
- const char *right_buffer;
- off_t right_size;
-};
-
-enum diff_rc diff_plain(FILE *dest, const struct diff_config *diff_config,
- const struct diff_input_info *info);
-
-enum diff_rc diff_unidiff(FILE *dest, const struct diff_config *diff_config,
- const struct diff_input_info *info,
- unsigned int context_lines);
blob - 5e9c48771fbdd73ddda301a22024de0361abe005 (mode 644)
blob + /dev/null
--- diff_output.c
+++ /dev/null
-/* $OpenBSD$ */
-
-/*
- * Copyright (c) 2020 Neels Hofmeyr <neels@hofmeyr.de>
- *
- * 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.
- */
-
-/*
- * Common parts for printing diff output
- */
-
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdio.h>
-
-#include "diff_main.h"
-#include "debug.h"
-
-enum diff_rc diff_output_plain(FILE *dest, const struct diff_input_info *info,
- const struct diff_result *result);
-enum diff_rc diff_output_unidiff(FILE *dest, const struct diff_input_info *info,
- const struct diff_result *result, unsigned int context_lines);
-void diff_output_lines(FILE *dest, const char *prefix, struct diff_atom *start_atom, unsigned int count);
-
-void
-diff_output_lines(FILE *dest, const char *prefix, struct diff_atom *start_atom,
- unsigned int count)
-{
- struct diff_atom *atom;
-
- foreach_diff_atom(atom, start_atom, count) {
- unsigned int len = atom->len;
- int i;
-
- fprintf(dest, "%s", prefix);
- if (len && atom->at[len - 1] == '\n') {
- len--;
- if (len && atom->at[len - 1] == '\r')
- len--;
- }
-
- for (i = 0; i < len; i++) {
- char c = atom->at[i];
- if ((c < 0x20 || c >= 0x7f) && c != '\t')
- fprintf(dest, "\\x%02x", (unsigned char)c);
- else
- fprintf(dest, "%c", c);
- }
- fprintf(dest, "\n");
- }
-}
-
-/*
- * Output all lines of a diff_result.
- */
-enum diff_rc
-diff_output_plain(FILE *dest, const struct diff_input_info *info,
- const struct diff_result *result)
-{
- int i;
-
- for (i = 0; i < result->chunks.len; i++) {
- struct diff_chunk *c = &result->chunks.head[i];
-
- if (c->left_count && c->right_count)
- diff_output_lines(dest, c->solved ? " " : "?",
- c->left_start, c->left_count);
- else if (c->left_count && !c->right_count)
- diff_output_lines(dest, c->solved ? "-" : "?",
- c->left_start, c->left_count);
- else if (c->right_count && !c->left_count)
- diff_output_lines(dest, c->solved ? "+" : "?",
- c->right_start, c->right_count);
- }
- return DIFF_RC_OK;
-}
-
-enum diff_rc
-diff_plain(FILE *dest, const struct diff_config *diff_config,
- const struct diff_input_info *info)
-{
- struct diff_result *result;
- int left_len, right_len;
- enum diff_rc rc;
-
- left_len = info->left_size;
- right_len = info->right_size;
- if (left_len < 0 || right_len < 0)
- return DIFF_RC_EINVAL;
- result = diff_main(diff_config, info->left_buffer, left_len,
- info->right_buffer, right_len);
- if (result == NULL)
- return DIFF_RC_EINVAL;
- if (result->rc != DIFF_RC_OK)
- return result->rc;
- rc = diff_output_plain(dest, info, result);
- diff_result_free(result);
- return rc;
-}
-
-/*
- * Produce a unidiff output from a diff_result.
- */
-enum chunk_type {
- CHUNK_EMPTY,
- CHUNK_PLUS,
- CHUNK_MINUS,
- CHUNK_SAME,
- CHUNK_WEIRD,
-};
-
-static inline enum chunk_type
-chunk_type(const struct diff_chunk *chunk)
-{
- if (!chunk->left_count && !chunk->right_count)
- return CHUNK_EMPTY;
- if (!chunk->solved)
- return CHUNK_WEIRD;
- if (!chunk->right_count)
- return CHUNK_MINUS;
- if (!chunk->left_count)
- return CHUNK_PLUS;
- if (chunk->left_count != chunk->right_count)
- return CHUNK_WEIRD;
- return CHUNK_SAME;
-}
-
-struct chunk_context {
- struct range chunk;
- struct range left, right;
-};
-
-static bool
-chunk_context_empty(const struct chunk_context *cc)
-{
- return range_empty(&cc->chunk);
-}
-
-static void
-chunk_context_get(struct chunk_context *cc, const struct diff_result *r,
- int chunk_idx, int context_lines)
-{
- const struct diff_chunk *c = &r->chunks.head[chunk_idx];
- int left_start, right_start;
-
- left_start = diff_atom_root_idx(&r->left, c->left_start);
- right_start = diff_atom_root_idx(&r->right, c->right_start);
-
- *cc = (struct chunk_context) {
- .chunk = {
- .start = chunk_idx,
- .end = chunk_idx + 1,
- },
- .left = {
- .start = MAX(0, left_start - context_lines),
- .end = MIN(r->left.atoms.len,
- left_start + c->left_count + context_lines),
- },
- .right = {
- .start = MAX(0, right_start - context_lines),
- .end = MIN(r->right.atoms.len,
- right_start + c->right_count + context_lines),
- },
- };
-}
-
-static bool
-chunk_contexts_touch(const struct chunk_context *cc, const struct chunk_context *other)
-{
- return ranges_touch(&cc->chunk, &other->chunk) ||
- ranges_touch(&cc->left, &other->left) ||
- ranges_touch(&cc->right, &other->right);
-}
-
-static void
-chunk_contexts_merge(struct chunk_context *cc, const struct chunk_context *other)
-{
- ranges_merge(&cc->chunk, &other->chunk);
- ranges_merge(&cc->left, &other->left);
- ranges_merge(&cc->right, &other->right);
-}
-
-static void
-diff_output_unidiff_chunk(FILE *dest, bool *header_printed,
- const struct diff_input_info *info, const struct diff_result *result,
- const struct chunk_context *cc)
-{
- const struct diff_chunk *first_chunk, *last_chunk;
- int chunk_start_line, chunk_end_line, c_idx;
-
- if (range_empty(&cc->left) && range_empty(&cc->right))
- return;
-
- if (!(*header_printed)) {
- fprintf(dest, "--- %s\n+++ %s\n",
- info->left_path ? : "a", info->right_path ? : "b");
- *header_printed = true;
- }
-
- fprintf(dest, "@@ -%d,%d +%d,%d @@\n",
- cc->left.start + 1, cc->left.end - cc->left.start,
- cc->right.start + 1, cc->right.end - cc->right.start);
-
- /*
- * Got the absolute line numbers where to start printing, and the
- * index of the interesting (non-context) chunk.
- * To print context lines above the interesting chunk, nipping on
- * the previous chunk index may be necessary.
- * It is guaranteed to be only context lines where left == right,
- * so it suffices to look on the left.
- */
- first_chunk = &result->chunks.head[cc->chunk.start];
- chunk_start_line = diff_atom_root_idx(&result->left,
- first_chunk->left_start);
-
- if (cc->left.start < chunk_start_line)
- diff_output_lines(dest, " ",
- &result->left.atoms.head[cc->left.start],
- chunk_start_line - cc->left.start);
-
- /* Now write out all the joined chunks and contexts between them */
- for (c_idx = cc->chunk.start; c_idx < cc->chunk.end; c_idx++) {
- const struct diff_chunk *c = &result->chunks.head[c_idx];
-
- if (c->left_count && c->right_count)
- diff_output_lines(dest, c->solved ? " " : "?",
- c->left_start, c->left_count);
- else if (c->left_count && !c->right_count)
- diff_output_lines(dest, c->solved ? "-" : "?",
- c->left_start, c->left_count);
- else if (c->right_count && !c->left_count)
- diff_output_lines(dest, c->solved ? "+" : "?",
- c->right_start, c->right_count);
- }
-
- /* Trailing context? */
- last_chunk = &result->chunks.head[cc->chunk.end - 1];
- chunk_end_line = diff_atom_root_idx(&result->left,
- last_chunk->left_start + last_chunk->left_count);
- if (cc->left.end > chunk_end_line)
- diff_output_lines(dest, " ",
- &result->left.atoms.head[chunk_end_line],
- cc->left.end - chunk_end_line);
-}
-
-enum diff_rc
-diff_output_unidiff(FILE *dest, const struct diff_input_info *info,
- const struct diff_result *result, unsigned int context_lines)
-{
- struct chunk_context cc = {};
- bool header_printed = false;
- int i;
-
- for (i = 0; i < result->chunks.len; i++) {
- struct diff_chunk *c = &result->chunks.head[i];
- enum chunk_type t = chunk_type(c);
- struct chunk_context next;
-
- if (t != CHUNK_MINUS && t != CHUNK_PLUS)
- continue;
-
- if (chunk_context_empty(&cc)) {
- /*
- * These are the first lines being printed.
- * Note down the start point, any number of
- * subsequent chunks may be joined up to this
- * unidiff chunk by context lines or by being
- * directly adjacent.
- */
- chunk_context_get(&cc, result, i, context_lines);
- debug("new chunk to be printed:"
- " chunk %d-%d left %d-%d right %d-%d\n",
- cc.chunk.start, cc.chunk.end,
- cc.left.start, cc.left.end, cc.right.start,
- cc.right.end);
- continue;
- }
-
- /*
- * There already is a previous chunk noted down for
- * being printed. Does it join up with this one?
- */
- chunk_context_get(&next, result, i, context_lines);
- debug("new chunk to be printed: chunk %d-%d left %d-%d right"
- " %d-%d\n", next.chunk.start, next.chunk.end,
- next.left.start, next.left.end, next.right.start,
- next.right.end);
-
- if (chunk_contexts_touch(&cc, &next)) {
- /*
- * This next context touches or overlaps the
- * previous one, join.
- */
- chunk_contexts_merge(&cc, &next);
- debug("new chunk to be printed touches previous chunk,"
- " now: left %d-%d right %d-%d\n", cc.left.start,
- cc.left.end, cc.right.start, cc.right.end);
- continue;
- }
-
- /*
- * No touching, so the previous context is complete with a
- * gap between it and this next one. Print the previous
- * one and start fresh here.
- */
- debug("new chunk to be printed does not touch previous chunk;"
- " print left %d-%d right %d-%d\n", cc.left.start,
- cc.left.end, cc.right.start, cc.right.end);
- diff_output_unidiff_chunk(dest, &header_printed, info, result,
- &cc);
-
- cc = next;
- debug("new unprinted chunk is left %d-%d right %d-%d\n",
- cc.left.start, cc.left.end, cc.right.start, cc.right.end);
-
- }
-
- if (!chunk_context_empty(&cc))
- diff_output_unidiff_chunk(dest, &header_printed, info, result,
- &cc);
- return DIFF_RC_OK;
-}
-
-enum diff_rc
-diff_unidiff(FILE *dest, const struct diff_config *diff_config,
- const struct diff_input_info *info, unsigned int context_lines)
-{
- struct diff_result *result;
- int left_len, right_len;
- enum diff_rc rc;
-
- left_len = info->left_size;
- right_len = info->right_size;
- if (left_len < 0 || right_len < 0)
- return DIFF_RC_EINVAL;
- result = diff_main(diff_config, info->left_buffer, left_len,
- info->right_buffer, right_len);
- if (result == NULL)
- return DIFF_RC_EINVAL;
- if (result->rc != DIFF_RC_OK)
- return result->rc;
- rc = diff_output_unidiff(dest, info, result, context_lines);
- diff_result_free(result);
- return rc;
-}