summaryrefslogtreecommitdiffstats
path: root/gnu/usr.bin/diff/diff3.c
diff options
context:
space:
mode:
authorpeter <peter@FreeBSD.org>1995-10-28 18:51:33 +0000
committerpeter <peter@FreeBSD.org>1995-10-28 18:51:33 +0000
commit27378b5694b4941bb63a62097f7ee523da0a35bb (patch)
tree9372a0168d8ef1138d4ec4ef2051198caed461de /gnu/usr.bin/diff/diff3.c
parent31fbfe9bebb8e48eaf39efc88875c743cf238ced (diff)
downloadFreeBSD-src-27378b5694b4941bb63a62097f7ee523da0a35bb.zip
FreeBSD-src-27378b5694b4941bb63a62097f7ee523da0a35bb.tar.gz
Import GNU diffutils 2.7
Note, this is going to be messy.. 2.3 was vendor-branch imported, while 2.6 was done as a delta. Sigh. I'm importing this on a vendor branch so that it will be easier to deal with next time.. (cvs-1.6 wants rcs-5.7, and rcs-5.7 suggests diffutils-2.7)
Diffstat (limited to 'gnu/usr.bin/diff/diff3.c')
-rw-r--r--gnu/usr.bin/diff/diff3.c495
1 files changed, 290 insertions, 205 deletions
diff --git a/gnu/usr.bin/diff/diff3.c b/gnu/usr.bin/diff/diff3.c
index b9952fc..5d94ab8 100644
--- a/gnu/usr.bin/diff/diff3.c
+++ b/gnu/usr.bin/diff/diff3.c
@@ -1,5 +1,5 @@
/* Three way file comparison program (diff3) for Project GNU.
- Copyright (C) 1988, 1989, 1992 Free Software Foundation, Inc.
+ Copyright (C) 1988, 1989, 1992, 1993, 1994 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -17,16 +17,12 @@
/* Written by Randy Smith */
-#if __STDC__
-#define VOID void
-#else
-#define VOID char
-#endif
-
+#include "system.h"
#include <stdio.h>
-#include <ctype.h>
+#include <signal.h>
#include "getopt.h"
-#include "system.h"
+
+extern char const version_string[];
/*
* Internal data structures and macros for the diff3 program; includes
@@ -70,7 +66,7 @@ enum diff_type {
struct diff_block {
int ranges[2][2]; /* Ranges are inclusive */
char **lines[2]; /* The actual lines (may contain nulls) */
- int *lengths[2]; /* Line lengths (including newlines, if any) */
+ size_t *lengths[2]; /* Line lengths (including newlines, if any) */
struct diff_block *next;
};
@@ -80,7 +76,7 @@ struct diff3_block {
enum diff_type correspond; /* Type of diff */
int ranges[3][2]; /* Ranges are inclusive */
char **lines[3]; /* The actual lines (may contain nulls) */
- int *lengths[3]; /* Line lengths (including newlines, if any) */
+ size_t *lengths[3]; /* Line lengths (including newlines, if any) */
struct diff3_block *next;
};
@@ -158,6 +154,9 @@ static int flagging;
/* Number of lines to keep in identical prefix and suffix. */
static int horizon_lines = 10;
+/* Use a tab to align output lines (-T). */
+static int tab_align_flag;
+
/* If nonzero, do not output information for overlapping diffs. */
static int simple_only;
@@ -174,48 +173,48 @@ static int finalwrite;
/* If nonzero, output a merged file. */
static int merge;
-static char *argv0;
-
-/*
- * Forward function declarations.
- */
-static int myread ();
-static void fatal ();
-static void perror_with_exit ();
-static struct diff_block *process_diff ();
-static struct diff3_block *make_3way_diff ();
-static void output_diff3 ();
-static int output_diff3_edscript ();
-static int output_diff3_merge ();
-static void usage ();
-
-static struct diff3_block *using_to_diff3_block ();
-static int copy_stringlist ();
-static struct diff3_block *create_diff3_block ();
-static int compare_line_list ();
-
-static char *read_diff ();
-static enum diff_type process_diff_control ();
-static char *scan_diff_line ();
-
-static struct diff3_block *reverse_diff3_blocklist ();
-
-VOID *xmalloc ();
-static VOID *xrealloc ();
-
-static char diff_program[] = DIFF_PROGRAM;
-
-static struct option longopts[] =
+static char *program_name;
+
+static VOID *xmalloc PARAMS((size_t));
+static VOID *xrealloc PARAMS((VOID *, size_t));
+
+static char *read_diff PARAMS((char const *, char const *, char **));
+static char *scan_diff_line PARAMS((char *, char **, size_t *, char *, int));
+static enum diff_type process_diff_control PARAMS((char **, struct diff_block *));
+static int compare_line_list PARAMS((char * const[], size_t const[], char * const[], size_t const[], int));
+static int copy_stringlist PARAMS((char * const[], size_t const[], char *[], size_t[], int));
+static int dotlines PARAMS((FILE *, struct diff3_block *, int));
+static int output_diff3_edscript PARAMS((FILE *, struct diff3_block *, int const[3], int const[3], char const *, char const *, char const *));
+static int output_diff3_merge PARAMS((FILE *, FILE *, struct diff3_block *, int const[3], int const[3], char const *, char const *, char const *));
+static size_t myread PARAMS((int, char *, size_t));
+static struct diff3_block *create_diff3_block PARAMS((int, int, int, int, int, int));
+static struct diff3_block *make_3way_diff PARAMS((struct diff_block *, struct diff_block *));
+static struct diff3_block *reverse_diff3_blocklist PARAMS((struct diff3_block *));
+static struct diff3_block *using_to_diff3_block PARAMS((struct diff_block *[2], struct diff_block *[2], int, int, struct diff3_block const *));
+static struct diff_block *process_diff PARAMS((char const *, char const *, struct diff_block **));
+static void check_stdout PARAMS((void));
+static void fatal PARAMS((char const *));
+static void output_diff3 PARAMS((FILE *, struct diff3_block *, int const[3], int const[3]));
+static void perror_with_exit PARAMS((char const *));
+static void try_help PARAMS((char const *));
+static void undotlines PARAMS((FILE *, int, int, int));
+static void usage PARAMS((void));
+
+static char const diff_program[] = DIFF_PROGRAM;
+
+static struct option const longopts[] =
{
- {"text", 0, NULL, 'a'},
- {"show-all", 0, NULL, 'A'},
- {"ed", 0, NULL, 'e'},
- {"show-overlap", 0, NULL, 'E'},
- {"label", 1, NULL, 'L'},
- {"merge", 0, NULL, 'm'},
- {"overlap-only", 0, NULL, 'x'},
- {"easy-only", 0, NULL, '3'},
- {"version", 0, NULL, 'v'},
+ {"text", 0, 0, 'a'},
+ {"show-all", 0, 0, 'A'},
+ {"ed", 0, 0, 'e'},
+ {"show-overlap", 0, 0, 'E'},
+ {"label", 1, 0, 'L'},
+ {"merge", 0, 0, 'm'},
+ {"initial-tab", 0, 0, 'T'},
+ {"overlap-only", 0, 0, 'x'},
+ {"easy-only", 0, 0, '3'},
+ {"version", 0, 0, 'v'},
+ {"help", 0, 0, 129},
{0, 0, 0, 0}
};
@@ -228,27 +227,23 @@ main (argc, argv)
int argc;
char **argv;
{
- extern char *version_string;
int c, i;
int mapping[3];
int rev_mapping[3];
- int incompat;
+ int incompat = 0;
int conflicts_found;
struct diff_block *thread0, *thread1, *last_block;
struct diff3_block *diff3;
int tag_count = 0;
char *tag_strings[3];
- extern char *optarg;
char *commonname;
char **file;
struct stat statb;
- incompat = 0;
-
- argv0 = argv[0];
+ initialize_main (&argc, &argv);
+ program_name = argv[0];
- while ((c = getopt_long (argc, argv, "aeimvx3AEXL:", longopts, (int *) 0))
- != EOF)
+ while ((c = getopt_long (argc, argv, "aeimvx3AEL:TX", longopts, 0)) != EOF)
{
switch (c)
{
@@ -283,9 +278,16 @@ main (argc, argv)
case 'e':
incompat++;
break;
- case 'v':
- fprintf (stderr, "GNU diff3 version %s\n", version_string);
+ case 'T':
+ tab_align_flag = 1;
break;
+ case 'v':
+ printf ("diff3 - GNU diffutils version %s\n", version_string);
+ exit (0);
+ case 129:
+ usage ();
+ check_stdout ();
+ exit (0);
case 'L':
/* Handle up to three -L options. */
if (tag_count < 3)
@@ -293,10 +295,9 @@ main (argc, argv)
tag_strings[tag_count++] = optarg;
break;
}
- /* Falls through */
+ try_help ("Too many labels were given. The limit is 3.");
default:
- usage ();
- /* NOTREACHED */
+ try_help (0);
}
}
@@ -306,9 +307,11 @@ main (argc, argv)
if (incompat > 1 /* Ensure at most one of -AeExX3. */
|| finalwrite & merge /* -i -m would rewrite input file. */
- || (tag_count && ! flagging) /* -L requires one of -AEX. */
- || argc - optind != 3)
- usage ();
+ || (tag_count && ! flagging)) /* -L requires one of -AEX. */
+ try_help ("incompatible options");
+
+ if (argc - optind != 3)
+ try_help (argc - optind < 3 ? "missing operand" : "extra operand");
file = &argv[optind];
@@ -346,14 +349,24 @@ main (argc, argv)
for (i = 0; i < 3; i++)
if (strcmp (file[i], "-") != 0)
- if (stat (file[i], &statb) < 0)
- perror_with_exit (file[i]);
- else if (S_ISDIR(statb.st_mode))
- {
- fprintf (stderr, "%s: %s: Is a directory\n", argv0, file[i]);
- exit (2);
- }
+ {
+ if (stat (file[i], &statb) < 0)
+ perror_with_exit (file[i]);
+ else if (S_ISDIR(statb.st_mode))
+ {
+ fprintf (stderr, "%s: %s: Is a directory\n",
+ program_name, file[i]);
+ exit (2);
+ }
+ }
+#if !defined(SIGCHLD) && defined(SIGCLD)
+#define SIGCHLD SIGCLD
+#endif
+#ifdef SIGCHLD
+ /* System V fork+wait does not work if SIGCHLD is ignored. */
+ signal (SIGCHLD, SIG_DFL);
+#endif
commonname = file[rev_mapping[FILEC]];
thread1 = process_diff (file[rev_mapping[FILE1]], commonname, &last_block);
@@ -385,26 +398,54 @@ main (argc, argv)
conflicts_found = 0;
}
- if (ferror (stdout) || fclose (stdout) != 0)
- fatal ("write error");
+ check_stdout ();
exit (conflicts_found);
return conflicts_found;
}
+static void
+try_help (reason)
+ char const *reason;
+{
+ if (reason)
+ fprintf (stderr, "%s: %s\n", program_name, reason);
+ fprintf (stderr, "%s: Try `%s --help' for more information.\n",
+ program_name, program_name);
+ exit (2);
+}
+
+static void
+check_stdout ()
+{
+ if (ferror (stdout) || fclose (stdout) != 0)
+ fatal ("write error");
+}
+
/*
- * Explain, patiently and kindly, how to use this program. Then exit.
+ * Explain, patiently and kindly, how to use this program.
*/
static void
usage ()
{
- fprintf (stderr, "\
-Usage: %s [options] my-file older-file your-file\n\
-Options:\n\
- [-exAEX3v] [-i|-m] [-L label1 [-L label2 [-L label3]]] [--text] [--ed]\n\
- [--merge] [--show-all] [--show-overlap] [--overlap-only] [--easy-only]\n\
- [--label=label1 [--label=label2 [--label=label3]]] [--version]\n\
- Only one of [exAEX3] is allowed\n", argv0);
- exit (2);
+ printf ("Usage: %s [OPTION]... MYFILE OLDFILE YOURFILE\n\n", program_name);
+
+ printf ("%s", "\
+ -e --ed Output unmerged changes from OLDFILE to YOURFILE into MYFILE.\n\
+ -E --show-overlap Output unmerged changes, bracketing conflicts.\n\
+ -A --show-all Output all changes, bracketing conflicts.\n\
+ -x --overlap-only Output overlapping changes.\n\
+ -X Output overlapping changes, bracketing them.\n\
+ -3 --easy-only Output unmerged nonoverlapping changes.\n\n");
+ printf ("%s", "\
+ -m --merge Output merged file instead of ed script (default -A).\n\
+ -L LABEL --label=LABEL Use LABEL instead of file name.\n\
+ -i Append `w' and `q' commands to ed scripts.\n\
+ -a --text Treat all files as text.\n\
+ -T --initial-tab Make tabs line up by prepending a tab.\n\n");
+ printf ("%s", "\
+ -v --version Output version info.\n\
+ --help Output this help.\n\n");
+ printf ("If a FILE is `-', read standard input.\n");
}
/*
@@ -436,7 +477,7 @@ Options:\n\
* Create a diff3_block, reserving space as indicated by the ranges.
*
* 3) Copy all of the pointers for file2 in. At least for now,
- * do bcmp's between corresponding strings in the two diffs.
+ * do memcmp's between corresponding strings in the two diffs.
*
* 4) Copy all of the pointers for file0 and 1 in. Get what you
* need from file2 (when there isn't a diff block, it's
@@ -447,8 +488,8 @@ Options:\n\
* the common file in that diff) is the odd person out. If you used
* diff blocks from both sets, check to see if files 0 and 1 match:
*
- * Same number of lines? If so, do a set of bcmp's (if a
- * bcmp matches; copy the pointer over; it'll be easier later
+ * Same number of lines? If so, do a set of memcmp's (if a
+ * memcmp matches; copy the pointer over; it'll be easier later
* if you have to do any compares). If they match, 0 & 1 are
* the same. If not, all three different.
*
@@ -518,16 +559,11 @@ make_3way_diff (thread0, thread1)
struct diff3_block
*result,
*tmpblock,
- **result_end,
- *last_diff3;
+ **result_end;
+
+ struct diff3_block const *last_diff3;
- static struct diff3_block zero_diff3 = {
- ERROR,
- { {0, 0}, {0, 0}, {0, 0} },
- { (char **) 0, (char **) 0, (char **) 0 },
- { (int *) 0, (int *) 0, (int *) 0 },
- (struct diff3_block *) 0
- };
+ static struct diff3_block const zero_diff3;
/* Initialization */
result = 0;
@@ -539,8 +575,7 @@ make_3way_diff (thread0, thread1)
while (current[0] || current[1])
{
- using[0] = using[1] = last_using[0] = last_using[1] =
- (struct diff_block *) 0;
+ using[0] = using[1] = last_using[0] = last_using[1] = 0;
/* Setup low and high water threads, diffs, and marks. */
if (!current[0])
@@ -567,8 +602,7 @@ make_3way_diff (thread0, thread1)
= last_using[high_water_thread]
= high_water_diff;
current[high_water_thread] = high_water_diff->next;
- last_using[high_water_thread]->next
- = (struct diff_block *) 0;
+ last_using[high_water_thread]->next = 0;
/* And mark the other diff */
other_thread = high_water_thread ^ 0x1;
@@ -591,10 +625,8 @@ make_3way_diff (thread0, thread1)
/* Take it off the current list. Note that this following
code assumes that other_diff enters it equal to
current[high_water_thread ^ 0x1] */
- current[other_thread]
- = current[other_thread]->next;
- other_diff->next
- = (struct diff_block *) 0;
+ current[other_thread] = current[other_thread]->next;
+ other_diff->next = 0;
/* Set the high_water stuff
If this comparison is equal, then this is the last pass
@@ -660,7 +692,7 @@ using_to_diff3_block (using, last_using, low_thread, high_thread, last_diff3)
*using[2],
*last_using[2];
int low_thread, high_thread;
- struct diff3_block *last_diff3;
+ struct diff3_block const *last_diff3;
{
int low[2], high[2];
struct diff3_block *result;
@@ -780,21 +812,21 @@ using_to_diff3_block (using, last_using, low_thread, high_thread, last_diff3)
*/
static int
copy_stringlist (fromptrs, fromlengths, toptrs, tolengths, copynum)
- char *fromptrs[], *toptrs[];
- int *fromlengths, *tolengths;
+ char * const fromptrs[];
+ char *toptrs[];
+ size_t const fromlengths[];
+ size_t tolengths[];
int copynum;
{
- register char
- **f = fromptrs,
- **t = toptrs;
- register int
- *fl = fromlengths,
- *tl = tolengths;
+ register char * const *f = fromptrs;
+ register char **t = toptrs;
+ register size_t const *fl = fromlengths;
+ register size_t *tl = tolengths;
while (copynum--)
{
if (*t)
- { if (*fl != *tl || bcmp (*f, *t, *fl)) return 0; }
+ { if (*fl != *tl || memcmp (*f, *t, *fl)) return 0; }
else
{ *t = *f ; *tl = *fl; }
@@ -831,42 +863,42 @@ create_diff3_block (low0, high0, low1, high1, low2, high2)
if (numlines)
{
D_LINEARRAY (result, FILE0) = ALLOCATE (numlines, char *);
- D_LENARRAY (result, FILE0) = ALLOCATE (numlines, int);
+ D_LENARRAY (result, FILE0) = ALLOCATE (numlines, size_t);
bzero (D_LINEARRAY (result, FILE0), (numlines * sizeof (char *)));
- bzero (D_LENARRAY (result, FILE0), (numlines * sizeof (int)));
+ bzero (D_LENARRAY (result, FILE0), (numlines * sizeof (size_t)));
}
else
{
- D_LINEARRAY (result, FILE0) = (char **) 0;
- D_LENARRAY (result, FILE0) = (int *) 0;
+ D_LINEARRAY (result, FILE0) = 0;
+ D_LENARRAY (result, FILE0) = 0;
}
numlines = D_NUMLINES (result, FILE1);
if (numlines)
{
D_LINEARRAY (result, FILE1) = ALLOCATE (numlines, char *);
- D_LENARRAY (result, FILE1) = ALLOCATE (numlines, int);
+ D_LENARRAY (result, FILE1) = ALLOCATE (numlines, size_t);
bzero (D_LINEARRAY (result, FILE1), (numlines * sizeof (char *)));
- bzero (D_LENARRAY (result, FILE1), (numlines * sizeof (int)));
+ bzero (D_LENARRAY (result, FILE1), (numlines * sizeof (size_t)));
}
else
{
- D_LINEARRAY (result, FILE1) = (char **) 0;
- D_LENARRAY (result, FILE1) = (int *) 0;
+ D_LINEARRAY (result, FILE1) = 0;
+ D_LENARRAY (result, FILE1) = 0;
}
numlines = D_NUMLINES (result, FILE2);
if (numlines)
{
D_LINEARRAY (result, FILE2) = ALLOCATE (numlines, char *);
- D_LENARRAY (result, FILE2) = ALLOCATE (numlines, int);
+ D_LENARRAY (result, FILE2) = ALLOCATE (numlines, size_t);
bzero (D_LINEARRAY (result, FILE2), (numlines * sizeof (char *)));
- bzero (D_LENARRAY (result, FILE2), (numlines * sizeof (int)));
+ bzero (D_LENARRAY (result, FILE2), (numlines * sizeof (size_t)));
}
else
{
- D_LINEARRAY (result, FILE2) = (char **) 0;
- D_LENARRAY (result, FILE2) = (int *) 0;
+ D_LINEARRAY (result, FILE2) = 0;
+ D_LENARRAY (result, FILE2) = 0;
}
/* Return */
@@ -879,20 +911,20 @@ create_diff3_block (low0, high0, low1, high1, low2, high2)
*/
static int
compare_line_list (list1, lengths1, list2, lengths2, nl)
- char *list1[], *list2[];
- int *lengths1, *lengths2;
+ char * const list1[], * const list2[];
+ size_t const lengths1[], lengths2[];
int nl;
{
char
- **l1 = list1,
- **l2 = list2;
- int
+ * const *l1 = list1,
+ * const *l2 = list2;
+ size_t const
*lgths1 = lengths1,
*lgths2 = lengths2;
while (nl--)
if (!*l1 || !*l2 || *lgths1 != *lgths2++
- || bcmp (*l1++, *l2++, *lgths1++))
+ || memcmp (*l1++, *l2++, *lgths1++))
return 0;
return 1;
}
@@ -903,11 +935,9 @@ compare_line_list (list1, lengths1, list2, lengths2, nl)
extern char **environ;
-#define DIFF_CHUNK_SIZE 10000
-
static struct diff_block *
process_diff (filea, fileb, last_block)
- char *filea, *fileb;
+ char const *filea, *fileb;
struct diff_block **last_block;
{
char *diff_contents;
@@ -920,17 +950,18 @@ process_diff (filea, fileb, last_block)
diff_limit = read_diff (filea, fileb, &diff_contents);
scan_diff = diff_contents;
block_list_end = &block_list;
+ bptr = 0; /* Pacify `gcc -W'. */
while (scan_diff < diff_limit)
{
bptr = ALLOCATE (1, struct diff_block);
- bptr->lines[0] = bptr->lines[1] = (char **) 0;
- bptr->lengths[0] = bptr->lengths[1] = (int *) 0;
+ bptr->lines[0] = bptr->lines[1] = 0;
+ bptr->lengths[0] = bptr->lengths[1] = 0;
dt = process_diff_control (&scan_diff, bptr);
if (dt == ERROR || *scan_diff != '\n')
{
- fprintf (stderr, "%s: diff error: ", argv0);
+ fprintf (stderr, "%s: diff error: ", program_name);
do
{
putc (*scan_diff, stderr);
@@ -962,7 +993,7 @@ process_diff (filea, fileb, last_block)
{
int numlines = D_NUMLINES (bptr, 0);
bptr->lines[0] = ALLOCATE (numlines, char *);
- bptr->lengths[0] = ALLOCATE (numlines, int);
+ bptr->lengths[0] = ALLOCATE (numlines, size_t);
for (i = 0; i < numlines; i++)
scan_diff = scan_diff_line (scan_diff,
&(bptr->lines[0][i]),
@@ -985,7 +1016,7 @@ process_diff (filea, fileb, last_block)
{
int numlines = D_NUMLINES (bptr, 1);
bptr->lines[1] = ALLOCATE (numlines, char *);
- bptr->lengths[1] = ALLOCATE (numlines, int);
+ bptr->lengths[1] = ALLOCATE (numlines, size_t);
for (i = 0; i < numlines; i++)
scan_diff = scan_diff_line (scan_diff,
&(bptr->lines[1][i]),
@@ -1038,9 +1069,9 @@ process_diff_control (string, db)
#define SKIPWHITE(s) { while (*s == ' ' || *s == '\t') s++; }
#define READNUM(s, num) \
- { if (!isdigit (*s)) return ERROR; holdnum = 0; \
- do { holdnum = (*s++ - '0' + holdnum * 10); } \
- while (isdigit (*s)); (num) = holdnum; }
+ { unsigned char c = *s; if (!ISDIGIT (c)) return ERROR; holdnum = 0; \
+ do { holdnum = (c - '0' + holdnum * 10); } \
+ while (ISDIGIT (c = *++s)); (num) = holdnum; }
/* Read first set of digits */
SKIPWHITE (s);
@@ -1097,19 +1128,25 @@ process_diff_control (string, db)
static char *
read_diff (filea, fileb, output_placement)
- char *filea, *fileb;
+ char const *filea, *fileb;
char **output_placement;
{
- char *argv[7];
- char horizon_arg[256];
- char **ap;
- int fds[2];
char *diff_result;
- int current_chunk_size;
- int bytes;
- int total;
- int pid, w;
- int wstatus;
+ size_t bytes, current_chunk_size, total;
+ int fd, wstatus;
+ struct stat pipestat;
+
+ /* 302 / 1000 is log10(2.0) rounded up. Subtract 1 for the sign bit;
+ add 1 for integer division truncation; add 1 more for a minus sign. */
+#define INT_STRLEN_BOUND(type) ((sizeof(type)*CHAR_BIT - 1) * 302 / 1000 + 2)
+
+#if HAVE_FORK
+
+ char const *argv[7];
+ char horizon_arg[17 + INT_STRLEN_BOUND (int)];
+ char const **ap;
+ int fds[2];
+ pid_t pid;
ap = argv;
*ap++ = diff_program;
@@ -1120,25 +1157,25 @@ read_diff (filea, fileb, output_placement)
*ap++ = "--";
*ap++ = filea;
*ap++ = fileb;
- *ap = (char *) 0;
+ *ap = 0;
- if (pipe (fds) < 0)
- perror_with_exit ("pipe failed");
+ if (pipe (fds) != 0)
+ perror_with_exit ("pipe");
pid = vfork ();
if (pid == 0)
{
/* Child */
close (fds[0]);
- if (fds[1] != fileno (stdout))
+ if (fds[1] != STDOUT_FILENO)
{
- dup2 (fds[1], fileno (stdout));
+ dup2 (fds[1], STDOUT_FILENO);
close (fds[1]);
}
- execve (diff_program, argv, environ);
+ execve (diff_program, (char **) argv, environ);
/* Avoid stdio, because the parent process's buffers are inherited. */
- write (fileno (stderr), diff_program, strlen (diff_program));
- write (fileno (stderr), ": not found\n", 12);
+ write (STDERR_FILENO, diff_program, strlen (diff_program));
+ write (STDERR_FILENO, ": not found\n", 12);
_exit (2);
}
@@ -1146,16 +1183,50 @@ read_diff (filea, fileb, output_placement)
perror_with_exit ("fork failed");
close (fds[1]); /* Prevent erroneous lack of EOF */
- current_chunk_size = DIFF_CHUNK_SIZE;
- diff_result = (char *) xmalloc (current_chunk_size);
+ fd = fds[0];
+
+#else /* ! HAVE_FORK */
+
+ FILE *fpipe;
+ char *command = xmalloc (sizeof (diff_program) + 30 + INT_STRLEN_BOUND (int)
+ + 4 * (strlen (filea) + strlen (fileb)));
+ char *p;
+ sprintf (command, "%s -a --horizon-lines=%d -- ",
+ diff_program, horizon_lines);
+ p = command + strlen (command);
+ SYSTEM_QUOTE_ARG (p, filea);
+ *p++ = ' ';
+ SYSTEM_QUOTE_ARG (p, fileb);
+ *p = '\0';
+ fpipe = popen (command, "r");
+ if (!fpipe)
+ perror_with_exit (command);
+ free (command);
+ fd = fileno (fpipe);
+
+#endif /* ! HAVE_FORK */
+
+ current_chunk_size = 8 * 1024;
+ if (fstat (fd, &pipestat) == 0)
+ current_chunk_size = max (current_chunk_size, STAT_BLOCKSIZE (pipestat));
+
+ diff_result = xmalloc (current_chunk_size);
total = 0;
do {
- bytes = myread (fds[0],
+ bytes = myread (fd,
diff_result + total,
current_chunk_size - total);
total += bytes;
if (total == current_chunk_size)
- diff_result = (char *) xrealloc (diff_result, (current_chunk_size *= 2));
+ {
+ if (current_chunk_size < 2 * current_chunk_size)
+ current_chunk_size = 2 * current_chunk_size;
+ else if (current_chunk_size < (size_t) -1)
+ current_chunk_size = (size_t) -1;
+ else
+ fatal ("files are too large to fit into memory");
+ diff_result = xrealloc (diff_result, (current_chunk_size *= 2));
+ }
} while (bytes);
if (total != 0 && diff_result[total-1] != '\n')
@@ -1163,10 +1234,18 @@ read_diff (filea, fileb, output_placement)
*output_placement = diff_result;
- do
- if ((w = wait (&wstatus)) == -1)
- perror_with_exit ("wait failed");
- while (w != pid);
+#if ! HAVE_FORK
+
+ wstatus = pclose (fpipe);
+
+#else /* HAVE_FORK */
+
+ if (close (fd) != 0)
+ perror_with_exit ("pipe close");
+ if (waitpid (pid, &wstatus, 0) < 0)
+ perror_with_exit ("waitpid failed");
+
+#endif /* HAVE_FORK */
if (! (WIFEXITED (wstatus) && WEXITSTATUS (wstatus) < 2))
fatal ("subsidiary diff failed");
@@ -1183,15 +1262,15 @@ read_diff (filea, fileb, output_placement)
* are used as call-by-reference values.
*/
static char *
-scan_diff_line (scan_ptr, set_start, set_length, limit, firstchar)
+scan_diff_line (scan_ptr, set_start, set_length, limit, leadingchar)
char *scan_ptr, **set_start;
- int *set_length;
+ size_t *set_length;
char *limit;
- char firstchar;
+ int leadingchar;
{
char *line_ptr;
- if (!(scan_ptr[0] == (firstchar)
+ if (!(scan_ptr[0] == leadingchar
&& scan_ptr[1] == ' '))
fatal ("invalid diff format; incorrect leading line chars");
@@ -1208,7 +1287,7 @@ scan_diff_line (scan_ptr, set_start, set_length, limit, firstchar)
if (line_ptr < limit && *line_ptr == '\\')
{
if (edscript)
- fprintf (stderr, "%s:", argv0);
+ fprintf (stderr, "%s:", program_name);
else
--*set_length;
line_ptr++;
@@ -1238,16 +1317,17 @@ static void
output_diff3 (outputfile, diff, mapping, rev_mapping)
FILE *outputfile;
struct diff3_block *diff;
- int mapping[3], rev_mapping[3];
+ int const mapping[3], rev_mapping[3];
{
int i;
int oddoneout;
char *cp;
struct diff3_block *ptr;
int line;
- int length;
+ size_t length;
int dontprint;
static int skew_increment[3] = { 2, 3, 1 }; /* 0==>2==>1==>3 */
+ char const *line_prefix = tab_align_flag ? "\t" : " ";
for (ptr = diff; ptr; ptr = D_NEXT (ptr))
{
@@ -1299,15 +1379,20 @@ output_diff3 (outputfile, diff, mapping, rev_mapping)
if (i == dontprint) continue;
- for (line = 0; line < hight - lowt + 1; line++)
+ if (lowt <= hight)
{
- fprintf (outputfile, " ");
- cp = D_RELNUM (ptr, realfile, line);
- length = D_RELLEN (ptr, realfile, line);
- fwrite (cp, sizeof (char), length, outputfile);
+ line = 0;
+ do
+ {
+ fprintf (outputfile, line_prefix);
+ cp = D_RELNUM (ptr, realfile, line);
+ length = D_RELLEN (ptr, realfile, line);
+ fwrite (cp, sizeof (char), length, outputfile);
+ }
+ while (++line < hight - lowt + 1);
+ if (cp[length - 1] != '\n')
+ fprintf (outputfile, "\n\\ No newline at end of file\n");
}
- if (line != 0 && cp[length - 1] != '\n')
- fprintf (outputfile, "\n\\ No newline at end of file\n");
}
}
}
@@ -1388,8 +1473,8 @@ output_diff3_edscript (outputfile, diff, mapping, rev_mapping,
file0, file1, file2)
FILE *outputfile;
struct diff3_block *diff;
- int mapping[3], rev_mapping[3];
- char *file0, *file1, *file2;
+ int const mapping[3], rev_mapping[3];
+ char const *file0, *file1, *file2;
{
int leading_dot;
int conflicts_found = 0, conflict;
@@ -1515,8 +1600,8 @@ output_diff3_merge (infile, outputfile, diff, mapping, rev_mapping,
file0, file1, file2)
FILE *infile, *outputfile;
struct diff3_block *diff;
- int mapping[3], rev_mapping[3];
- char *file0, *file1, *file2;
+ int const mapping[3], rev_mapping[3];
+ char const *file0, *file1, *file2;
{
int c, i;
int conflicts_found = 0, conflict;
@@ -1532,7 +1617,7 @@ output_diff3_merge (infile, outputfile, diff, mapping, rev_mapping,
((enum diff_type)
(((int) DIFF_1ST)
+ rev_mapping[(int) b->correspond - (int) DIFF_1ST])));
- char *format_2nd = "<<<<<<< %s\n";
+ char const *format_2nd = "<<<<<<< %s\n";
/* If we aren't supposed to do this output block, skip it. */
switch (type)
@@ -1630,8 +1715,7 @@ reverse_diff3_blocklist (diff)
{
register struct diff3_block *tmp, *next, *prev;
- for (tmp = diff, prev = (struct diff3_block *) 0;
- tmp; tmp = next)
+ for (tmp = diff, prev = 0; tmp; tmp = next)
{
next = tmp->next;
tmp->next = prev;
@@ -1641,52 +1725,53 @@ reverse_diff3_blocklist (diff)
return prev;
}
-static int
+static size_t
myread (fd, ptr, size)
- int fd, size;
+ int fd;
char *ptr;
+ size_t size;
{
- int result = read (fd, ptr, size);
- if (result < 0)
+ size_t result = read (fd, ptr, size);
+ if (result == -1)
perror_with_exit ("read failed");
return result;
}
-VOID *
+static VOID *
xmalloc (size)
- unsigned size;
+ size_t size;
{
VOID *result = (VOID *) malloc (size ? size : 1);
if (!result)
- fatal ("virtual memory exhausted");
+ fatal ("memory exhausted");
return result;
}
static VOID *
xrealloc (ptr, size)
VOID *ptr;
- unsigned size;
+ size_t size;
{
VOID *result = (VOID *) realloc (ptr, size ? size : 1);
if (!result)
- fatal ("virtual memory exhausted");
+ fatal ("memory exhausted");
return result;
}
static void
fatal (string)
- char *string;
+ char const *string;
{
- fprintf (stderr, "%s: %s\n", argv0, string);
+ fprintf (stderr, "%s: %s\n", program_name, string);
exit (2);
}
static void
perror_with_exit (string)
- char *string;
+ char const *string;
{
int e = errno;
- fprintf (stderr, "%s: ", argv0);
+ fprintf (stderr, "%s: ", program_name);
errno = e;
perror (string);
exit (2);
OpenPOWER on IntegriCloud