summaryrefslogtreecommitdiffstats
path: root/usr.bin/diff/diffreg.c
diff options
context:
space:
mode:
authormillert <millert@openbsd.org>2003-07-06 20:48:59 +0000
committermillert <millert@openbsd.org>2003-07-06 20:48:59 +0000
commit4ec4b3d54a5517b053ea56c6a0ae89ce93183500 (patch)
treeb69056a72bdfd262d4624e75408caac48c13fac1 /usr.bin/diff/diffreg.c
parentvarious proto, ansi, and knf repair. tested on all architectures that (diff)
downloadwireguard-openbsd-4ec4b3d54a5517b053ea56c6a0ae89ce93183500.tar.xz
wireguard-openbsd-4ec4b3d54a5517b053ea56c6a0ae89ce93183500.zip
Some fairly major changes:
o -N is implemented o -X is implemented o -x is implemented o diff.c has been rewritten and GNU long options are now supported o diffdir.c has been rewritten + no longer does fork + exec of /usr/bin/diff + can be called recursively (and will be for -r) o diff.h + don't include any .h files here any more, do it in the .c files + no Bell Labs code in this, gets a UCB copyright (the 32v sources only have a diff.c and there is nothing in common). o diffreg.c + most all remaining globals are now private to diffreg.c + files are only opened once + dynamically allocated objects are either freed or realloced + added missing UCB copyright (there were lots of UCB changes) + print correct thing when -s is specified OK deraadt@
Diffstat (limited to 'usr.bin/diff/diffreg.c')
-rw-r--r--usr.bin/diff/diffreg.c513
1 files changed, 314 insertions, 199 deletions
diff --git a/usr.bin/diff/diffreg.c b/usr.bin/diff/diffreg.c
index c8dbc50c5d5..3a5852125e5 100644
--- a/usr.bin/diff/diffreg.c
+++ b/usr.bin/diff/diffreg.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: diffreg.c,v 1.26 2003/07/04 17:37:07 millert Exp $ */
+/* $OpenBSD: diffreg.c,v 1.27 2003/07/06 20:48:59 millert Exp $ */
/*
* Copyright (C) Caldera International Inc. 2001-2002.
@@ -33,20 +33,56 @@
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
+/*-
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)diffreg.c 8.1 (Berkeley) 6/6/93
+ */
+
+#ifndef lint
+static const char rcsid[] = "$OpenBSD: diffreg.c,v 1.27 2003/07/06 20:48:59 millert Exp $";
+#endif /* not lint */
#include <sys/types.h>
+#include <sys/stat.h>
-#include <stdlib.h>
-#include <unistd.h>
+#include <ctype.h>
+#include <err.h>
#include <fcntl.h>
+#include <libgen.h>
+#include <paths.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
+#include <unistd.h>
#include "diff.h"
-#include "pathnames.h"
-
-#if 0
-static char const sccsid[] = "@(#)diffreg.c 4.21 4/6/90";
-#endif
/*
* diff - compare two files.
@@ -115,10 +151,6 @@ static char const sccsid[] = "@(#)diffreg.c 4.21 4/6/90";
* 6n words for files of length n.
*/
-#define prints(s) fputs(s,stdout)
-
-FILE *input[2];
-
struct cand {
int x;
int y;
@@ -130,40 +162,42 @@ struct line {
int value;
} *file[2];
-int len[2];
-struct line *sfile[2]; /* shortened by pruning common prefix and suffix */
-int slen[2];
-int pref, suff; /* length of prefix and suffix */
-int inifdef; /* whether or not we are in a #ifdef block */
-int *class; /* will be overlaid on file[0] */
-int *member; /* will be overlaid on file[1] */
-int *klist; /* will be overlaid on file[0] after class */
-struct cand *clist; /* merely a free storage pot for candidates */
-int clen = 0;
-int *J; /* will be overlaid on class */
-long *ixold; /* will be overlaid on klist */
-long *ixnew; /* will be overlaid on file[1] */
-u_char *chrtran; /* translation table for case-folding */
+static int *J; /* will be overlaid on class */
+static int *class; /* will be overlaid on file[0] */
+static int *klist; /* will be overlaid on file[0] after class */
+static int *member; /* will be overlaid on file[1] */
+static int clen;
+static int inifdef; /* whether or not we are in a #ifdef block */
+static int len[2];
+static int pref, suff; /* length of prefix and suffix */
+static int slen[2];
+static int anychange;
+static long *ixnew; /* will be overlaid on file[1] */
+static long *ixold; /* will be overlaid on klist */
+static struct cand *clist; /* merely a free storage pot for candidates */
+static struct line *sfile[2]; /* shortened by pruning common prefix/suffix */
+static u_char *chrtran; /* translation table for case-folding */
static void fetch(long *, int, int, FILE *, char *, int);
-static void output(void);
-static void check(void);
+static void output(char *, FILE *, char *, FILE *);
+static void check(char *, FILE *, char *, FILE *);
static void range(int, int, char *);
-static void dump_context_vec(void);
-static void dump_unified_vec(void);
+static void dump_context_vec(FILE *, FILE *);
+static void dump_unified_vec(FILE *, FILE *);
static void prepare(int, FILE *);
static void prune(void);
static void equiv(struct line *, int, struct line *, int, int *);
static void unravel(int);
static void unsort(struct line *, int, int *);
-static void change(int, int, int, int);
+static void change(char *, FILE *, char *, FILE *, int, int, int, int);
static void sort(struct line *, int);
-static int newcand(int, int, int);
-static int search(int *, int, int);
-static int skipline(int);
-static int asciifile(FILE *);
-static int stone(int *, int, int *, int *);
-static int readhash(FILE *);
+static int asciifile(FILE *);
+static int newcand(int, int, int);
+static int search(int *, int, int);
+static int skipline(FILE *);
+static int stone(int *, int, int *, int *);
+static int readhash(FILE *);
+static int files_differ(FILE *, FILE *, int);
/*
* chrtran points to one of 2 translation tables: cup2low if folding upper to
@@ -224,70 +258,100 @@ u_char cup2low[256] = {
};
void
-diffreg(void)
+diffreg(char *ofile1, char *ofile2, int flags)
{
- char buf1[BUFSIZ], buf2[BUFSIZ];
- FILE *f1, *f2;
- int i, j;
+ char *file1 = ofile1;
+ char *file2 = ofile2;
+ FILE *f1 = NULL;
+ FILE *f2 = NULL;
+ int i;
+ anychange = 0;
chrtran = (iflag ? cup2low : clow2low);
if (strcmp(file1, "-") == 0 && strcmp(file2, "-") == 0)
- errorx("can't specify - -");
- if (S_ISDIR(stb1.st_mode)) {
- file1 = splice(file1, file2);
- if (stat(file1, &stb1) < 0)
- error("%s", file1);
- } else if (strcmp(file1, "-") == 0 ||
- (!S_ISREG(stb1.st_mode) && strcmp(file1, _PATH_DEVNULL) != 0)) {
- file1 = copytemp(file1, 1);
- if (stat(file1, &stb1) < 0)
- error("%s", file1);
+ goto notsame;
+
+ /* XXX - only make temp file for stdin if not seekable? (millert) */
+ if (flags & D_EMPTY1)
+ f1 = fopen(_PATH_DEVNULL, "r");
+ else {
+ if (S_ISDIR(stb1.st_mode)) {
+ file1 = splice(file1, file2);
+ if (stat(file1, &stb1) < 0) {
+ warn("%s", file1);
+ status |= 2;
+ goto closem;
+ }
+ } else if (strcmp(file1, "-") == 0 || !S_ISREG(stb1.st_mode)) {
+ file1 = copytemp(file1, 1);
+ if (file1 == NULL || stat(file1, &stb1) < 0) {
+ warn("%s", file1);
+ status |= 2;
+ goto closem;
+ }
+ }
+ f1 = fopen(file1, "r");
}
- if (S_ISDIR(stb2.st_mode)) {
- file2 = splice(file2, file1);
- if (stat(file2, &stb2) < 0)
- error("%s", file2);
- } else if (strcmp(file2, "-") == 0 ||
- (!S_ISREG(stb2.st_mode) && strcmp(file2, _PATH_DEVNULL) != 0)) {
- file2 = copytemp(file2, 2);
- if (stat(file2, &stb2) < 0)
- error("%s", file2);
+ if (f1 == NULL) {
+ warn("%s", file1);
+ status |= 2;
+ goto closem;
}
- if ((f1 = fopen(file1, "r")) == NULL)
- error("%s", file1);
- if ((f2 = fopen(file2, "r")) == NULL)
- error("%s", file2);
- if ((stb1.st_mode & S_IFMT) != (stb2.st_mode & S_IFMT) ||
- stb1.st_size != stb2.st_size)
- goto notsame;
- for (;;) {
- i = fread(buf1, 1, BUFSIZ, f1);
- j = fread(buf2, 1, BUFSIZ, f2);
- if (i < 0 || j < 0 || i != j)
- goto notsame;
- if (i == 0 && j == 0) {
- fclose(f1);
- fclose(f2);
- status = 0; /* files don't differ */
- goto same;
+
+ if (flags & D_EMPTY2)
+ f2 = fopen(_PATH_DEVNULL, "r");
+ else {
+ if (S_ISDIR(stb2.st_mode)) {
+ file2 = splice(file2, file1);
+ if (stat(file2, &stb2) < 0) {
+ warn("%s", file2);
+ status |= 2;
+ goto closem;
+ }
+ } else if (strcmp(file2, "-") == 0 || !S_ISREG(stb2.st_mode)) {
+ file2 = copytemp(file2, 2);
+ if (file2 == NULL || stat(file2, &stb2) < 0) {
+ warn("%s", file2);
+ status |= 2;
+ goto closem;
+ }
}
- for (j = 0; j < i; j++)
- if (buf1[j] != buf2[j])
- goto notsame;
+ f2 = fopen(file2, "r");
+ }
+ if (f2 == NULL) {
+ warn("%s", file2);
+ status |= 2;
+ goto closem;
}
+
+ switch (files_differ(f1, f2, flags)) {
+ case 0:
+ goto same;
+ case 1:
+ break;
+ default:
+ /* error */
+ status |= 2;
+ goto closem;
+ }
+
notsame:
/*
* Files certainly differ at this point; set status accordingly
*/
- status = 1;
+ status |= 1;
+ if (flags & D_HEADER) {
+ if (format == D_EDIT)
+ printf("ed - %s << '-*-END-*-'\n", basename(file1));
+ else
+ printf("%s %s %s\n", diffargs, file1, file2);
+ }
if (!asciifile(f1) || !asciifile(f2)) {
printf("Binary files %s and %s differ\n", file1, file2);
- exit(status);
+ goto closem;
}
prepare(0, f1);
prepare(1, f2);
- fclose(f1);
- fclose(f2);
prune();
sort(sfile[0], slen[0]);
sort(sfile[1], slen[1]);
@@ -306,23 +370,74 @@ notsame:
free(member);
free(class);
- J = emalloc((len[0] + 2) * sizeof(int));
+ J = erealloc(J, (len[0] + 2) * sizeof(int));
unravel(klist[i]);
free(clist);
free(klist);
- ixold = emalloc((len[0] + 2) * sizeof(long));
- ixnew = emalloc((len[1] + 2) * sizeof(long));
- check();
- output();
- status = anychange;
+ ixold = erealloc(ixold, (len[0] + 2) * sizeof(long));
+ ixnew = erealloc(ixnew, (len[1] + 2) * sizeof(long));
+ check(file1, f1, file2, f2);
+ output(file1, f1, file2, f2);
+ if ((flags & D_HEADER) && format == D_EDIT)
+ printf("w\nq\n-*-END-*-\n");
same:
- if (anychange == 0 && (opt == D_CONTEXT || opt == D_UNIFIED))
- printf("No differences encountered\n");
+ if (anychange == 0 && sflag != 0)
+ printf("Files %s and %s are identical\n", file1, file2);
+
+closem:
+ if (f1 != NULL)
+ fclose(f1);
+ if (f2 != NULL)
+ fclose(f2);
+ if (tempfiles[0] != NULL) {
+ unlink(tempfiles[0]);
+ free(tempfiles[0]);
+ tempfiles[0] = NULL;
+ }
+ if (tempfiles[1] != NULL) {
+ unlink(tempfiles[1]);
+ free(tempfiles[1]);
+ tempfiles[1] = NULL;
+ }
+ if (file1 != ofile1)
+ free(file1);
+ if (file2 != ofile2)
+ free(file2);
+}
+
+/*
+ * Check to see if the given files differ.
+ * Returns 0 if they are the same, 1 if different, and -1 on error.
+ * XXX - could use code from cmp(1) [faster]
+ */
+static int
+files_differ(FILE *f1, FILE *f2, int flags)
+{
+ char buf1[BUFSIZ], buf2[BUFSIZ];
+ size_t i, j;
+
+ if ((flags & (D_EMPTY1|D_EMPTY2)) || stb1.st_size != stb2.st_size ||
+ (stb1.st_mode & S_IFMT) != (stb2.st_mode & S_IFMT))
+ return (1);
+ for (;;) {
+ i = fread(buf1, 1, sizeof(buf1), f1);
+ j = fread(buf2, 1, sizeof(buf2), f2);
+ if (i != j)
+ return (1);
+ if (i == 0 && j == 0) {
+ if (ferror(f1) || ferror(f2))
+ return (1);
+ return (0);
+ }
+ if (memcmp(buf1, buf2, i) != 0)
+ return (1);
+ }
}
char *tempfiles[2];
+/* XXX - pass back a FILE * too (millert) */
char *
copytemp(const char *file, int n)
{
@@ -335,24 +450,24 @@ copytemp(const char *file, int n)
if (strcmp(file, "-") == 0)
ifd = STDIN_FILENO;
else if ((ifd = open(file, O_RDONLY, 0644)) < 0)
- error("%s", file);
+ return (NULL);
if ((tempdir = getenv("TMPDIR")) == NULL)
tempdir = _PATH_TMP;
if (asprintf(&tempfile, "%s/diff%d.XXXXXXXX", tempdir, n) == -1)
- error(NULL);
+ return (NULL);
tempfiles[n - 1] = tempfile;
- signal(SIGHUP, done);
- signal(SIGINT, done);
- signal(SIGPIPE, done);
- signal(SIGTERM, done);
+ signal(SIGHUP, quit);
+ signal(SIGINT, quit);
+ signal(SIGPIPE, quit);
+ signal(SIGTERM, quit);
ofd = mkstemp(tempfile);
if (ofd < 0)
- error("%s", tempfile);
+ return (NULL);
while ((i = read(ifd, buf, BUFSIZ)) > 0) {
if (write(ofd, buf, i) != i)
- error("%s", tempfile);
+ return (NULL);
}
close(ifd);
close(ofd);
@@ -365,8 +480,6 @@ splice(char *dir, char *file)
char *tail, *buf;
size_t len;
- if (!strcmp(file, "-"))
- errorx("can't specify - with other arg directory");
tail = strrchr(file, '/');
if (tail == NULL)
tail = file;
@@ -384,7 +497,7 @@ prepare(int i, FILE *fd)
struct line *p;
int j, h;
- fseek(fd, 0L, SEEK_SET);
+ rewind(fd);
p = emalloc(3 * sizeof(struct line));
for (j = 0; (h = readhash(fd));) {
p = erealloc(p, (++j + 3) * sizeof(struct line));
@@ -538,32 +651,30 @@ unravel(int p)
* 2. collect random access indexes to the two files
*/
static void
-check(void)
+check(char *file1, FILE *f1, char *file2, FILE *f2)
{
int i, j, jackpot, c, d;
long ctold, ctnew;
- if ((input[0] = fopen(file1, "r")) == NULL)
- error("%s", file1);
- if ((input[1] = fopen(file2, "r")) == NULL)
- error("%s", file2);
+ rewind(f1);
+ rewind(f2);
j = 1;
ixold[0] = ixnew[0] = 0;
jackpot = 0;
ctold = ctnew = 0;
for (i = 1; i <= len[0]; i++) {
if (J[i] == 0) {
- ixold[i] = ctold += skipline(0);
+ ixold[i] = ctold += skipline(f1);
continue;
}
while (j < J[i]) {
- ixnew[j] = ctnew += skipline(1);
+ ixnew[j] = ctnew += skipline(f2);
j++;
}
if (bflag || wflag || iflag) {
for (;;) {
- c = getc(input[0]);
- d = getc(input[1]);
+ c = getc(f1);
+ d = getc(f2);
ctold++;
ctnew++;
if (bflag && isspace(c) && isspace(d)) {
@@ -571,19 +682,19 @@ check(void)
if (c == '\n')
break;
ctold++;
- } while (isspace(c = getc(input[0])));
+ } while (isspace(c = getc(f1)));
do {
if (d == '\n')
break;
ctnew++;
- } while (isspace(d = getc(input[1])));
+ } while (isspace(d = getc(f2)));
} else if (wflag) {
while (isspace(c) && c != '\n') {
- c = getc(input[0]);
+ c = getc(f1);
ctold++;
}
while (isspace(d) && d != '\n') {
- d = getc(input[1]);
+ d = getc(f2);
ctnew++;
}
}
@@ -591,9 +702,9 @@ check(void)
jackpot++;
J[i] = 0;
if (c != '\n')
- ctold += skipline(0);
+ ctold += skipline(f1);
if (d != '\n')
- ctnew += skipline(1);
+ ctnew += skipline(f2);
break;
}
if (c == '\n')
@@ -603,13 +714,13 @@ check(void)
for (;;) {
ctold++;
ctnew++;
- if ((c = getc(input[0])) != (d = getc(input[1]))) {
+ if ((c = getc(f1)) != (d = getc(f2))) {
/* jackpot++; */
J[i] = 0;
if (c != '\n')
- ctold += skipline(0);
+ ctold += skipline(f1);
if (d != '\n')
- ctnew += skipline(1);
+ ctnew += skipline(f2);
break;
}
if (c == '\n')
@@ -620,11 +731,8 @@ check(void)
ixnew[j] = ctnew;
j++;
}
- for (; j <= len[1]; j++) {
- ixnew[j] = ctnew += skipline(1);
- }
- fclose(input[0]);
- fclose(input[1]);
+ for (; j <= len[1]; j++)
+ ixnew[j] = ctnew += skipline(f2);
/*
* if (jackpot)
* fprintf(stderr, "jackpot\n");
@@ -678,27 +786,27 @@ unsort(struct line *f, int l, int *b)
}
static int
-skipline(int f)
+skipline(FILE *f)
{
int i, c;
- for (i = 1; (c = getc(input[f])) != '\n'; i++)
+ for (i = 1; (c = getc(f)) != '\n'; i++)
if (c < 0)
return (i);
return (i);
}
static void
-output(void)
+output(char *file1, FILE *f1, char *file2, FILE *f2)
{
int m, i0, i1, j0, j1;
- input[0] = fopen(file1, "r");
- input[1] = fopen(file2, "r");
+ rewind(f1);
+ rewind(f2);
m = len[0];
J[0] = 0;
J[m + 1] = len[1] + 1;
- if (opt != D_EDIT) {
+ if (format != D_EDIT) {
for (i0 = 1; i0 <= m; i0 = i1 + 1) {
while (i0 <= m && J[i0] == J[i0 - 1] + 1)
i0++;
@@ -708,7 +816,7 @@ output(void)
i1++;
j1 = J[i1 + 1] - 1;
J[i1] = j1;
- change(i0, i1, j0, j1);
+ change(file1, f1, file2, f2, i0, i1, j0, j1);
}
} else {
for (i0 = m; i0 >= 1; i0 = i1 - 1) {
@@ -720,15 +828,15 @@ output(void)
i1--;
j1 = J[i1 - 1] + 1;
J[i1] = j1;
- change(i1, i0, j1, j0);
+ change(file1, f1, file2, f2, i1, i0, j1, j0);
}
}
if (m == 0)
- change(1, 0, 1, len[1]);
- if (opt == D_IFDEF) {
+ change(file1, f1, file2, f2, 1, 0, 1, len[1]);
+ if (format == D_IFDEF) {
for (;;) {
#define c i0
- c = getc(input[0]);
+ c = getc(f1);
if (c < 0)
return;
putchar(c);
@@ -736,17 +844,17 @@ output(void)
#undef c
}
if (anychange != 0) {
- if (opt == D_CONTEXT)
- dump_context_vec();
- else if (opt == D_UNIFIED)
- dump_unified_vec();
+ if (format == D_CONTEXT)
+ dump_context_vec(f1, f2);
+ else if (format == D_UNIFIED)
+ dump_unified_vec(f1, f2);
}
}
/*
* The following struct is used to record change information when
- * doing a "context" diff. (see routine "change" to understand the
- * highly mneumonic field names)
+ * doing a "context" or "unified" diff. (see routine "change" to
+ * understand the highly mnemonic field names)
*/
struct context_vec {
int a; /* start line in old file */
@@ -760,35 +868,32 @@ struct context_vec *context_vec_start, *context_vec_end, *context_vec_ptr;
#define MAX_CONTEXT 128
/*
- * indicate that there is a difference between lines a and b of the from file
- * to get to lines c to d of the to file. If a is greater then b then there
+ * Indicate that there is a difference between lines a and b of the from file
+ * to get to lines c to d of the to file. If a is greater then b then there
* are no lines in the from file involved and this means that there were
- * lines appended (beginning at b). If c is greater than d then there are
+ * lines appended (beginning at b). If c is greater than d then there are
* lines missing from the to file.
*/
static void
-change(int a, int b, int c, int d)
+change(char *file1, FILE *f1, char *file2, FILE *f2, int a, int b, int c, int d)
{
- struct stat stbuf;
-
- if (opt != D_IFDEF && a > b && c > d)
+ if (format != D_IFDEF && a > b && c > d)
return;
if (anychange == 0) {
anychange = 1;
- if (opt == D_CONTEXT || opt == D_UNIFIED) {
- stat(file1, &stbuf);
- printf("%s %s %s", opt == D_CONTEXT ? "***" : "---",
- file1, ctime(&stbuf.st_mtime));
- stat(file2, &stbuf);
- printf("%s %s %s", opt == D_CONTEXT ? "---" : "+++",
- file2, ctime(&stbuf.st_mtime));
- context_vec_start = emalloc(MAX_CONTEXT *
- sizeof(struct context_vec));
+ if (format == D_CONTEXT || format == D_UNIFIED) {
+ printf("%s %s %s", format == D_CONTEXT ? "***" : "---",
+ file1, ctime(&stb1.st_mtime));
+ printf("%s %s %s", format == D_CONTEXT ? "---" : "+++",
+ file2, ctime(&stb2.st_mtime));
+ if (context_vec_start == NULL)
+ context_vec_start = emalloc(MAX_CONTEXT *
+ sizeof(struct context_vec));
context_vec_end = context_vec_start + MAX_CONTEXT;
context_vec_ptr = context_vec_start - 1;
}
}
- if (opt == D_CONTEXT || opt == D_UNIFIED) {
+ if (format == D_CONTEXT || format == D_UNIFIED) {
/*
* If this new change is within 'context' lines of
* the previous change, just add it to the change
@@ -800,10 +905,10 @@ change(int a, int b, int c, int d)
(context_vec_ptr >= context_vec_start &&
a > (context_vec_ptr->b + 2 * context) &&
c > (context_vec_ptr->d + 2 * context))) {
- if (opt == D_CONTEXT)
- dump_context_vec();
+ if (format == D_CONTEXT)
+ dump_context_vec(f1, f2);
else
- dump_unified_vec();
+ dump_unified_vec(f1, f2);
}
context_vec_ptr++;
context_vec_ptr->a = a;
@@ -812,13 +917,13 @@ change(int a, int b, int c, int d)
context_vec_ptr->d = d;
return;
}
- switch (opt) {
+ switch (format) {
case D_NORMAL:
case D_EDIT:
range(a, b, ",");
putchar(a > b ? 'a' : c > d ? 'd' : 'c');
- if (opt == D_NORMAL)
+ if (format == D_NORMAL)
range(c, d, ",");
putchar('\n');
break;
@@ -838,14 +943,14 @@ change(int a, int b, int c, int d)
}
break;
}
- if (opt == D_NORMAL || opt == D_IFDEF) {
- fetch(ixold, a, b, input[0], "< ", 1);
- if (a <= b && c <= d && opt == D_NORMAL)
- prints("---\n");
+ if (format == D_NORMAL || format == D_IFDEF) {
+ fetch(ixold, a, b, f1, "< ", 1);
+ if (a <= b && c <= d && format == D_NORMAL)
+ puts("---");
}
- fetch(ixnew, c, d, input[1], opt == D_NORMAL ? "> " : "", 0);
- if ((opt == D_EDIT || opt == D_REVERSE) && c <= d)
- prints(".\n");
+ fetch(ixnew, c, d, f2, format == D_NORMAL ? "> " : "", 0);
+ if ((format == D_EDIT || format == D_REVERSE) && c <= d)
+ puts(".");
if (inifdef) {
fprintf(stdout, "#endif /* %s */\n", ifdefname);
inifdef = 0;
@@ -869,7 +974,7 @@ fetch(long *f, int a, int b, FILE *lb, char *s, int oldfile)
* When doing #ifdef's, copy down to current line
* if this is the first file, so that stuff makes it to output.
*/
- if (opt == D_IFDEF && oldfile) {
+ if (format == D_IFDEF && oldfile) {
long curpos = ftell(lb);
/* print through if append (a>b), else to (nb: 0 vs 1 orig) */
nc = f[a > b ? b : a - 1] - curpos;
@@ -878,7 +983,7 @@ fetch(long *f, int a, int b, FILE *lb, char *s, int oldfile)
}
if (a > b)
return;
- if (opt == D_IFDEF) {
+ if (format == D_IFDEF) {
if (inifdef) {
fprintf(stdout, "#else /* %s%s */\n",
oldfile == 1 ? "!" : "", ifdefname);
@@ -893,8 +998,8 @@ fetch(long *f, int a, int b, FILE *lb, char *s, int oldfile)
for (i = a; i <= b; i++) {
fseek(lb, f[i - 1], SEEK_SET);
nc = f[i] - f[i - 1];
- if (opt != D_IFDEF)
- prints(s);
+ if (format != D_IFDEF)
+ fputs(s, stdout);
col = 0;
for (j = 0; j < nc; j++) {
c = getc(lb);
@@ -984,17 +1089,17 @@ readhash(FILE *f)
return ((short) low(sum) + (short) high(sum));
}
-static int
+int
asciifile(FILE *f)
{
char buf[BUFSIZ], *cp;
int cnt;
- if (aflag)
+ if (aflag || f == NULL)
return (1);
- fseek(f, 0L, SEEK_SET);
- cnt = fread(buf, 1, BUFSIZ, f);
+ rewind(f);
+ cnt = fread(buf, 1, sizeof(buf), f);
cp = buf;
while (--cnt >= 0)
if (*cp++ & 0200)
@@ -1002,9 +1107,19 @@ asciifile(FILE *f)
return (1);
}
+static __inline int min(int a, int b)
+{
+ return (a < b ? a : b);
+}
+
+static __inline int max(int a, int b)
+{
+ return (a > b ? a : b);
+}
+
/* dump accumulated "context" diff changes */
static void
-dump_context_vec(void)
+dump_context_vec(FILE *f1, FILE *f2)
{
struct context_vec *cvp = context_vec_start;
int lowa, upb, lowc, upd, do_output;
@@ -1025,7 +1140,7 @@ dump_context_vec(void)
printf(" ****\n");
/*
- * output changes to the "old" file. The first loop suppresses
+ * Output changes to the "old" file. The first loop suppresses
* output if there were no changes to the "old" file (we'll see
* the "old" lines as context in the "new" list).
*/
@@ -1049,16 +1164,16 @@ dump_context_vec(void)
ch = (a <= b) ? 'd' : 'a';
if (ch == 'a')
- fetch(ixold, lowa, b, input[0], " ", 0);
+ fetch(ixold, lowa, b, f1, " ", 0);
else {
- fetch(ixold, lowa, a - 1, input[0], " ", 0);
- fetch(ixold, a, b, input[0],
+ fetch(ixold, lowa, a - 1, f1, " ", 0);
+ fetch(ixold, a, b, f1,
ch == 'c' ? "! " : "- ", 0);
}
lowa = b + 1;
cvp++;
}
- fetch(ixold, b + 1, upb, input[0], " ", 0);
+ fetch(ixold, b + 1, upb, f1, " ", 0);
}
/* output changes to the "new" file */
printf("--- ");
@@ -1085,23 +1200,23 @@ dump_context_vec(void)
ch = (a <= b) ? 'd' : 'a';
if (ch == 'd')
- fetch(ixnew, lowc, d, input[1], " ", 0);
+ fetch(ixnew, lowc, d, f2, " ", 0);
else {
- fetch(ixnew, lowc, c - 1, input[1], " ", 0);
- fetch(ixnew, c, d, input[1],
+ fetch(ixnew, lowc, c - 1, f2, " ", 0);
+ fetch(ixnew, c, d, f2,
ch == 'c' ? "! " : "+ ", 0);
}
lowc = d + 1;
cvp++;
}
- fetch(ixnew, d + 1, upd, input[1], " ", 0);
+ fetch(ixnew, d + 1, upd, f2, " ", 0);
}
context_vec_ptr = context_vec_start - 1;
}
/* dump accumulated "unified" diff changes */
static void
-dump_unified_vec(void)
+dump_unified_vec(FILE *f1, FILE *f2)
{
struct context_vec *cvp = context_vec_start;
int lowa, upb, lowc, upd;
@@ -1142,23 +1257,23 @@ dump_unified_vec(void)
switch (ch) {
case 'c':
- fetch(ixold, lowa, a - 1, input[0], " ", 0);
- fetch(ixold, a, b, input[0], "-", 0);
- fetch(ixnew, c, d, input[1], "+", 0);
+ fetch(ixold, lowa, a - 1, f1, " ", 0);
+ fetch(ixold, a, b, f1, "-", 0);
+ fetch(ixnew, c, d, f2, "+", 0);
break;
case 'd':
- fetch(ixold, lowa, a - 1, input[0], " ", 0);
- fetch(ixold, a, b, input[0], "-", 0);
+ fetch(ixold, lowa, a - 1, f1, " ", 0);
+ fetch(ixold, a, b, f1, "-", 0);
break;
case 'a':
- fetch(ixnew, lowc, c - 1, input[1], " ", 0);
- fetch(ixnew, c, d, input[1], "+", 0);
+ fetch(ixnew, lowc, c - 1, f2, " ", 0);
+ fetch(ixnew, c, d, f2, "+", 0);
break;
}
lowa = b + 1;
lowc = d + 1;
}
- fetch(ixnew, d + 1, upd, input[1], " ", 0);
+ fetch(ixnew, d + 1, upd, f2, " ", 0);
context_vec_ptr = context_vec_start - 1;
}