commit - 3c72fc1f8c4e7379f78689017df9a129d6ad9b88
commit + 654951e121a78b702156603211659be2c6137182
blob - efb105889ccc3062ecac11fcae439ab59226271c
blob + d049b642d93d3a99f2fdda9a788f9d1365949a16
--- diff.1
+++ diff.1
.Nd compare files
.Sh SYNOPSIS
.Nm diff
-.Op Fl u
-.Op Fl U Ar number
+.Op Fl c | u | Fl C Ar n | Fl U Ar n
.Ar file1 file2
.Sh DESCRIPTION
The
.Pp
The options are as follows:
.Bl -tag -width Ds
-.It Fl u
-Produces a unified diff with 3 lines of context.
-.It Fl U Ar number
+.It Fl C Ar n
Similar to
+.Fl c
+with
+.Ar n
+lines of context.
+.It Fl c
+Produces a diff with 3 lines of context.
+.It Fl U Ar n
+Similar to
.Fl u
with
-.Ar number
+.Ar n
lines of context.
+.It Fl u
+Produces a unified diff with 3 lines of context.
.El
.Sh EXIT STATUS
The
blob - 176909cbcc2d9cf0db227ab76310509e550f0745
blob + 1c62a7f5efa616133362b0a161ce18fff5172b82
--- diff.c
+++ diff.c
#include <sys/mman.h>
#include <sys/stat.h>
+#include <assert.h>
#include <err.h>
#include <fcntl.h>
#include <limits.h>
#define DEFAULT_CONTEXT 3
-#define F_UNIFIED (1 << 0)
+#define F_CFORMAT (1 << 0)
+#define F_FFORMAT (1 << 1)
+#define F_ED (1 << 2)
+#define F_UNIFIED (1 << 3)
struct output_info {
const char *left_path;
+ time_t left_time;
const char *right_path;
- int flags;
+ time_t right_time;
+ int format;
int context;
};
__dead void
usage(void)
{
- fprintf(stderr, "usage: %s file1 file2\n", getprogname());
+ fprintf(stderr, "usage: %s [-c | -e | -f | -u] file1 file2\n",
+ getprogname());
exit(1);
}
int
main(int argc, char *argv[])
{
- int ch, context = DEFAULT_CONTEXT, flags = 0;
+ int ch, context = DEFAULT_CONTEXT, format = 0;
long lval;
char *ep;
- while ((ch = getopt(argc, argv, "uU:")) != -1) {
+ while ((ch = getopt(argc, argv, "cC:efuU:")) != -1) {
switch (ch) {
+ case 'C':
+ lval = strtol(optarg, &ep, 10);
+ if (*ep != '\0' || lval < 0 || lval >= INT_MAX)
+ usage();
+ context = (int)lval;
+ /* FALLTHROUGH */
+ case 'c':
+ format = F_CFORMAT;
+ break;
+ case 'e':
+ format = F_ED;
+ break;
+ case 'f':
+ format = F_FFORMAT;
+ break;
case 'U':
lval = strtol(optarg, &ep, 10);
if (*ep != '\0' || lval < 0 || lval >= INT_MAX)
context = (int)lval;
/* FALLTHROUGH */
case 'u':
- flags |= F_UNIFIED;
+ format = F_UNIFIED;
break;
default:
usage();
if (argc != 2)
usage();
- return diffreg(argv[0], argv[1], flags, context);
+ return diffreg(argv[0], argv[1], format, context);
}
int
diffreg(char *file1, char *file2, int flags, int context)
{
- struct output_info info = { file1, file2, flags, context };
+ struct output_info info = { file1, 0, file2, 0, flags, context };
char *str1, *str2;
struct stat st1, st2;
struct diff_result *result;
if (result->rc != DIFF_RC_OK)
return result->rc;
+ info.left_time = st1.st_mtime;
+ info.right_time = st2.st_mtime;
output(&info, result);
diff_result_free(result);
int left_start, right_start;
int context_lines = 0;
- if (info->flags & F_UNIFIED)
+ switch (info->format) {
+ case F_CFORMAT:
+ case F_UNIFIED:
context_lines = info->context;
+ default:
+ break;
+ }
left_start = DD_ROOT_INDEX(&r->left, c->left_start);
right_start = DD_ROOT_INDEX(&r->right, c->right_start);
}
static void
-print_chunk(bool *header_printed, const struct output_info *info,
+print_default(const struct output_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;
- char *minus, *plus;
+ int c_idx;
- if (range_empty(&cc->left) && range_empty(&cc->right))
+ printf("%dc%d\n", cc->left.start + 1, cc->right.start + 1);
+
+ /* 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];
+
+ assert(c->solved);
+
+ if (c->left_count && !c->right_count) {
+ print_lines("< ", c->left_start, c->left_count);
+ continue;
+ }
+
+ if (c->right_count && !c->left_count) {
+ print_lines("> ", c->right_start, c->right_count);
+ continue;
+ }
+ }
+}
+
+void
+print_context_before(const char *prefix, const struct diff_result *result,
+ const struct chunk_context *cc)
+{
+ const struct diff_chunk *chunk = &result->chunks.head[cc->chunk.start];
+ int start_line;
+
+ start_line = DD_ROOT_INDEX(&result->left, chunk->left_start);
+ if (cc->left.start >= start_line)
return;
+ print_lines(prefix, DD_ATOM_AT(&result->left, cc->left.start),
+ start_line - cc->left.start);
+}
- if (!(*header_printed) && info->flags & F_UNIFIED) {
- printf("--- %s\n+++ %s\n",
- info->left_path ? : "a", info->right_path ? : "b");
+void
+print_context_after(const char *prefix, const struct diff_result *result,
+ const struct chunk_context *cc)
+{
+ const struct diff_chunk *chunk = &result->chunks.head[cc->chunk.end - 1];
+ int end_line;
+
+ end_line = DD_ROOT_INDEX(&result->left,
+ chunk->left_start + chunk->left_count);
+ if (cc->left.end <= end_line)
+ return;
+ print_lines(prefix, DD_ATOM_AT(&result->left, end_line),
+ cc->left.end - end_line);
+}
+
+static void
+print_unified(bool *header_printed, const struct output_info *info,
+ const struct diff_result *result, const struct chunk_context *cc)
+{
+ int c_idx;
+
+ assert(info->format == F_UNIFIED);
+
+ if (!(*header_printed)) {
+ printf("--- %s\t%s+++ %s\t%s",
+ info->left_path, ctime(&info->left_time),
+ info->right_path, ctime(&info->right_time));
*header_printed = true;
}
- if (info->flags & F_UNIFIED) {
- minus = "-";
- plus = "+";
- printf("@@ -%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);
- } else {
- minus = "< ";
- plus = "> ";
- printf("%dc%d\n", cc->left.start + 1, cc->right.start + 1);
- }
+ printf("@@ -%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
* 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 = DD_ROOT_INDEX(&result->left,
- first_chunk->left_start);
+ print_context_before(" ", result, cc);
- if (cc->left.start < chunk_start_line)
- print_lines(" ", DD_ATOM_AT(&result->left, 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)
- print_lines(c->solved ? " " : "?",
- c->left_start, c->left_count);
- else if (c->left_count && !c->right_count)
- print_lines(c->solved ? minus : "?",
- c->left_start, c->left_count);
- else if (c->right_count && !c->left_count)
- print_lines(c->solved ? plus : "?",
- c->right_start, c->right_count);
+ assert(c->solved);
+
+ if (c->left_count && c->right_count) {
+ print_lines(" ", c->left_start, c->left_count);
+ continue;
+ }
+
+ if (c->left_count && !c->right_count) {
+ print_lines("-", c->left_start, c->left_count);
+ continue;
+ }
+
+ if (c->right_count && !c->left_count) {
+ print_lines("+", c->right_start, c->right_count);
+ continue;
+ }
}
/* Trailing context? */
- last_chunk = &result->chunks.head[cc->chunk.end - 1];
- chunk_end_line = DD_ROOT_INDEX(&result->left,
- last_chunk->left_start + last_chunk->left_count);
- if (cc->left.end > chunk_end_line)
- print_lines(" ", DD_ATOM_AT(&result->left, chunk_end_line),
- cc->left.end - chunk_end_line);
+ print_context_after(" ", result, cc);
}
+static void
+print_cformat(bool *header_printed, const struct output_info *info,
+ const struct diff_result *result, const struct chunk_context *cc)
+{
+ const struct diff_chunk *c, *cleft = NULL, *cright = NULL;
+ int c_idx;
+
+ assert(info->format == F_CFORMAT);
+
+ if (!(*header_printed)) {
+ printf("*** %s\t%s--- %s\t%s",
+ info->left_path, ctime(&info->left_time),
+ info->right_path, ctime(&info->right_time));
+ *header_printed = true;
+ }
+
+ for (c_idx = cc->chunk.start; c_idx < cc->chunk.end; c_idx++) {
+ c = &result->chunks.head[c_idx];
+
+ assert(c->solved);
+ if (c->left_count && !c->right_count) {
+ cleft = c;
+ continue;
+ }
+ if (c->right_count && !c->left_count) {
+ cright = c;
+ continue;
+ }
+ }
+
+ printf("***************\n");
+ printf("*** %d,%d ****\n", cc->left.start + 1, cc->left.end);
+ if (cleft != NULL) {
+ print_context_before(" ", result, cc);
+ print_lines(cright ? "! " : "- ",
+ cleft->left_start, cleft->left_count);
+ print_context_after(" ", result, cc);
+ }
+ printf("--- %d,%d ----\n", cc->right.start + 1, cc->right.end);
+ if (cright != NULL) {
+ print_context_before(" ", result, cc);
+ print_lines(cleft ? "! " : "+ ",
+ cright->right_start, cright->right_count);
+ print_context_after(" ", result, cc);
+ }
+}
+
+static void
+print_chunk(bool *header_printed, const struct output_info *info,
+ const struct diff_result *result, const struct chunk_context *cc)
+{
+ if (range_empty(&cc->left) && range_empty(&cc->right))
+ return;
+
+ switch (info->format) {
+ case F_UNIFIED:
+ print_unified(header_printed, info, result, cc);
+ break;
+ case F_CFORMAT:
+ print_cformat(header_printed, info, result, cc);
+ break;
+ case F_FFORMAT:
+ case F_ED:
+ default:
+ print_default(info, result, cc);
+ break;
+ }
+}
+
void
output(const struct output_info *info, const struct diff_result *result)
{
blob - 7a63e8958713ab55fbb7ebf87ebe4dd11663e85e
blob + 1a0af62af8fb78b8855e4897f6289fe028b77335
--- diff_atomize_text.c
+++ diff_atomize_text.c
#include "diff_main.h"
static int
-diff_data_atomize_text_lines(struct diff_data *d)
+diff_data_atomize_text_lines(struct diff_data *dd)
{
- const uint8_t *pos = d->data;
- const uint8_t *end = pos + d->dlen;
- unsigned int array_size_estimate = d->dlen / 50;
+ const uint8_t *pos = dd->data;
+ const uint8_t *end = pos + dd->dlen;
+ unsigned int array_size_estimate = dd->dlen / 50;
unsigned int pow2 = 1;
while (array_size_estimate >>= 1)
pow2++;
- ARRAYLIST_INIT(d->atoms, 1 << pow2);
+ ARRAYLIST_INIT(dd->atoms, 1 << pow2);
while (pos < end) {
const uint8_t *line_end = pos;
line_end++;
/* Record the found line as diff atom */
- ARRAYLIST_ADD(atom, d->atoms);
+ ARRAYLIST_ADD(atom, dd->atoms);
if (atom == NULL)
return DIFF_RC_ENOMEM;
blob - 1a556f7d0464e0bb4e03a1fa3ce0b45209e09ae9
blob + 4affcbb6ab54c059d6b75ca5b2a6937e0ed3e59f
--- diff_main.c
+++ diff_main.c
}
void
-diff_data_init_root(struct diff_data *d, const uint8_t *data, size_t dlen)
+diff_data_init_root(struct diff_data *dd, const uint8_t *data, size_t dlen)
{
- *d = (struct diff_data) {
+ *dd = (struct diff_data) {
.data = data,
.dlen = dlen,
- .root = d,
+ .root = dd,
};
}