1
0

Source code upload

This commit is contained in:
calmsacibis995
2022-09-29 17:59:04 +03:00
parent 72fa9da3d7
commit 8fc8fa8089
33399 changed files with 11964078 additions and 0 deletions

View File

@@ -0,0 +1,956 @@
--- source.gnu.orig/analyze.c Sun Jan 6 15:05:11 1991
+++ analyze.c Fri Jul 31 23:08:48 1992
@@ -35,6 +35,7 @@
void setup_output ();
extern int no_discards;
+extern int files_are_identical;
static int *xvec, *yvec; /* Vectors being compared. */
static int *fdiag; /* Vector, indexed by diagonal, containing
@@ -711,7 +712,112 @@
return script;
}
-
+
+#include <invent.h>
+/* Return size of main memory in bytes */
+memsize(){
+ inventory_t *getinvent(void);
+ inventory_t *sp;
+ static int sz = 0;
+
+ if (sz == 0)
+ {
+ while ((sp = getinvent()) != 0)
+ {
+ if (sp->inv_class == INV_MEMORY && sp->inv_type == INV_MAIN)
+ {
+ sz = sp->inv_state;
+ break;
+ }
+ }
+ }
+
+ if (sz == 0)
+ sz = 8*1024*1024; /* 8 MByte default main memory size */
+
+ return sz;
+}
+
+#include <signal.h>
+#include <unistd.h>
+#include <sys/wait.h>
+
+int
+tryodiff (char *cmd, int argc, char **argv)
+{
+ int status, pid, w, sig;
+ struct sigaction oldistat, oldqstat, oldcstat, newiqstat, newcstat, newustat;
+
+ /*
+ * ignore INT and QUIT, saving previous handlers and masks
+ */
+ if (sigaction(SIGINT,NULL,&oldistat) == -1)
+ return(-1);
+
+ newiqstat.sa_handler = SIG_IGN;
+ newiqstat.sa_flags = 0;
+ newcstat.sa_handler = SIG_DFL;
+ newcstat.sa_flags = 0;
+
+ if ( (sigaction(SIGINT,&newiqstat,&oldistat) == -1) ||
+ (sigaction(SIGQUIT,&newiqstat,&oldqstat) == -1) ||
+ (sigaction(SIGCLD,&newcstat,&oldcstat) == -1) ) {
+ return(-1);
+ }
+
+ if ((pid = fork()) == 0) {
+ char *emsg = ": sigaction internal botch\n";
+ /* Child process */
+ /* reinstall old handlers and masks. */
+ (void) sigaction(SIGINT,&oldistat,NULL);
+ (void) sigaction(SIGQUIT,&oldqstat,NULL);
+ (void) sigaction(SIGCLD,&oldcstat,NULL);
+ argv[0] = cmd;
+ (void) execvp(argv[0], argv);
+
+ /* oops - exec failed - tell parent that we didn't
+ * do anything useful by committing SIGUSR2 harikari.
+ */
+ newustat.sa_handler = SIG_DFL;
+ newustat.sa_flags = 0;
+ sigaction(SIGUSR2,&newustat,NULL);
+ kill(getpid(), SIGUSR2);
+ /* should be dead by now -- but just in case ... */
+ /* Avoid stdio: parent process's buffers are inherited. */
+ write (fileno (stderr), program, strlen (program));
+ write (fileno (stderr), emsg, strlen(emsg));
+ _exit(127); /* dont double fflush stdio */
+ /* NOTREACHED */
+ }
+
+ if (pid < 0) {
+ w = -1; /* fork failed */
+ } else {
+ w = waitpid(pid,&status,0);
+ }
+
+ /* reinstall old handlers and masks. */
+ (void) sigaction(SIGINT,&oldistat,NULL);
+ (void) sigaction(SIGQUIT,&oldqstat,NULL);
+ (void) sigaction(SIGCLD,&oldcstat,NULL);
+
+ sig = WTERMSIG(status);
+
+ if (w == -1)
+ return -1; /* fork failed */
+ else if (WIFSIGNALED(status) && sig == SIGUSR2)
+ return -1; /* exec failed */
+ else if (WIFEXITED(status))
+ return WEXITSTATUS(status); /* normal odiff exit */
+ else if (WIFSIGNALED(status) && (sig == SIGINT || sig == SIGQUIT))
+ kill(getpid(), sig); /* reissue held off signal to self */
+ return 2; /* problems */
+}
+
+extern int xargc;
+extern char **xargv;
+extern int gnudiffopts;
+
/* Report the differences of two files. DEPTH is the current directory
depth. */
int
@@ -734,8 +840,42 @@
&& filevec[0].stat.st_dev == filevec[1].stat.st_dev)
return 0;
+ /* See if the two named files are too big to fit in memory
+ comfortably. Since GNU diff reads/mmaps both files into its
+ virtual addr space, it pages heavily on huge files. The old BSD
+ derived "odiff" is much more space (swap and main memory)
+ efficient. But if the files fit in main memory, then the GNU
+ diff is quite a bit faster - as much as 2x to 3x faster. Arbitrarily
+ consider 1/4 Main Memory size as too big. User can force choice:
+ specify -H always gets GNU diff, use odiff always gets the old BSD diff.
+ Return of -1 from tryodiff means that odiff wasn't even run - so we
+ should try further here instead. */
+
+ if (gnudiffopts == 0 &&
+ (filevec[0].stat.st_size + filevec[1].stat.st_size) > memsize()/4 )
+ {
+ int ret;
+ if ((ret = tryodiff("odiff",xargc,xargv)) != -1)
+ return ret;
+ }
+
+ files_are_identical = 0;
+
binary = read_files (filevec);
+ if (files_are_identical)
+ {
+ for (i = 0; i < 2; ++i)
+ if (filevec[i].buffer)
+ {
+ if (filevec[i].buffer_was_mmapped)
+ munmap (filevec[i].buffer, filevec[i].bufsize + 2);
+ else
+ free (filevec[i].buffer);
+ }
+ return 0;
+ }
+
/* If we have detected that file 0 is a binary file,
compare the two files as binary. This can happen
only when the first chunk is read.
@@ -753,7 +893,12 @@
for (i = 0; i < 2; ++i)
if (filevec[i].buffer)
+ {
+ if (filevec[i].buffer_was_mmapped)
+ munmap (filevec[i].buffer, filevec[i].bufsize + 2);
+ else
free (filevec[i].buffer);
+ }
return differs;
}
@@ -900,7 +1045,12 @@
for (i = 0; i < 2; ++i)
{
if (filevec[i].buffer != 0)
+ {
+ if (filevec[i].buffer_was_mmapped)
+ munmap (filevec[i].buffer, filevec[i].bufsize + 2);
+ else
free (filevec[i].buffer);
+ }
free (filevec[i].linbuf);
}
--- source.gnu.orig/diff.c Mon Mar 9 19:58:10 1992
+++ diff.c Fri Jul 31 23:08:49 1992
@@ -23,7 +23,7 @@
#define GDIFF_MAIN
#include "regex.h"
#include "diff.h"
-#include "getopt.h"
+#include <getopt.h>
/* Nonzero for -r: if comparing two directories,
@@ -66,45 +66,12 @@
return result;
}
-
-/* The numbers 129 and 130 that appear in the fourth element
- for the context and unidiff entries are used as a way of
- telling the big switch in `main' how to process those options. */
-static struct option longopts[] =
-{
- {"ignore-blank-lines", 0, 0, 'B'},
- {"context", 2, 0, 129},
- {"ifdef", 1, 0, 'D'},
- {"show-function-line", 1, 0, 'F'},
- {"speed-large-files", 0, 0, 'H'},
- {"ignore-matching-lines", 1, 0, 'I'},
- {"file-label", 1, 0, 'L'},
- {"entire-new-files", 0, 0, 'N'},
- {"new-files", 0, 0, 'N'},
- {"starting-file", 1, 0, 'S'},
- {"initial-tab", 0, 0, 'T'},
- {"text", 0, 0, 'a'},
- {"all-text", 0, 0, 'a'},
- {"ascii", 0, 0, 'a'},
- {"ignore-space-change", 0, 0, 'b'},
- {"minimal", 0, 0, 'd'},
- {"ed", 0, 0, 'e'},
- {"reversed-ed", 0, 0, 'f'},
- {"ignore-case", 0, 0, 'i'},
- {"print", 0, 0, 'l'},
- {"rcs", 0, 0, 'n'},
- {"show-c-function", 0, 0, 'p'},
- {"binary", 0, 0, 'q'},
- {"brief", 0, 0, 'q'},
- {"recursive", 0, 0, 'r'},
- {"report-identical-files", 0, 0, 's'},
- {"expand-tabs", 0, 0, 't'},
- {"ignore-all-space", 0, 0, 'w'},
- {"unified", 2, 0, 130},
- {"version", 0, 0, 'v'},
- {0, 0, 0, 0}
-};
+int xargc;
+char **xargv;
+int gnudiffopts;
+int sgidiffopts;
+
main (argc, argv)
int argc;
@@ -113,8 +80,10 @@
int val;
int c;
int prev = -1;
- int longind;
extern char *version_string;
+ extern char *optarg;
+ extern int optind;
+ extern void setxpat(char *);
program = argv[0];
@@ -143,28 +112,30 @@
msg_chain = NULL;
msg_chain_end = NULL;
no_discards = 0;
+ gnudiffopts = 0;
+ sgidiffopts = 0;
+ xargc = argc;
+ xargv = argv;
/* Decode the options. */
- while ((c = getopt_long (argc, argv,
- "0123456789abBcC:dD:efF:hHiI:lL:nNpqrsS:tTuvw",
- longopts, &longind)) != EOF)
+ while ((c = getopt (argc, argv,
+ "0123456789abBcC:dD:efF:hHiI:lL:nNpqrsS:tTuvwx:"
+ )) != EOF)
{
- if (c == 0) /* Long option. */
- c = longopts[longind].val;
switch (c)
{
/* All digits combine in decimal to specify the context-size. */
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- case '0':
+ case '1': gnudiffopts++;
+ case '2': gnudiffopts++;
+ case '3': gnudiffopts++;
+ case '4': gnudiffopts++;
+ case '5': gnudiffopts++;
+ case '6': gnudiffopts++;
+ case '7': gnudiffopts++;
+ case '8': gnudiffopts++;
+ case '9': gnudiffopts++;
+ case '0': gnudiffopts++;
if (context == -1)
context = 0;
/* If a context length has already been specified,
@@ -176,25 +147,23 @@
context = context * 10 + c - '0';
break;
- case 'a':
+ case 'a': gnudiffopts++;
/* Treat all files as text files; never treat as binary. */
always_text_flag = 1;
break;
- case 'b':
+ case 'b': sgidiffopts++;
/* Ignore changes in amount of whitespace. */
ignore_space_change_flag = 1;
length_varies = 1;
break;
- case 'B':
+ case 'B': gnudiffopts++;
/* Ignore changes affecting only blank lines. */
ignore_blank_lines_flag = 1;
break;
- case 'C':
- case 129: /* +context[=lines] */
- case 130: /* +unified[=lines] */
+ case 'C': gnudiffopts++;
if (optarg)
{
if (context >= 0)
@@ -209,35 +178,35 @@
}
/* Falls through. */
- case 'c':
+ case 'c': sgidiffopts++;
/* Make context-style output. */
specify_style (c == 130 ? OUTPUT_UNIFIED : OUTPUT_CONTEXT);
break;
- case 'd':
+ case 'd': gnudiffopts++;
/* Don't discard lines. This makes things slower (sometimes much
slower) but will find a guaranteed minimal set of changes. */
no_discards = 1;
break;
- case 'D':
+ case 'D': sgidiffopts++;
/* Make merged #ifdef output. */
specify_style (OUTPUT_IFDEF);
ifdef_string = optarg;
break;
- case 'e':
+ case 'e': sgidiffopts++;
/* Make output that is a valid `ed' script. */
specify_style (OUTPUT_ED);
break;
- case 'f':
+ case 'f': sgidiffopts++;
/* Make output that looks vaguely like an `ed' script
but has changes in the order they appear in the file. */
specify_style (OUTPUT_FORWARD_ED);
break;
- case 'F':
+ case 'F': gnudiffopts++;
/* Show, for each set of changes, the previous line that
matches the specified regexp. Currently affects only
context-style output. */
@@ -244,7 +213,7 @@
function_regexp = optarg;
break;
- case 'h':
+ case 'h': sgidiffopts++;
/* Split the files into chunks of around 1500 lines
for faster processing. Usually does not change the result.
@@ -251,29 +220,29 @@
This currently has no effect. */
break;
- case 'H':
+ case 'H': gnudiffopts++;
/* Turn on heuristics that speed processing of large files
with a small density of changes. */
heuristic = 1;
break;
- case 'i':
+ case 'i': sgidiffopts++;
/* Ignore changes in case. */
ignore_case_flag = 1;
break;
- case 'I':
+ case 'I': gnudiffopts++;
/* Ignore changes affecting only lines that match the
specified regexp. */
ignore_regexp = optarg;
break;
- case 'l':
+ case 'l': sgidiffopts++;
/* Pass the output through `pr' to paginate it. */
paginate_flag = 1;
break;
- case 'L':
+ case 'L': gnudiffopts++;
/* Specify file labels for `-c' output headers. */
if (!file_label[0])
file_label[0] = optarg;
@@ -283,52 +252,52 @@
fatal ("too many file label options");
break;
- case 'n':
+ case 'n': sgidiffopts++;
/* Output RCS-style diffs, like `-f' except that each command
specifies the number of lines affected. */
specify_style (OUTPUT_RCS);
break;
- case 'N':
+ case 'N': gnudiffopts++;
/* When comparing directories, if a file appears only in one
directory, treat it as present but empty in the other. */
entire_new_file_flag = 1;
break;
- case 'p':
+ case 'p': gnudiffopts++;
/* Make context-style output and show name of last C function. */
specify_style (OUTPUT_CONTEXT);
function_regexp = "^[_a-zA-Z]";
break;
- case 'q':
+ case 'q': gnudiffopts++;
no_details_flag = 1;
break;
- case 'r':
+ case 'r': sgidiffopts++;
/* When comparing directories,
recursively compare any subdirectories found. */
recursive = 1;
break;
- case 's':
+ case 's': sgidiffopts++;
/* Print a message if the files are the same. */
print_file_same_flag = 1;
break;
- case 'S':
+ case 'S': sgidiffopts++;
/* When comparing directories, start with the specified
file name. This is used for resuming an aborted comparison. */
dir_start_file = optarg;
break;
- case 't':
+ case 't': sgidiffopts++;
/* Expand tabs to spaces in the output so that it preserves
the alignment of the input files. */
tab_expand_flag = 1;
break;
- case 'T':
+ case 'T': gnudiffopts++;
/* Use a tab in the output, rather than a space, before the
text of an input line, so as to keep the proper alignment
in the input line without changing the characters in it. */
@@ -335,21 +304,25 @@
tab_align_flag = 1;
break;
- case 'v':
+ case 'v': gnudiffopts++;
printf ("GNU diff version %s\n", version_string);
break;
- case 'u':
+ case 'u': gnudiffopts++;
/* Output the context diff in unidiff format. */
specify_style (OUTPUT_UNIFIED);
break;
- case 'w':
+ case 'w': sgidiffopts++;
/* Ignore horizontal whitespace when comparing lines. */
ignore_all_space_flag = 1;
length_varies = 1;
break;
+ case 'x': sgidiffopts++;
+ setxpat(optarg);
+ break;
+
default:
usage ();
}
@@ -401,19 +374,8 @@
usage ()
{
- fprintf (stderr, "\
-Usage: diff [-#] [-abBcdefhHilnNprstTuvw] [-C lines] [-F regexp] [-I regexp]\n\
- [-L label [-L label]] [-S file] [-D symbol] [+ignore-blank-lines]\n\
- [+context[=lines]] [+unified[=lines]] [+ifdef=symbol]\n\
- [+show-function-line=regexp]\n");
- fprintf (stderr, "\
- [+speed-large-files] [+ignore-matching-lines=regexp] [+new-file]\n\
- [+initial-tab] [+starting-file=file] [+text] [+all-text] [+ascii]\n\
- [+minimal] [+ignore-space-change] [+ed] [+reversed-ed] [+ignore-case]\n");
- fprintf (stderr, "\
- [+print] [+rcs] [+show-c-function] [+binary] [+brief] [+recursive]\n\
- [+report-identical-files] [+expand-tabs] [+ignore-all-space]\n\
- [+file-label=label [+file-label=label]] [+version] path1 path2\n");
+ fprintf (stderr, "Usage: diff [-bcefhilnrstw -Dstring -Sname -xpattern ] file1 file2\n");
+ fprintf (stderr, "\tGNU diff options: [-# -aBdHNpqTuv -Cnum -Fregexp -Iregexp -Llabel]\n");
exit (2);
}
--- source.gnu.orig/diff.h Mon Dec 9 21:50:39 1991
+++ diff.h Fri Jul 31 23:08:50 1992
@@ -90,7 +90,7 @@
#endif
/* Support old-fashioned C compilers. */
-#if !defined (__STDC__) && !defined (__GNUC__)
+#if !defined (__STDC__) && !defined (__GNUC__) && !defined(_MODERN_C)
#define const
#endif
@@ -314,6 +314,8 @@
The allocated size is always linbufsize
and the number of valid elements is buffered_lines. */
int *ltran;
+ /* 1 if buffer was mmapped - need to munmap instead of free */
+ int buffer_was_mmapped;
};
/* Describe the two files currently being compared. */
--- source.gnu.orig/dir.c Mon Mar 9 19:57:40 1992
+++ dir.c Fri Jul 31 23:08:50 1992
@@ -17,8 +17,41 @@
along with GNU DIFF; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+#include "regex.h"
#include "diff.h"
+static struct re_pattern_buffer **revec = NULL;
+static struct re_pattern_buffer **revec_end;
+
+/* add a directory name to the list to exclude
+ */
+void
+setxpat(char *pat)
+{
+ char *val;
+ int old_re_syntax = re_set_syntax (RE_SYNTAX_EGREP);
+
+ if (revec == NULL)
+ revec_end = revec = (struct re_pattern_buffer **) xmalloc (sizeof *revec);
+ else
+ {
+ int oldsz = revec_end - revec;
+ revec = (struct re_pattern_buffer **) xrealloc (revec, (oldsz+1) * (sizeof *revec));
+ revec_end = revec + oldsz;
+ }
+ *revec_end = (struct re_pattern_buffer *) xmalloc (sizeof (struct re_pattern_buffer));
+ bzero (*revec_end, sizeof (struct re_pattern_buffer));
+ if ((val = re_compile_pattern (pat, strlen(pat), *revec_end)) != NULL)
+ {
+ error ("%s: %s", pat, val);
+ fatal ("use egrep(1) style patterns");
+ /* NOTREACHED */
+ }
+ (*revec_end)->fastmap = (char *) xmalloc (256);
+ revec_end++;
+ re_set_syntax (old_re_syntax);
+}
+
static int compare_names ();
/* Read the directory named DIRNAME and return a sorted vector
@@ -76,6 +109,21 @@
while (next = readdir (reading))
{
+ if (revec)
+ {
+ struct re_pattern_buffer **rep;
+ int old_re_syntax = re_set_syntax (RE_SYNTAX_EGREP);
+ char *s = next->d_name;
+ int len = strlen (s);
+
+ for (rep = revec; rep < revec_end; rep++)
+ if (re_search (*rep, s, len, 0, len, 0) >= 0)
+ break;
+ re_set_syntax (old_re_syntax);
+ if (rep != revec_end)
+ continue;
+ }
+
/* Ignore the files `.' and `..' */
if (next->d_name[0] == '.'
&& (next->d_name[1] == 0
--- source.gnu.orig/io.c Thu Nov 29 13:15:43 1990
+++ io.c Fri Jul 31 23:08:51 1992
@@ -18,6 +18,7 @@
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "diff.h"
+#include <sys/mman.h>
/* Rotate a value n bits to the left. */
#define UINT_BIT (sizeof (unsigned) * CHAR_BIT)
@@ -28,10 +29,11 @@
/* Current file under consideration. */
struct file_data *current;
+int files_are_identical;
/* Check for binary files and compare them for exact identity. */
-/* Return 1 if BUF contains a non text character.
+/* Return 1 if BUF contains a nul character.
SIZE is the number of characters in BUF. */
static int
@@ -39,48 +41,13 @@
char *buf;
int size;
{
- static const char textchar[] = {
- /* ISO 8859 */
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 1, 1, 1, 1, 1, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- };
while (--size >= 0)
- if (!textchar[*buf++ & 0377])
+ if (*buf++ == '\0')
return 1;
return 0;
}
-int binary_file_threshold = 512;
+int binary_file_threshold = BUFSIZ;
/* Slurp the current file completely into core.
Return nonzero if it appears to be a binary file. */
@@ -104,6 +71,17 @@
else if ((current->stat.st_mode & S_IFMT) == S_IFREG)
{
current->bufsize = current->stat.st_size;
+ current->buffer = (char *)(-1);
+ current->buffer_was_mmapped = 0;
+ if (current->bufsize > 0) {
+ current->buffer
+ = (char *)mmap((void *)0, current->bufsize + 2,
+ PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_AUTOGROW, current->desc, 0);
+ }
+ if ((int)(current->buffer) != -1) {
+ current->buffered_chars = current->bufsize;
+ current->buffer_was_mmapped = 1;
+ } else {
current->buffer = (char *) xmalloc (current->bufsize + 2);
current->buffered_chars
= read (current->desc, current->buffer, current->bufsize);
@@ -110,6 +88,7 @@
if (current->buffered_chars < 0)
pfatal_with_name (current->name);
}
+ }
else
{
int cc;
@@ -334,6 +313,43 @@
&& current->suffix_begin == current->buffer + current->buffered_chars)
--current->linbuf[current->buffered_lines - 1].length;
}
+
+/* For same size files, look for mismatch w/o counting lines, in case identical */
+loop_for_mismatch (pp0, pp1)
+ char **pp0, **pp1;
+{
+ char *p0 = *pp0;
+ char *p1 = *pp1;
+
+ {
+ register int *ip0 = (int *)p0;
+ register int *ip1 = (int *)p1;
+ while (*ip0++ == *ip1++)
+ ;
+ --ip0; --ip1;
+ p0 = (char *)(ip0);
+ p1 = (char *)(ip1);
+ }
+ while (*p0++ == *p1++)
+ ;
+ *pp0 = p0;
+ *pp1 = p1;
+}
+
+/* Don't count lines until failed files_are_identical test */
+loop_for_line_count (pbase, pend)
+ char *pbase, *pend;
+{
+ int i = 0;
+ int j = pend - pbase;
+ int lines = 0;
+
+ while (i < j)
+ if (pbase[i++] == '\n')
+ ++lines;
+
+ return lines;
+}
/* Given a vector of two file_data objects, find the identical
prefixes and suffixes of each object. */
@@ -370,7 +386,28 @@
else
p1[filevec[1].buffered_chars] = ~p0[filevec[1].buffered_chars];
+ if (filevec[0].buffered_chars == filevec[1].buffered_chars)
+ {
/* Loop until first mismatch, or to the sentinel characters. */
+ loop_for_mismatch (&p0, &p1);
+
+ /* If the sentinel was passed, and lengths are equal, the
+ files are identical. */
+ if (p0 - filevec[0].buffer > filevec[0].buffered_chars)
+ {
+ filevec[0].prefix_end = p0 - 1;
+ filevec[1].prefix_end = p1 - 1;
+ filevec[0].prefix_lines = filevec[1].prefix_lines = 0;
+ filevec[0].suffix_begin = filevec[0].buffer;
+ filevec[1].suffix_begin = filevec[1].buffer;
+ filevec[0].suffix_lines = filevec[1].suffix_lines = 0;
+ files_are_identical = 1;
+ return;
+ }
+
+ lines = loop_for_line_count (filevec[0].buffer, p0 - 1);
+ }
+ else
while (1)
{
char c = *p0++;
@@ -389,20 +426,6 @@
&& p1 - filevec[1].buffer > filevec[1].buffered_chars)))
--p0, --p1, --lines;
- /* If the sentinel was passed, and lengths are equal, the
- files are identical. */
- if (p0 - filevec[0].buffer > filevec[0].buffered_chars
- && filevec[0].buffered_chars == filevec[1].buffered_chars)
- {
- filevec[0].prefix_end = p0 - 1;
- filevec[1].prefix_end = p1 - 1;
- filevec[0].prefix_lines = filevec[1].prefix_lines = lines;
- filevec[0].suffix_begin = filevec[0].buffer;
- filevec[1].suffix_begin = filevec[1].buffer;
- filevec[0].suffix_lines = filevec[1].suffix_lines = lines;
- return;
- }
-
/* Point at first nonmatching characters. */
--p0, --p1;
@@ -592,7 +615,12 @@
if (binary || this_binary)
return 1;
+ files_are_identical = 0;
+
find_identical_ends (filevec);
+
+ if (files_are_identical)
+ return 0;
for (i = 0; i < 2; ++i)
{
--- source.gnu.orig/util.c Sun Jan 6 15:14:14 1991
+++ util.c Fri Jul 31 23:08:53 1992
@@ -203,33 +203,24 @@
{
register char *t1, *t2;
register char end_char = line_end_char;
- int savechar;
/* Check first for exact identity.
If that is true, return 0 immediately.
This detects the common case of exact identity
- faster than complete comparison would. */
+ faster than complete comparison would.
+ The check for equal lengths is almost always not needed.
+ Only if the last line of two files both hash to the same
+ value, and the last line in the first file is a prefix
+ of the last line in the second file, and the first file
+ lacks a trailing newline, and length_varies is set,
+ and a ROBUST output style is chosen (which doesnt include
+ the artificial final newline in the length of the final line)
+ THEN does the length compare become critical to avoid falsely
+ concluding that the two lines are the same. Many thanks
+ to Paul Eggert for noticing this bug. */
- t1 = s1->text;
- t2 = s2->text;
-
- /* Alter the character following line 2 so it doesn't
- match that following line 1.
- (We used to alter the character after line 1,
- but that caused trouble if line 2 directly follows line 1.) */
- savechar = s2->text[s2->length];
- s2->text[s2->length] = s1->text[s1->length] + 1;
-
- /* Now find the first mismatch; this won't go past the
- character we just changed. */
- while (*t1++ == *t2++);
-
- /* Undo the alteration. */
- s2->text[s2->length] = savechar;
-
- /* If the comparison stopped at the alteration,
- the two lines are identical. */
- if (t2 == s2->text + s2->length + 1)
+ if (s1->length == s2->length
+ && memcmp (s1->text, s2->text, s1->length) == 0)
return 0;
/* Not exactly identical, but perhaps they match anyway
--- source.gnu.orig/diff3.c Fri Sep 30 22:14:15 1994
+++ diff3.c Tue Apr 15 17:16:51 1997
@@ -20,7 +20,7 @@
#include "system.h"
#include <stdio.h>
#include <signal.h>
-#include "getopt.h"
+#include <getopt.h>
extern char const version_string[];
@@ -202,6 +202,7 @@
static char const diff_program[] = DIFF_PROGRAM;
+#if 0
static struct option const longopts[] =
{
{"text", 0, 0, 'a'},
@@ -217,6 +218,7 @@
{"help", 0, 0, 129},
{0, 0, 0, 0}
};
+#endif
/*
* Main program. Calls diff twice on two pairs of input files,
@@ -243,7 +245,7 @@
initialize_main (&argc, &argv);
program_name = argv[0];
- while ((c = getopt_long (argc, argv, "aeimvx3AEL:TX", longopts, 0)) != EOF)
+ while ((c = getopt (argc, argv, "aeimvx3AEL:TX")) != EOF)
{
switch (c)
{
@@ -281,9 +283,11 @@
case 'T':
tab_align_flag = 1;
break;
+#if 0
case 'v':
printf ("diff3 - GNU diffutils version %s\n", version_string);
exit (0);
+#endif
case 129:
usage ();
check_stdout ();
@@ -561,9 +565,9 @@
*tmpblock,
**result_end;
- struct diff3_block const *last_diff3;
+ struct diff3_block *last_diff3;
- static struct diff3_block const zero_diff3;
+ static struct diff3_block zero_diff3;
/* Initialization */
result = 0;
@@ -1152,9 +1156,11 @@
*ap++ = diff_program;
if (always_text)
*ap++ = "-a";
+#if 0
sprintf (horizon_arg, "--horizon-lines=%d", horizon_lines);
*ap++ = horizon_arg;
*ap++ = "--";
+#endif
*ap++ = filea;
*ap++ = fileb;
*ap = 0;