1*18fd37a7SXin LI /* diff3 - compare three files line by line
2*18fd37a7SXin LI
3*18fd37a7SXin LI Copyright (C) 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1998, 2001,
4*18fd37a7SXin LI 2002, 2004 Free Software Foundation, Inc.
5*18fd37a7SXin LI
6*18fd37a7SXin LI This program is free software; you can redistribute it and/or modify
7*18fd37a7SXin LI it under the terms of the GNU General Public License as published by
8*18fd37a7SXin LI the Free Software Foundation; either version 2, or (at your option)
9*18fd37a7SXin LI any later version.
10*18fd37a7SXin LI
11*18fd37a7SXin LI This program is distributed in the hope that it will be useful,
12*18fd37a7SXin LI but WITHOUT ANY WARRANTY; without even the implied warranty of
13*18fd37a7SXin LI MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14*18fd37a7SXin LI See the GNU General Public License for more details.
15*18fd37a7SXin LI
16*18fd37a7SXin LI You should have received a copy of the GNU General Public License
17*18fd37a7SXin LI along with this program; see the file COPYING.
18*18fd37a7SXin LI If not, write to the Free Software Foundation,
19*18fd37a7SXin LI 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
20*18fd37a7SXin LI
21*18fd37a7SXin LI #include "system.h"
22*18fd37a7SXin LI #include "paths.h"
23*18fd37a7SXin LI
24*18fd37a7SXin LI #include <stdio.h>
25*18fd37a7SXin LI #include <unlocked-io.h>
26*18fd37a7SXin LI
27*18fd37a7SXin LI #include <c-stack.h>
28*18fd37a7SXin LI #include <cmpbuf.h>
29*18fd37a7SXin LI #include <error.h>
30*18fd37a7SXin LI #include <exitfail.h>
31*18fd37a7SXin LI #include <file-type.h>
32*18fd37a7SXin LI #include <getopt.h>
33*18fd37a7SXin LI #include <inttostr.h>
34*18fd37a7SXin LI #include <quotesys.h>
35*18fd37a7SXin LI #include <version-etc.h>
36*18fd37a7SXin LI #include <xalloc.h>
37*18fd37a7SXin LI
38*18fd37a7SXin LI /* Internal data structures and macros for the diff3 program; includes
39*18fd37a7SXin LI data structures for both diff3 diffs and normal diffs. */
40*18fd37a7SXin LI
41*18fd37a7SXin LI /* Different files within a three way diff. */
42*18fd37a7SXin LI #define FILE0 0
43*18fd37a7SXin LI #define FILE1 1
44*18fd37a7SXin LI #define FILE2 2
45*18fd37a7SXin LI
46*18fd37a7SXin LI /* A three way diff is built from two two-way diffs; the file which
47*18fd37a7SXin LI the two two-way diffs share is: */
48*18fd37a7SXin LI #define FILEC FILE2
49*18fd37a7SXin LI
50*18fd37a7SXin LI /* Different files within a two way diff.
51*18fd37a7SXin LI FC is the common file, FO the other file. */
52*18fd37a7SXin LI #define FO 0
53*18fd37a7SXin LI #define FC 1
54*18fd37a7SXin LI
55*18fd37a7SXin LI /* The ranges are indexed by */
56*18fd37a7SXin LI #define RANGE_START 0
57*18fd37a7SXin LI #define RANGE_END 1
58*18fd37a7SXin LI
59*18fd37a7SXin LI enum diff_type {
60*18fd37a7SXin LI ERROR, /* Should not be used */
61*18fd37a7SXin LI ADD, /* Two way diff add */
62*18fd37a7SXin LI CHANGE, /* Two way diff change */
63*18fd37a7SXin LI DELETE, /* Two way diff delete */
64*18fd37a7SXin LI DIFF_ALL, /* All three are different */
65*18fd37a7SXin LI DIFF_1ST, /* Only the first is different */
66*18fd37a7SXin LI DIFF_2ND, /* Only the second */
67*18fd37a7SXin LI DIFF_3RD /* Only the third */
68*18fd37a7SXin LI };
69*18fd37a7SXin LI
70*18fd37a7SXin LI /* Two way diff */
71*18fd37a7SXin LI struct diff_block {
72*18fd37a7SXin LI lin ranges[2][2]; /* Ranges are inclusive */
73*18fd37a7SXin LI char **lines[2]; /* The actual lines (may contain nulls) */
74*18fd37a7SXin LI size_t *lengths[2]; /* Line lengths (including newlines, if any) */
75*18fd37a7SXin LI struct diff_block *next;
76*18fd37a7SXin LI };
77*18fd37a7SXin LI
78*18fd37a7SXin LI /* Three way diff */
79*18fd37a7SXin LI
80*18fd37a7SXin LI struct diff3_block {
81*18fd37a7SXin LI enum diff_type correspond; /* Type of diff */
82*18fd37a7SXin LI lin ranges[3][2]; /* Ranges are inclusive */
83*18fd37a7SXin LI char **lines[3]; /* The actual lines (may contain nulls) */
84*18fd37a7SXin LI size_t *lengths[3]; /* Line lengths (including newlines, if any) */
85*18fd37a7SXin LI struct diff3_block *next;
86*18fd37a7SXin LI };
87*18fd37a7SXin LI
88*18fd37a7SXin LI /* Access the ranges on a diff block. */
89*18fd37a7SXin LI #define D_LOWLINE(diff, filenum) \
90*18fd37a7SXin LI ((diff)->ranges[filenum][RANGE_START])
91*18fd37a7SXin LI #define D_HIGHLINE(diff, filenum) \
92*18fd37a7SXin LI ((diff)->ranges[filenum][RANGE_END])
93*18fd37a7SXin LI #define D_NUMLINES(diff, filenum) \
94*18fd37a7SXin LI (D_HIGHLINE (diff, filenum) - D_LOWLINE (diff, filenum) + 1)
95*18fd37a7SXin LI
96*18fd37a7SXin LI /* Access the line numbers in a file in a diff by relative line
97*18fd37a7SXin LI numbers (i.e. line number within the diff itself). Note that these
98*18fd37a7SXin LI are lvalues and can be used for assignment. */
99*18fd37a7SXin LI #define D_RELNUM(diff, filenum, linenum) \
100*18fd37a7SXin LI ((diff)->lines[filenum][linenum])
101*18fd37a7SXin LI #define D_RELLEN(diff, filenum, linenum) \
102*18fd37a7SXin LI ((diff)->lengths[filenum][linenum])
103*18fd37a7SXin LI
104*18fd37a7SXin LI /* And get at them directly, when that should be necessary. */
105*18fd37a7SXin LI #define D_LINEARRAY(diff, filenum) \
106*18fd37a7SXin LI ((diff)->lines[filenum])
107*18fd37a7SXin LI #define D_LENARRAY(diff, filenum) \
108*18fd37a7SXin LI ((diff)->lengths[filenum])
109*18fd37a7SXin LI
110*18fd37a7SXin LI /* Next block. */
111*18fd37a7SXin LI #define D_NEXT(diff) ((diff)->next)
112*18fd37a7SXin LI
113*18fd37a7SXin LI /* Access the type of a diff3 block. */
114*18fd37a7SXin LI #define D3_TYPE(diff) ((diff)->correspond)
115*18fd37a7SXin LI
116*18fd37a7SXin LI /* Line mappings based on diffs. The first maps off the top of the
117*18fd37a7SXin LI diff, the second off of the bottom. */
118*18fd37a7SXin LI #define D_HIGH_MAPLINE(diff, fromfile, tofile, linenum) \
119*18fd37a7SXin LI ((linenum) \
120*18fd37a7SXin LI - D_HIGHLINE ((diff), (fromfile)) \
121*18fd37a7SXin LI + D_HIGHLINE ((diff), (tofile)))
122*18fd37a7SXin LI
123*18fd37a7SXin LI #define D_LOW_MAPLINE(diff, fromfile, tofile, linenum) \
124*18fd37a7SXin LI ((linenum) \
125*18fd37a7SXin LI - D_LOWLINE ((diff), (fromfile)) \
126*18fd37a7SXin LI + D_LOWLINE ((diff), (tofile)))
127*18fd37a7SXin LI
128*18fd37a7SXin LI /* Options variables for flags set on command line. */
129*18fd37a7SXin LI
130*18fd37a7SXin LI /* If nonzero, treat all files as text files, never as binary. */
131*18fd37a7SXin LI static bool text;
132*18fd37a7SXin LI
133*18fd37a7SXin LI /* Remove trailing carriage returns from input. */
134*18fd37a7SXin LI static bool strip_trailing_cr;
135*18fd37a7SXin LI
136*18fd37a7SXin LI /* If nonzero, write out an ed script instead of the standard diff3 format. */
137*18fd37a7SXin LI static bool edscript;
138*18fd37a7SXin LI
139*18fd37a7SXin LI /* If nonzero, in the case of overlapping diffs (type DIFF_ALL),
140*18fd37a7SXin LI preserve the lines which would normally be deleted from
141*18fd37a7SXin LI file 1 with a special flagging mechanism. */
142*18fd37a7SXin LI static bool flagging;
143*18fd37a7SXin LI
144*18fd37a7SXin LI /* Use a tab to align output lines (-T). */
145*18fd37a7SXin LI static bool initial_tab;
146*18fd37a7SXin LI
147*18fd37a7SXin LI /* If nonzero, do not output information for overlapping diffs. */
148*18fd37a7SXin LI static bool simple_only;
149*18fd37a7SXin LI
150*18fd37a7SXin LI /* If nonzero, do not output information for non-overlapping diffs. */
151*18fd37a7SXin LI static bool overlap_only;
152*18fd37a7SXin LI
153*18fd37a7SXin LI /* If nonzero, show information for DIFF_2ND diffs. */
154*18fd37a7SXin LI static bool show_2nd;
155*18fd37a7SXin LI
156*18fd37a7SXin LI /* If nonzero, include `:wq' at the end of the script
157*18fd37a7SXin LI to write out the file being edited. */
158*18fd37a7SXin LI static bool finalwrite;
159*18fd37a7SXin LI
160*18fd37a7SXin LI /* If nonzero, output a merged file. */
161*18fd37a7SXin LI static bool merge;
162*18fd37a7SXin LI
163*18fd37a7SXin LI char *program_name;
164*18fd37a7SXin LI
165*18fd37a7SXin LI static char *read_diff (char const *, char const *, char **);
166*18fd37a7SXin LI static char *scan_diff_line (char *, char **, size_t *, char *, char);
167*18fd37a7SXin LI static enum diff_type process_diff_control (char **, struct diff_block *);
168*18fd37a7SXin LI static bool compare_line_list (char * const[], size_t const[], char * const[], size_t const[], lin);
169*18fd37a7SXin LI static bool copy_stringlist (char * const[], size_t const[], char *[], size_t[], lin);
170*18fd37a7SXin LI static bool output_diff3_edscript (FILE *, struct diff3_block *, int const[3], int const[3], char const *, char const *, char const *);
171*18fd37a7SXin LI static bool output_diff3_merge (FILE *, FILE *, struct diff3_block *, int const[3], int const[3], char const *, char const *, char const *);
172*18fd37a7SXin LI static struct diff3_block *create_diff3_block (lin, lin, lin, lin, lin, lin);
173*18fd37a7SXin LI static struct diff3_block *make_3way_diff (struct diff_block *, struct diff_block *);
174*18fd37a7SXin LI static struct diff3_block *reverse_diff3_blocklist (struct diff3_block *);
175*18fd37a7SXin LI static struct diff3_block *using_to_diff3_block (struct diff_block *[2], struct diff_block *[2], int, int, struct diff3_block const *);
176*18fd37a7SXin LI static struct diff_block *process_diff (char const *, char const *, struct diff_block **);
177*18fd37a7SXin LI static void check_stdout (void);
178*18fd37a7SXin LI static void fatal (char const *) __attribute__((noreturn));
179*18fd37a7SXin LI static void output_diff3 (FILE *, struct diff3_block *, int const[3], int const[3]);
180*18fd37a7SXin LI static void perror_with_exit (char const *) __attribute__((noreturn));
181*18fd37a7SXin LI static void try_help (char const *, char const *) __attribute__((noreturn));
182*18fd37a7SXin LI static void usage (void);
183*18fd37a7SXin LI
184*18fd37a7SXin LI static char const *diff_program = DEFAULT_DIFF_PROGRAM;
185*18fd37a7SXin LI
186*18fd37a7SXin LI /* Values for long options that do not have single-letter equivalents. */
187*18fd37a7SXin LI enum
188*18fd37a7SXin LI {
189*18fd37a7SXin LI DIFF_PROGRAM_OPTION = CHAR_MAX + 1,
190*18fd37a7SXin LI HELP_OPTION,
191*18fd37a7SXin LI STRIP_TRAILING_CR_OPTION
192*18fd37a7SXin LI };
193*18fd37a7SXin LI
194*18fd37a7SXin LI static struct option const longopts[] =
195*18fd37a7SXin LI {
196*18fd37a7SXin LI {"diff-program", 1, 0, DIFF_PROGRAM_OPTION},
197*18fd37a7SXin LI {"easy-only", 0, 0, '3'},
198*18fd37a7SXin LI {"ed", 0, 0, 'e'},
199*18fd37a7SXin LI {"help", 0, 0, HELP_OPTION},
200*18fd37a7SXin LI {"initial-tab", 0, 0, 'T'},
201*18fd37a7SXin LI {"label", 1, 0, 'L'},
202*18fd37a7SXin LI {"merge", 0, 0, 'm'},
203*18fd37a7SXin LI {"overlap-only", 0, 0, 'x'},
204*18fd37a7SXin LI {"show-all", 0, 0, 'A'},
205*18fd37a7SXin LI {"show-overlap", 0, 0, 'E'},
206*18fd37a7SXin LI {"strip-trailing-cr", 0, 0, STRIP_TRAILING_CR_OPTION},
207*18fd37a7SXin LI {"text", 0, 0, 'a'},
208*18fd37a7SXin LI {"version", 0, 0, 'v'},
209*18fd37a7SXin LI {0, 0, 0, 0}
210*18fd37a7SXin LI };
211*18fd37a7SXin LI
212*18fd37a7SXin LI int
main(int argc,char ** argv)213*18fd37a7SXin LI main (int argc, char **argv)
214*18fd37a7SXin LI {
215*18fd37a7SXin LI int c, i;
216*18fd37a7SXin LI int common;
217*18fd37a7SXin LI int mapping[3];
218*18fd37a7SXin LI int rev_mapping[3];
219*18fd37a7SXin LI int incompat = 0;
220*18fd37a7SXin LI bool conflicts_found;
221*18fd37a7SXin LI struct diff_block *thread0, *thread1, *last_block;
222*18fd37a7SXin LI struct diff3_block *diff3;
223*18fd37a7SXin LI int tag_count = 0;
224*18fd37a7SXin LI char *tag_strings[3];
225*18fd37a7SXin LI char *commonname;
226*18fd37a7SXin LI char **file;
227*18fd37a7SXin LI struct stat statb;
228*18fd37a7SXin LI
229*18fd37a7SXin LI exit_failure = 2;
230*18fd37a7SXin LI initialize_main (&argc, &argv);
231*18fd37a7SXin LI program_name = argv[0];
232*18fd37a7SXin LI setlocale (LC_ALL, "");
233*18fd37a7SXin LI bindtextdomain (PACKAGE, LOCALEDIR);
234*18fd37a7SXin LI textdomain (PACKAGE);
235*18fd37a7SXin LI c_stack_action (0);
236*18fd37a7SXin LI
237*18fd37a7SXin LI while ((c = getopt_long (argc, argv, "aeimvx3AEL:TX", longopts, 0)) != -1)
238*18fd37a7SXin LI {
239*18fd37a7SXin LI switch (c)
240*18fd37a7SXin LI {
241*18fd37a7SXin LI case 'a':
242*18fd37a7SXin LI text = true;
243*18fd37a7SXin LI break;
244*18fd37a7SXin LI case 'A':
245*18fd37a7SXin LI show_2nd = true;
246*18fd37a7SXin LI flagging = true;
247*18fd37a7SXin LI incompat++;
248*18fd37a7SXin LI break;
249*18fd37a7SXin LI case 'x':
250*18fd37a7SXin LI overlap_only = true;
251*18fd37a7SXin LI incompat++;
252*18fd37a7SXin LI break;
253*18fd37a7SXin LI case '3':
254*18fd37a7SXin LI simple_only = true;
255*18fd37a7SXin LI incompat++;
256*18fd37a7SXin LI break;
257*18fd37a7SXin LI case 'i':
258*18fd37a7SXin LI finalwrite = true;
259*18fd37a7SXin LI break;
260*18fd37a7SXin LI case 'm':
261*18fd37a7SXin LI merge = true;
262*18fd37a7SXin LI break;
263*18fd37a7SXin LI case 'X':
264*18fd37a7SXin LI overlap_only = true;
265*18fd37a7SXin LI /* Fall through. */
266*18fd37a7SXin LI case 'E':
267*18fd37a7SXin LI flagging = true;
268*18fd37a7SXin LI /* Fall through. */
269*18fd37a7SXin LI case 'e':
270*18fd37a7SXin LI incompat++;
271*18fd37a7SXin LI break;
272*18fd37a7SXin LI case 'T':
273*18fd37a7SXin LI initial_tab = true;
274*18fd37a7SXin LI break;
275*18fd37a7SXin LI case STRIP_TRAILING_CR_OPTION:
276*18fd37a7SXin LI strip_trailing_cr = true;
277*18fd37a7SXin LI break;
278*18fd37a7SXin LI case 'v':
279*18fd37a7SXin LI version_etc (stdout, "diff3", PACKAGE_NAME, PACKAGE_VERSION,
280*18fd37a7SXin LI "Randy Smith", (char *) 0);
281*18fd37a7SXin LI check_stdout ();
282*18fd37a7SXin LI return EXIT_SUCCESS;
283*18fd37a7SXin LI case DIFF_PROGRAM_OPTION:
284*18fd37a7SXin LI diff_program = optarg;
285*18fd37a7SXin LI break;
286*18fd37a7SXin LI case HELP_OPTION:
287*18fd37a7SXin LI usage ();
288*18fd37a7SXin LI check_stdout ();
289*18fd37a7SXin LI return EXIT_SUCCESS;
290*18fd37a7SXin LI case 'L':
291*18fd37a7SXin LI /* Handle up to three -L options. */
292*18fd37a7SXin LI if (tag_count < 3)
293*18fd37a7SXin LI {
294*18fd37a7SXin LI tag_strings[tag_count++] = optarg;
295*18fd37a7SXin LI break;
296*18fd37a7SXin LI }
297*18fd37a7SXin LI try_help ("too many file label options", 0);
298*18fd37a7SXin LI default:
299*18fd37a7SXin LI try_help (0, 0);
300*18fd37a7SXin LI }
301*18fd37a7SXin LI }
302*18fd37a7SXin LI
303*18fd37a7SXin LI edscript = incompat & ~merge; /* -AeExX3 without -m implies ed script. */
304*18fd37a7SXin LI show_2nd |= ~incompat & merge; /* -m without -AeExX3 implies -A. */
305*18fd37a7SXin LI flagging |= ~incompat & merge;
306*18fd37a7SXin LI
307*18fd37a7SXin LI if (incompat > 1 /* Ensure at most one of -AeExX3. */
308*18fd37a7SXin LI || finalwrite & merge /* -i -m would rewrite input file. */
309*18fd37a7SXin LI || (tag_count && ! flagging)) /* -L requires one of -AEX. */
310*18fd37a7SXin LI try_help ("incompatible options", 0);
311*18fd37a7SXin LI
312*18fd37a7SXin LI if (argc - optind != 3)
313*18fd37a7SXin LI {
314*18fd37a7SXin LI if (argc - optind < 3)
315*18fd37a7SXin LI try_help ("missing operand after `%s'", argv[argc - 1]);
316*18fd37a7SXin LI else
317*18fd37a7SXin LI try_help ("extra operand `%s'", argv[optind + 3]);
318*18fd37a7SXin LI }
319*18fd37a7SXin LI
320*18fd37a7SXin LI file = &argv[optind];
321*18fd37a7SXin LI
322*18fd37a7SXin LI for (i = tag_count; i < 3; i++)
323*18fd37a7SXin LI tag_strings[i] = file[i];
324*18fd37a7SXin LI
325*18fd37a7SXin LI /* Always compare file1 to file2, even if file2 is "-".
326*18fd37a7SXin LI This is needed for -mAeExX3. Using the file0 as
327*18fd37a7SXin LI the common file would produce wrong results, because if the
328*18fd37a7SXin LI file0-file1 diffs didn't line up with the file0-file2 diffs
329*18fd37a7SXin LI (which is entirely possible since we don't use diff's -n option),
330*18fd37a7SXin LI diff3 might report phantom changes from file1 to file2.
331*18fd37a7SXin LI
332*18fd37a7SXin LI Also, try to compare file0 to file1, because this is where
333*18fd37a7SXin LI changes are expected to come from. Diffing between these pairs
334*18fd37a7SXin LI of files is more likely to avoid phantom changes from file0 to file1.
335*18fd37a7SXin LI
336*18fd37a7SXin LI Historically, the default common file was file2, so some older
337*18fd37a7SXin LI applications (e.g. Emacs ediff) used file2 as the ancestor. So,
338*18fd37a7SXin LI for compatibility, if this is a 3-way diff (not a merge or
339*18fd37a7SXin LI edscript), prefer file2 as the common file. */
340*18fd37a7SXin LI
341*18fd37a7SXin LI common = 2 - (edscript | merge);
342*18fd37a7SXin LI
343*18fd37a7SXin LI if (strcmp (file[common], "-") == 0)
344*18fd37a7SXin LI {
345*18fd37a7SXin LI /* Sigh. We've got standard input as the common file. We can't
346*18fd37a7SXin LI call diff twice on stdin. Use the other arg as the common
347*18fd37a7SXin LI file instead. */
348*18fd37a7SXin LI common = 3 - common;
349*18fd37a7SXin LI if (strcmp (file[0], "-") == 0 || strcmp (file[common], "-") == 0)
350*18fd37a7SXin LI fatal ("`-' specified for more than one input file");
351*18fd37a7SXin LI }
352*18fd37a7SXin LI
353*18fd37a7SXin LI mapping[0] = 0;
354*18fd37a7SXin LI mapping[1] = 3 - common;
355*18fd37a7SXin LI mapping[2] = common;
356*18fd37a7SXin LI
357*18fd37a7SXin LI for (i = 0; i < 3; i++)
358*18fd37a7SXin LI rev_mapping[mapping[i]] = i;
359*18fd37a7SXin LI
360*18fd37a7SXin LI for (i = 0; i < 3; i++)
361*18fd37a7SXin LI if (strcmp (file[i], "-") != 0)
362*18fd37a7SXin LI {
363*18fd37a7SXin LI if (stat (file[i], &statb) < 0)
364*18fd37a7SXin LI perror_with_exit (file[i]);
365*18fd37a7SXin LI else if (S_ISDIR (statb.st_mode))
366*18fd37a7SXin LI error (EXIT_TROUBLE, EISDIR, "%s", file[i]);
367*18fd37a7SXin LI }
368*18fd37a7SXin LI
369*18fd37a7SXin LI #ifdef SIGCHLD
370*18fd37a7SXin LI /* System V fork+wait does not work if SIGCHLD is ignored. */
371*18fd37a7SXin LI signal (SIGCHLD, SIG_DFL);
372*18fd37a7SXin LI #endif
373*18fd37a7SXin LI
374*18fd37a7SXin LI /* Invoke diff twice on two pairs of input files, combine the two
375*18fd37a7SXin LI diffs, and output them. */
376*18fd37a7SXin LI
377*18fd37a7SXin LI commonname = file[rev_mapping[FILEC]];
378*18fd37a7SXin LI thread1 = process_diff (file[rev_mapping[FILE1]], commonname, &last_block);
379*18fd37a7SXin LI thread0 = process_diff (file[rev_mapping[FILE0]], commonname, &last_block);
380*18fd37a7SXin LI diff3 = make_3way_diff (thread0, thread1);
381*18fd37a7SXin LI if (edscript)
382*18fd37a7SXin LI conflicts_found
383*18fd37a7SXin LI = output_diff3_edscript (stdout, diff3, mapping, rev_mapping,
384*18fd37a7SXin LI tag_strings[0], tag_strings[1], tag_strings[2]);
385*18fd37a7SXin LI else if (merge)
386*18fd37a7SXin LI {
387*18fd37a7SXin LI if (! freopen (file[rev_mapping[FILE0]], "r", stdin))
388*18fd37a7SXin LI perror_with_exit (file[rev_mapping[FILE0]]);
389*18fd37a7SXin LI conflicts_found
390*18fd37a7SXin LI = output_diff3_merge (stdin, stdout, diff3, mapping, rev_mapping,
391*18fd37a7SXin LI tag_strings[0], tag_strings[1], tag_strings[2]);
392*18fd37a7SXin LI if (ferror (stdin))
393*18fd37a7SXin LI fatal ("read failed");
394*18fd37a7SXin LI }
395*18fd37a7SXin LI else
396*18fd37a7SXin LI {
397*18fd37a7SXin LI output_diff3 (stdout, diff3, mapping, rev_mapping);
398*18fd37a7SXin LI conflicts_found = false;
399*18fd37a7SXin LI }
400*18fd37a7SXin LI
401*18fd37a7SXin LI check_stdout ();
402*18fd37a7SXin LI exit (conflicts_found);
403*18fd37a7SXin LI return conflicts_found;
404*18fd37a7SXin LI }
405*18fd37a7SXin LI
406*18fd37a7SXin LI static void
try_help(char const * reason_msgid,char const * operand)407*18fd37a7SXin LI try_help (char const *reason_msgid, char const *operand)
408*18fd37a7SXin LI {
409*18fd37a7SXin LI if (reason_msgid)
410*18fd37a7SXin LI error (0, 0, _(reason_msgid), operand);
411*18fd37a7SXin LI error (EXIT_TROUBLE, 0,
412*18fd37a7SXin LI _("Try `%s --help' for more information."), program_name);
413*18fd37a7SXin LI abort ();
414*18fd37a7SXin LI }
415*18fd37a7SXin LI
416*18fd37a7SXin LI static void
check_stdout(void)417*18fd37a7SXin LI check_stdout (void)
418*18fd37a7SXin LI {
419*18fd37a7SXin LI if (ferror (stdout))
420*18fd37a7SXin LI fatal ("write failed");
421*18fd37a7SXin LI else if (fclose (stdout) != 0)
422*18fd37a7SXin LI perror_with_exit (_("standard output"));
423*18fd37a7SXin LI }
424*18fd37a7SXin LI
425*18fd37a7SXin LI static char const * const option_help_msgid[] = {
426*18fd37a7SXin LI N_("-e --ed Output unmerged changes from OLDFILE to YOURFILE into MYFILE."),
427*18fd37a7SXin LI N_("-E --show-overlap Output unmerged changes, bracketing conflicts."),
428*18fd37a7SXin LI N_("-A --show-all Output all changes, bracketing conflicts."),
429*18fd37a7SXin LI N_("-x --overlap-only Output overlapping changes."),
430*18fd37a7SXin LI N_("-X Output overlapping changes, bracketing them."),
431*18fd37a7SXin LI N_("-3 --easy-only Output unmerged nonoverlapping changes."),
432*18fd37a7SXin LI "",
433*18fd37a7SXin LI N_("-m --merge Output merged file instead of ed script (default -A)."),
434*18fd37a7SXin LI N_("-L LABEL --label=LABEL Use LABEL instead of file name."),
435*18fd37a7SXin LI N_("-i Append `w' and `q' commands to ed scripts."),
436*18fd37a7SXin LI N_("-a --text Treat all files as text."),
437*18fd37a7SXin LI N_("--strip-trailing-cr Strip trailing carriage return on input."),
438*18fd37a7SXin LI N_("-T --initial-tab Make tabs line up by prepending a tab."),
439*18fd37a7SXin LI N_("--diff-program=PROGRAM Use PROGRAM to compare files."),
440*18fd37a7SXin LI "",
441*18fd37a7SXin LI N_("-v --version Output version info."),
442*18fd37a7SXin LI N_("--help Output this help."),
443*18fd37a7SXin LI 0
444*18fd37a7SXin LI };
445*18fd37a7SXin LI
446*18fd37a7SXin LI static void
usage(void)447*18fd37a7SXin LI usage (void)
448*18fd37a7SXin LI {
449*18fd37a7SXin LI char const * const *p;
450*18fd37a7SXin LI
451*18fd37a7SXin LI printf (_("Usage: %s [OPTION]... MYFILE OLDFILE YOURFILE\n"),
452*18fd37a7SXin LI program_name);
453*18fd37a7SXin LI printf ("%s\n\n", _("Compare three files line by line."));
454*18fd37a7SXin LI for (p = option_help_msgid; *p; p++)
455*18fd37a7SXin LI if (**p)
456*18fd37a7SXin LI printf (" %s\n", _(*p));
457*18fd37a7SXin LI else
458*18fd37a7SXin LI putchar ('\n');
459*18fd37a7SXin LI printf ("\n%s\n%s\n\n%s\n",
460*18fd37a7SXin LI _("If a FILE is `-', read standard input."),
461*18fd37a7SXin LI _("Exit status is 0 if successful, 1 if conflicts, 2 if trouble."),
462*18fd37a7SXin LI _("Report bugs to <[email protected]>."));
463*18fd37a7SXin LI }
464*18fd37a7SXin LI
465*18fd37a7SXin LI /* Combine the two diffs together into one.
466*18fd37a7SXin LI Here is the algorithm:
467*18fd37a7SXin LI
468*18fd37a7SXin LI File2 is shared in common between the two diffs.
469*18fd37a7SXin LI Diff02 is the diff between 0 and 2.
470*18fd37a7SXin LI Diff12 is the diff between 1 and 2.
471*18fd37a7SXin LI
472*18fd37a7SXin LI 1) Find the range for the first block in File2.
473*18fd37a7SXin LI a) Take the lowest of the two ranges (in File2) in the two
474*18fd37a7SXin LI current blocks (one from each diff) as being the low
475*18fd37a7SXin LI water mark. Assign the upper end of this block as
476*18fd37a7SXin LI being the high water mark and move the current block up
477*18fd37a7SXin LI one. Mark the block just moved over as to be used.
478*18fd37a7SXin LI b) Check the next block in the diff that the high water
479*18fd37a7SXin LI mark is *not* from.
480*18fd37a7SXin LI
481*18fd37a7SXin LI *If* the high water mark is above
482*18fd37a7SXin LI the low end of the range in that block,
483*18fd37a7SXin LI
484*18fd37a7SXin LI mark that block as to be used and move the current
485*18fd37a7SXin LI block up. Set the high water mark to the max of
486*18fd37a7SXin LI the high end of this block and the current. Repeat b.
487*18fd37a7SXin LI
488*18fd37a7SXin LI 2) Find the corresponding ranges in File0 (from the blocks
489*18fd37a7SXin LI in diff02; line per line outside of diffs) and in File1.
490*18fd37a7SXin LI Create a diff3_block, reserving space as indicated by the ranges.
491*18fd37a7SXin LI
492*18fd37a7SXin LI 3) Copy all of the pointers for file2 in. At least for now,
493*18fd37a7SXin LI do memcmp's between corresponding strings in the two diffs.
494*18fd37a7SXin LI
495*18fd37a7SXin LI 4) Copy all of the pointers for file0 and 1 in. Get what is
496*18fd37a7SXin LI needed from file2 (when there isn't a diff block, it's
497*18fd37a7SXin LI identical to file2 within the range between diff blocks).
498*18fd37a7SXin LI
499*18fd37a7SXin LI 5) If the diff blocks used came from only one of the two
500*18fd37a7SXin LI strings of diffs, then that file (i.e. the one other than
501*18fd37a7SXin LI the common file in that diff) is the odd person out. If
502*18fd37a7SXin LI diff blocks are used from both sets, check to see if files
503*18fd37a7SXin LI 0 and 1 match:
504*18fd37a7SXin LI
505*18fd37a7SXin LI Same number of lines? If so, do a set of memcmp's (if
506*18fd37a7SXin LI a memcmp matches; copy the pointer over; it'll be easier
507*18fd37a7SXin LI later during comparisons). If they match, 0 & 1 are the
508*18fd37a7SXin LI same. If not, all three different.
509*18fd37a7SXin LI
510*18fd37a7SXin LI Then do it again, until the blocks are exhausted. */
511*18fd37a7SXin LI
512*18fd37a7SXin LI
513*18fd37a7SXin LI /* Make a three way diff (chain of diff3_block's) from two two way
514*18fd37a7SXin LI diffs (chains of diff_block's). Assume that each of the two diffs
515*18fd37a7SXin LI passed are onto the same file (i.e. that each of the diffs were
516*18fd37a7SXin LI made "to" the same file). Return a three way diff pointer with
517*18fd37a7SXin LI numbering FILE0 = the other file in diff02, FILE1 = the other file
518*18fd37a7SXin LI in diff12, and FILEC = the common file. */
519*18fd37a7SXin LI
520*18fd37a7SXin LI static struct diff3_block *
make_3way_diff(struct diff_block * thread0,struct diff_block * thread1)521*18fd37a7SXin LI make_3way_diff (struct diff_block *thread0, struct diff_block *thread1)
522*18fd37a7SXin LI {
523*18fd37a7SXin LI /* Work on the two diffs passed to it as threads. Thread number 0
524*18fd37a7SXin LI is diff02, thread number 1 is diff12. USING is the base of the
525*18fd37a7SXin LI list of blocks to be used to construct each block of the three
526*18fd37a7SXin LI way diff; if no blocks from a particular thread are to be used,
527*18fd37a7SXin LI that element of USING is 0. LAST_USING contains the last
528*18fd37a7SXin LI elements on each of the using lists.
529*18fd37a7SXin LI
530*18fd37a7SXin LI HIGH_WATER_MARK is the highest line number in the common file
531*18fd37a7SXin LI described in any of the diffs in either of the USING lists.
532*18fd37a7SXin LI HIGH_WATER_THREAD names the thread. Similarly BASE_WATER_MARK
533*18fd37a7SXin LI and BASE_WATER_THREAD describe the lowest line number in the
534*18fd37a7SXin LI common file described in any of the diffs in either of the USING
535*18fd37a7SXin LI lists. HIGH_WATER_DIFF is the diff from which the
536*18fd37a7SXin LI HIGH_WATER_MARK was taken.
537*18fd37a7SXin LI
538*18fd37a7SXin LI HIGH_WATER_DIFF should always be equal to
539*18fd37a7SXin LI LAST_USING[HIGH_WATER_THREAD]. OTHER_DIFF is the next diff to
540*18fd37a7SXin LI check for higher water, and should always be equal to
541*18fd37a7SXin LI CURRENT[HIGH_WATER_THREAD ^ 1]. OTHER_THREAD is the thread in
542*18fd37a7SXin LI which the OTHER_DIFF is, and hence should always be equal to
543*18fd37a7SXin LI HIGH_WATER_THREAD ^ 1.
544*18fd37a7SXin LI
545*18fd37a7SXin LI LAST_DIFF is the last diff block produced by this routine, for
546*18fd37a7SXin LI line correspondence purposes between that diff and the one
547*18fd37a7SXin LI currently being worked on. It is ZERO_DIFF before any blocks
548*18fd37a7SXin LI have been created. */
549*18fd37a7SXin LI
550*18fd37a7SXin LI struct diff_block *using[2];
551*18fd37a7SXin LI struct diff_block *last_using[2];
552*18fd37a7SXin LI struct diff_block *current[2];
553*18fd37a7SXin LI
554*18fd37a7SXin LI lin high_water_mark;
555*18fd37a7SXin LI
556*18fd37a7SXin LI int high_water_thread;
557*18fd37a7SXin LI int base_water_thread;
558*18fd37a7SXin LI int other_thread;
559*18fd37a7SXin LI
560*18fd37a7SXin LI struct diff_block *high_water_diff;
561*18fd37a7SXin LI struct diff_block *other_diff;
562*18fd37a7SXin LI
563*18fd37a7SXin LI struct diff3_block *result;
564*18fd37a7SXin LI struct diff3_block *tmpblock;
565*18fd37a7SXin LI struct diff3_block **result_end;
566*18fd37a7SXin LI
567*18fd37a7SXin LI struct diff3_block const *last_diff3;
568*18fd37a7SXin LI
569*18fd37a7SXin LI static struct diff3_block const zero_diff3;
570*18fd37a7SXin LI
571*18fd37a7SXin LI /* Initialization */
572*18fd37a7SXin LI result = 0;
573*18fd37a7SXin LI result_end = &result;
574*18fd37a7SXin LI current[0] = thread0; current[1] = thread1;
575*18fd37a7SXin LI last_diff3 = &zero_diff3;
576*18fd37a7SXin LI
577*18fd37a7SXin LI /* Sniff up the threads until we reach the end */
578*18fd37a7SXin LI
579*18fd37a7SXin LI while (current[0] || current[1])
580*18fd37a7SXin LI {
581*18fd37a7SXin LI using[0] = using[1] = last_using[0] = last_using[1] = 0;
582*18fd37a7SXin LI
583*18fd37a7SXin LI /* Setup low and high water threads, diffs, and marks. */
584*18fd37a7SXin LI if (!current[0])
585*18fd37a7SXin LI base_water_thread = 1;
586*18fd37a7SXin LI else if (!current[1])
587*18fd37a7SXin LI base_water_thread = 0;
588*18fd37a7SXin LI else
589*18fd37a7SXin LI base_water_thread =
590*18fd37a7SXin LI (D_LOWLINE (current[0], FC) > D_LOWLINE (current[1], FC));
591*18fd37a7SXin LI
592*18fd37a7SXin LI high_water_thread = base_water_thread;
593*18fd37a7SXin LI
594*18fd37a7SXin LI high_water_diff = current[high_water_thread];
595*18fd37a7SXin LI
596*18fd37a7SXin LI high_water_mark = D_HIGHLINE (high_water_diff, FC);
597*18fd37a7SXin LI
598*18fd37a7SXin LI /* Make the diff you just got info from into the using class */
599*18fd37a7SXin LI using[high_water_thread]
600*18fd37a7SXin LI = last_using[high_water_thread]
601*18fd37a7SXin LI = high_water_diff;
602*18fd37a7SXin LI current[high_water_thread] = high_water_diff->next;
603*18fd37a7SXin LI last_using[high_water_thread]->next = 0;
604*18fd37a7SXin LI
605*18fd37a7SXin LI /* And mark the other diff */
606*18fd37a7SXin LI other_thread = high_water_thread ^ 0x1;
607*18fd37a7SXin LI other_diff = current[other_thread];
608*18fd37a7SXin LI
609*18fd37a7SXin LI /* Shuffle up the ladder, checking the other diff to see if it
610*18fd37a7SXin LI needs to be incorporated. */
611*18fd37a7SXin LI while (other_diff
612*18fd37a7SXin LI && D_LOWLINE (other_diff, FC) <= high_water_mark + 1)
613*18fd37a7SXin LI {
614*18fd37a7SXin LI
615*18fd37a7SXin LI /* Incorporate this diff into the using list. Note that
616*18fd37a7SXin LI this doesn't take it off the current list */
617*18fd37a7SXin LI if (using[other_thread])
618*18fd37a7SXin LI last_using[other_thread]->next = other_diff;
619*18fd37a7SXin LI else
620*18fd37a7SXin LI using[other_thread] = other_diff;
621*18fd37a7SXin LI last_using[other_thread] = other_diff;
622*18fd37a7SXin LI
623*18fd37a7SXin LI /* Take it off the current list. Note that this following
624*18fd37a7SXin LI code assumes that other_diff enters it equal to
625*18fd37a7SXin LI current[high_water_thread ^ 0x1] */
626*18fd37a7SXin LI current[other_thread] = current[other_thread]->next;
627*18fd37a7SXin LI other_diff->next = 0;
628*18fd37a7SXin LI
629*18fd37a7SXin LI /* Set the high_water stuff
630*18fd37a7SXin LI If this comparison is equal, then this is the last pass
631*18fd37a7SXin LI through this loop; since diff blocks within a given
632*18fd37a7SXin LI thread cannot overlap, the high_water_mark will be
633*18fd37a7SXin LI *below* the range_start of either of the next diffs. */
634*18fd37a7SXin LI
635*18fd37a7SXin LI if (high_water_mark < D_HIGHLINE (other_diff, FC))
636*18fd37a7SXin LI {
637*18fd37a7SXin LI high_water_thread ^= 1;
638*18fd37a7SXin LI high_water_diff = other_diff;
639*18fd37a7SXin LI high_water_mark = D_HIGHLINE (other_diff, FC);
640*18fd37a7SXin LI }
641*18fd37a7SXin LI
642*18fd37a7SXin LI /* Set the other diff */
643*18fd37a7SXin LI other_thread = high_water_thread ^ 0x1;
644*18fd37a7SXin LI other_diff = current[other_thread];
645*18fd37a7SXin LI }
646*18fd37a7SXin LI
647*18fd37a7SXin LI /* The using lists contain a list of all of the blocks to be
648*18fd37a7SXin LI included in this diff3_block. Create it. */
649*18fd37a7SXin LI
650*18fd37a7SXin LI tmpblock = using_to_diff3_block (using, last_using,
651*18fd37a7SXin LI base_water_thread, high_water_thread,
652*18fd37a7SXin LI last_diff3);
653*18fd37a7SXin LI
654*18fd37a7SXin LI if (!tmpblock)
655*18fd37a7SXin LI fatal ("internal error: screwup in format of diff blocks");
656*18fd37a7SXin LI
657*18fd37a7SXin LI /* Put it on the list. */
658*18fd37a7SXin LI *result_end = tmpblock;
659*18fd37a7SXin LI result_end = &tmpblock->next;
660*18fd37a7SXin LI
661*18fd37a7SXin LI /* Set up corresponding lines correctly. */
662*18fd37a7SXin LI last_diff3 = tmpblock;
663*18fd37a7SXin LI }
664*18fd37a7SXin LI return result;
665*18fd37a7SXin LI }
666*18fd37a7SXin LI
667*18fd37a7SXin LI /* Take two lists of blocks (from two separate diff threads) and put
668*18fd37a7SXin LI them together into one diff3 block. Return a pointer to this diff3
669*18fd37a7SXin LI block or 0 for failure.
670*18fd37a7SXin LI
671*18fd37a7SXin LI All arguments besides using are for the convenience of the routine;
672*18fd37a7SXin LI they could be derived from the using array. LAST_USING is a pair
673*18fd37a7SXin LI of pointers to the last blocks in the using structure. LOW_THREAD
674*18fd37a7SXin LI and HIGH_THREAD tell which threads contain the lowest and highest
675*18fd37a7SXin LI line numbers for File0. LAST_DIFF3 contains the last diff produced
676*18fd37a7SXin LI in the calling routine. This is used for lines mappings that
677*18fd37a7SXin LI would still be identical to the state that diff ended in.
678*18fd37a7SXin LI
679*18fd37a7SXin LI A distinction should be made in this routine between the two diffs
680*18fd37a7SXin LI that are part of a normal two diff block, and the three diffs that
681*18fd37a7SXin LI are part of a diff3_block. */
682*18fd37a7SXin LI
683*18fd37a7SXin LI static struct diff3_block *
using_to_diff3_block(struct diff_block * using[2],struct diff_block * last_using[2],int low_thread,int high_thread,struct diff3_block const * last_diff3)684*18fd37a7SXin LI using_to_diff3_block (struct diff_block *using[2],
685*18fd37a7SXin LI struct diff_block *last_using[2],
686*18fd37a7SXin LI int low_thread, int high_thread,
687*18fd37a7SXin LI struct diff3_block const *last_diff3)
688*18fd37a7SXin LI {
689*18fd37a7SXin LI lin low[2], high[2];
690*18fd37a7SXin LI struct diff3_block *result;
691*18fd37a7SXin LI struct diff_block *ptr;
692*18fd37a7SXin LI int d;
693*18fd37a7SXin LI lin i;
694*18fd37a7SXin LI
695*18fd37a7SXin LI /* Find the range in the common file. */
696*18fd37a7SXin LI lin lowc = D_LOWLINE (using[low_thread], FC);
697*18fd37a7SXin LI lin highc = D_HIGHLINE (last_using[high_thread], FC);
698*18fd37a7SXin LI
699*18fd37a7SXin LI /* Find the ranges in the other files.
700*18fd37a7SXin LI If using[d] is null, that means that the file to which that diff
701*18fd37a7SXin LI refers is equivalent to the common file over this range. */
702*18fd37a7SXin LI
703*18fd37a7SXin LI for (d = 0; d < 2; d++)
704*18fd37a7SXin LI if (using[d])
705*18fd37a7SXin LI {
706*18fd37a7SXin LI low[d] = D_LOW_MAPLINE (using[d], FC, FO, lowc);
707*18fd37a7SXin LI high[d] = D_HIGH_MAPLINE (last_using[d], FC, FO, highc);
708*18fd37a7SXin LI }
709*18fd37a7SXin LI else
710*18fd37a7SXin LI {
711*18fd37a7SXin LI low[d] = D_HIGH_MAPLINE (last_diff3, FILEC, FILE0 + d, lowc);
712*18fd37a7SXin LI high[d] = D_HIGH_MAPLINE (last_diff3, FILEC, FILE0 + d, highc);
713*18fd37a7SXin LI }
714*18fd37a7SXin LI
715*18fd37a7SXin LI /* Create a block with the appropriate sizes */
716*18fd37a7SXin LI result = create_diff3_block (low[0], high[0], low[1], high[1], lowc, highc);
717*18fd37a7SXin LI
718*18fd37a7SXin LI /* Copy information for the common file.
719*18fd37a7SXin LI Return with a zero if any of the compares failed. */
720*18fd37a7SXin LI
721*18fd37a7SXin LI for (d = 0; d < 2; d++)
722*18fd37a7SXin LI for (ptr = using[d]; ptr; ptr = D_NEXT (ptr))
723*18fd37a7SXin LI {
724*18fd37a7SXin LI lin result_offset = D_LOWLINE (ptr, FC) - lowc;
725*18fd37a7SXin LI
726*18fd37a7SXin LI if (!copy_stringlist (D_LINEARRAY (ptr, FC),
727*18fd37a7SXin LI D_LENARRAY (ptr, FC),
728*18fd37a7SXin LI D_LINEARRAY (result, FILEC) + result_offset,
729*18fd37a7SXin LI D_LENARRAY (result, FILEC) + result_offset,
730*18fd37a7SXin LI D_NUMLINES (ptr, FC)))
731*18fd37a7SXin LI return 0;
732*18fd37a7SXin LI }
733*18fd37a7SXin LI
734*18fd37a7SXin LI /* Copy information for file d. First deal with anything that might be
735*18fd37a7SXin LI before the first diff. */
736*18fd37a7SXin LI
737*18fd37a7SXin LI for (d = 0; d < 2; d++)
738*18fd37a7SXin LI {
739*18fd37a7SXin LI struct diff_block *u = using[d];
740*18fd37a7SXin LI lin lo = low[d], hi = high[d];
741*18fd37a7SXin LI
742*18fd37a7SXin LI for (i = 0;
743*18fd37a7SXin LI i + lo < (u ? D_LOWLINE (u, FO) : hi + 1);
744*18fd37a7SXin LI i++)
745*18fd37a7SXin LI {
746*18fd37a7SXin LI D_RELNUM (result, FILE0 + d, i) = D_RELNUM (result, FILEC, i);
747*18fd37a7SXin LI D_RELLEN (result, FILE0 + d, i) = D_RELLEN (result, FILEC, i);
748*18fd37a7SXin LI }
749*18fd37a7SXin LI
750*18fd37a7SXin LI for (ptr = u; ptr; ptr = D_NEXT (ptr))
751*18fd37a7SXin LI {
752*18fd37a7SXin LI lin result_offset = D_LOWLINE (ptr, FO) - lo;
753*18fd37a7SXin LI lin linec;
754*18fd37a7SXin LI
755*18fd37a7SXin LI if (!copy_stringlist (D_LINEARRAY (ptr, FO),
756*18fd37a7SXin LI D_LENARRAY (ptr, FO),
757*18fd37a7SXin LI D_LINEARRAY (result, FILE0 + d) + result_offset,
758*18fd37a7SXin LI D_LENARRAY (result, FILE0 + d) + result_offset,
759*18fd37a7SXin LI D_NUMLINES (ptr, FO)))
760*18fd37a7SXin LI return 0;
761*18fd37a7SXin LI
762*18fd37a7SXin LI /* Catch the lines between here and the next diff */
763*18fd37a7SXin LI linec = D_HIGHLINE (ptr, FC) + 1 - lowc;
764*18fd37a7SXin LI for (i = D_HIGHLINE (ptr, FO) + 1 - lo;
765*18fd37a7SXin LI i < (D_NEXT (ptr) ? D_LOWLINE (D_NEXT (ptr), FO) : hi + 1) - lo;
766*18fd37a7SXin LI i++)
767*18fd37a7SXin LI {
768*18fd37a7SXin LI D_RELNUM (result, FILE0 + d, i) = D_RELNUM (result, FILEC, linec);
769*18fd37a7SXin LI D_RELLEN (result, FILE0 + d, i) = D_RELLEN (result, FILEC, linec);
770*18fd37a7SXin LI linec++;
771*18fd37a7SXin LI }
772*18fd37a7SXin LI }
773*18fd37a7SXin LI }
774*18fd37a7SXin LI
775*18fd37a7SXin LI /* Set correspond */
776*18fd37a7SXin LI if (!using[0])
777*18fd37a7SXin LI D3_TYPE (result) = DIFF_2ND;
778*18fd37a7SXin LI else if (!using[1])
779*18fd37a7SXin LI D3_TYPE (result) = DIFF_1ST;
780*18fd37a7SXin LI else
781*18fd37a7SXin LI {
782*18fd37a7SXin LI lin nl0 = D_NUMLINES (result, FILE0);
783*18fd37a7SXin LI lin nl1 = D_NUMLINES (result, FILE1);
784*18fd37a7SXin LI
785*18fd37a7SXin LI if (nl0 != nl1
786*18fd37a7SXin LI || !compare_line_list (D_LINEARRAY (result, FILE0),
787*18fd37a7SXin LI D_LENARRAY (result, FILE0),
788*18fd37a7SXin LI D_LINEARRAY (result, FILE1),
789*18fd37a7SXin LI D_LENARRAY (result, FILE1),
790*18fd37a7SXin LI nl0))
791*18fd37a7SXin LI D3_TYPE (result) = DIFF_ALL;
792*18fd37a7SXin LI else
793*18fd37a7SXin LI D3_TYPE (result) = DIFF_3RD;
794*18fd37a7SXin LI }
795*18fd37a7SXin LI
796*18fd37a7SXin LI return result;
797*18fd37a7SXin LI }
798*18fd37a7SXin LI
799*18fd37a7SXin LI /* Copy pointers from a list of strings to a different list of
800*18fd37a7SXin LI strings. If a spot in the second list is already filled, make sure
801*18fd37a7SXin LI that it is filled with the same string; if not, return false, the copy
802*18fd37a7SXin LI incomplete. Upon successful completion of the copy, return true. */
803*18fd37a7SXin LI
804*18fd37a7SXin LI static bool
copy_stringlist(char * const fromptrs[],size_t const fromlengths[],char * toptrs[],size_t tolengths[],lin copynum)805*18fd37a7SXin LI copy_stringlist (char * const fromptrs[], size_t const fromlengths[],
806*18fd37a7SXin LI char *toptrs[], size_t tolengths[],
807*18fd37a7SXin LI lin copynum)
808*18fd37a7SXin LI {
809*18fd37a7SXin LI register char * const *f = fromptrs;
810*18fd37a7SXin LI register char **t = toptrs;
811*18fd37a7SXin LI register size_t const *fl = fromlengths;
812*18fd37a7SXin LI register size_t *tl = tolengths;
813*18fd37a7SXin LI
814*18fd37a7SXin LI while (copynum--)
815*18fd37a7SXin LI {
816*18fd37a7SXin LI if (*t)
817*18fd37a7SXin LI {
818*18fd37a7SXin LI if (*fl != *tl || memcmp (*f, *t, *fl) != 0)
819*18fd37a7SXin LI return false;
820*18fd37a7SXin LI }
821*18fd37a7SXin LI else
822*18fd37a7SXin LI {
823*18fd37a7SXin LI *t = *f;
824*18fd37a7SXin LI *tl = *fl;
825*18fd37a7SXin LI }
826*18fd37a7SXin LI
827*18fd37a7SXin LI t++; f++; tl++; fl++;
828*18fd37a7SXin LI }
829*18fd37a7SXin LI
830*18fd37a7SXin LI return true;
831*18fd37a7SXin LI }
832*18fd37a7SXin LI
833*18fd37a7SXin LI /* Create a diff3_block, with ranges as specified in the arguments.
834*18fd37a7SXin LI Allocate the arrays for the various pointers (and zero them) based
835*18fd37a7SXin LI on the arguments passed. Return the block as a result. */
836*18fd37a7SXin LI
837*18fd37a7SXin LI static struct diff3_block *
create_diff3_block(lin low0,lin high0,lin low1,lin high1,lin low2,lin high2)838*18fd37a7SXin LI create_diff3_block (lin low0, lin high0,
839*18fd37a7SXin LI lin low1, lin high1,
840*18fd37a7SXin LI lin low2, lin high2)
841*18fd37a7SXin LI {
842*18fd37a7SXin LI struct diff3_block *result = xmalloc (sizeof *result);
843*18fd37a7SXin LI lin numlines;
844*18fd37a7SXin LI
845*18fd37a7SXin LI D3_TYPE (result) = ERROR;
846*18fd37a7SXin LI D_NEXT (result) = 0;
847*18fd37a7SXin LI
848*18fd37a7SXin LI /* Assign ranges */
849*18fd37a7SXin LI D_LOWLINE (result, FILE0) = low0;
850*18fd37a7SXin LI D_HIGHLINE (result, FILE0) = high0;
851*18fd37a7SXin LI D_LOWLINE (result, FILE1) = low1;
852*18fd37a7SXin LI D_HIGHLINE (result, FILE1) = high1;
853*18fd37a7SXin LI D_LOWLINE (result, FILE2) = low2;
854*18fd37a7SXin LI D_HIGHLINE (result, FILE2) = high2;
855*18fd37a7SXin LI
856*18fd37a7SXin LI /* Allocate and zero space */
857*18fd37a7SXin LI numlines = D_NUMLINES (result, FILE0);
858*18fd37a7SXin LI if (numlines)
859*18fd37a7SXin LI {
860*18fd37a7SXin LI D_LINEARRAY (result, FILE0) = xcalloc (numlines, sizeof (char *));
861*18fd37a7SXin LI D_LENARRAY (result, FILE0) = xcalloc (numlines, sizeof (size_t));
862*18fd37a7SXin LI }
863*18fd37a7SXin LI else
864*18fd37a7SXin LI {
865*18fd37a7SXin LI D_LINEARRAY (result, FILE0) = 0;
866*18fd37a7SXin LI D_LENARRAY (result, FILE0) = 0;
867*18fd37a7SXin LI }
868*18fd37a7SXin LI
869*18fd37a7SXin LI numlines = D_NUMLINES (result, FILE1);
870*18fd37a7SXin LI if (numlines)
871*18fd37a7SXin LI {
872*18fd37a7SXin LI D_LINEARRAY (result, FILE1) = xcalloc (numlines, sizeof (char *));
873*18fd37a7SXin LI D_LENARRAY (result, FILE1) = xcalloc (numlines, sizeof (size_t));
874*18fd37a7SXin LI }
875*18fd37a7SXin LI else
876*18fd37a7SXin LI {
877*18fd37a7SXin LI D_LINEARRAY (result, FILE1) = 0;
878*18fd37a7SXin LI D_LENARRAY (result, FILE1) = 0;
879*18fd37a7SXin LI }
880*18fd37a7SXin LI
881*18fd37a7SXin LI numlines = D_NUMLINES (result, FILE2);
882*18fd37a7SXin LI if (numlines)
883*18fd37a7SXin LI {
884*18fd37a7SXin LI D_LINEARRAY (result, FILE2) = xcalloc (numlines, sizeof (char *));
885*18fd37a7SXin LI D_LENARRAY (result, FILE2) = xcalloc (numlines, sizeof (size_t));
886*18fd37a7SXin LI }
887*18fd37a7SXin LI else
888*18fd37a7SXin LI {
889*18fd37a7SXin LI D_LINEARRAY (result, FILE2) = 0;
890*18fd37a7SXin LI D_LENARRAY (result, FILE2) = 0;
891*18fd37a7SXin LI }
892*18fd37a7SXin LI
893*18fd37a7SXin LI /* Return */
894*18fd37a7SXin LI return result;
895*18fd37a7SXin LI }
896*18fd37a7SXin LI
897*18fd37a7SXin LI /* Compare two lists of lines of text.
898*18fd37a7SXin LI Return 1 if they are equivalent, 0 if not. */
899*18fd37a7SXin LI
900*18fd37a7SXin LI static bool
compare_line_list(char * const list1[],size_t const lengths1[],char * const list2[],size_t const lengths2[],lin nl)901*18fd37a7SXin LI compare_line_list (char * const list1[], size_t const lengths1[],
902*18fd37a7SXin LI char * const list2[], size_t const lengths2[],
903*18fd37a7SXin LI lin nl)
904*18fd37a7SXin LI {
905*18fd37a7SXin LI char * const *l1 = list1;
906*18fd37a7SXin LI char * const *l2 = list2;
907*18fd37a7SXin LI size_t const *lgths1 = lengths1;
908*18fd37a7SXin LI size_t const *lgths2 = lengths2;
909*18fd37a7SXin LI
910*18fd37a7SXin LI while (nl--)
911*18fd37a7SXin LI if (!*l1 || !*l2 || *lgths1 != *lgths2++
912*18fd37a7SXin LI || memcmp (*l1++, *l2++, *lgths1++) != 0)
913*18fd37a7SXin LI return false;
914*18fd37a7SXin LI return true;
915*18fd37a7SXin LI }
916*18fd37a7SXin LI
917*18fd37a7SXin LI /* Input and parse two way diffs. */
918*18fd37a7SXin LI
919*18fd37a7SXin LI static struct diff_block *
process_diff(char const * filea,char const * fileb,struct diff_block ** last_block)920*18fd37a7SXin LI process_diff (char const *filea,
921*18fd37a7SXin LI char const *fileb,
922*18fd37a7SXin LI struct diff_block **last_block)
923*18fd37a7SXin LI {
924*18fd37a7SXin LI char *diff_contents;
925*18fd37a7SXin LI char *diff_limit;
926*18fd37a7SXin LI char *scan_diff;
927*18fd37a7SXin LI enum diff_type dt;
928*18fd37a7SXin LI lin i;
929*18fd37a7SXin LI struct diff_block *block_list, **block_list_end, *bptr;
930*18fd37a7SXin LI size_t too_many_lines = (PTRDIFF_MAX
931*18fd37a7SXin LI / MIN (sizeof *bptr->lines[1],
932*18fd37a7SXin LI sizeof *bptr->lengths[1]));
933*18fd37a7SXin LI
934*18fd37a7SXin LI diff_limit = read_diff (filea, fileb, &diff_contents);
935*18fd37a7SXin LI scan_diff = diff_contents;
936*18fd37a7SXin LI block_list_end = &block_list;
937*18fd37a7SXin LI bptr = 0; /* Pacify `gcc -W'. */
938*18fd37a7SXin LI
939*18fd37a7SXin LI while (scan_diff < diff_limit)
940*18fd37a7SXin LI {
941*18fd37a7SXin LI bptr = xmalloc (sizeof *bptr);
942*18fd37a7SXin LI bptr->lines[0] = bptr->lines[1] = 0;
943*18fd37a7SXin LI bptr->lengths[0] = bptr->lengths[1] = 0;
944*18fd37a7SXin LI
945*18fd37a7SXin LI dt = process_diff_control (&scan_diff, bptr);
946*18fd37a7SXin LI if (dt == ERROR || *scan_diff != '\n')
947*18fd37a7SXin LI {
948*18fd37a7SXin LI fprintf (stderr, _("%s: diff failed: "), program_name);
949*18fd37a7SXin LI do
950*18fd37a7SXin LI {
951*18fd37a7SXin LI putc (*scan_diff, stderr);
952*18fd37a7SXin LI }
953*18fd37a7SXin LI while (*scan_diff++ != '\n');
954*18fd37a7SXin LI exit (EXIT_TROUBLE);
955*18fd37a7SXin LI }
956*18fd37a7SXin LI scan_diff++;
957*18fd37a7SXin LI
958*18fd37a7SXin LI /* Force appropriate ranges to be null, if necessary */
959*18fd37a7SXin LI switch (dt)
960*18fd37a7SXin LI {
961*18fd37a7SXin LI case ADD:
962*18fd37a7SXin LI bptr->ranges[0][0]++;
963*18fd37a7SXin LI break;
964*18fd37a7SXin LI case DELETE:
965*18fd37a7SXin LI bptr->ranges[1][0]++;
966*18fd37a7SXin LI break;
967*18fd37a7SXin LI case CHANGE:
968*18fd37a7SXin LI break;
969*18fd37a7SXin LI default:
970*18fd37a7SXin LI fatal ("internal error: invalid diff type in process_diff");
971*18fd37a7SXin LI break;
972*18fd37a7SXin LI }
973*18fd37a7SXin LI
974*18fd37a7SXin LI /* Allocate space for the pointers for the lines from filea, and
975*18fd37a7SXin LI parcel them out among these pointers */
976*18fd37a7SXin LI if (dt != ADD)
977*18fd37a7SXin LI {
978*18fd37a7SXin LI lin numlines = D_NUMLINES (bptr, 0);
979*18fd37a7SXin LI if (too_many_lines <= numlines)
980*18fd37a7SXin LI xalloc_die ();
981*18fd37a7SXin LI bptr->lines[0] = xmalloc (numlines * sizeof *bptr->lines[0]);
982*18fd37a7SXin LI bptr->lengths[0] = xmalloc (numlines * sizeof *bptr->lengths[0]);
983*18fd37a7SXin LI for (i = 0; i < numlines; i++)
984*18fd37a7SXin LI scan_diff = scan_diff_line (scan_diff,
985*18fd37a7SXin LI &(bptr->lines[0][i]),
986*18fd37a7SXin LI &(bptr->lengths[0][i]),
987*18fd37a7SXin LI diff_limit,
988*18fd37a7SXin LI '<');
989*18fd37a7SXin LI }
990*18fd37a7SXin LI
991*18fd37a7SXin LI /* Get past the separator for changes */
992*18fd37a7SXin LI if (dt == CHANGE)
993*18fd37a7SXin LI {
994*18fd37a7SXin LI if (strncmp (scan_diff, "---\n", 4))
995*18fd37a7SXin LI fatal ("invalid diff format; invalid change separator");
996*18fd37a7SXin LI scan_diff += 4;
997*18fd37a7SXin LI }
998*18fd37a7SXin LI
999*18fd37a7SXin LI /* Allocate space for the pointers for the lines from fileb, and
1000*18fd37a7SXin LI parcel them out among these pointers */
1001*18fd37a7SXin LI if (dt != DELETE)
1002*18fd37a7SXin LI {
1003*18fd37a7SXin LI lin numlines = D_NUMLINES (bptr, 1);
1004*18fd37a7SXin LI if (too_many_lines <= numlines)
1005*18fd37a7SXin LI xalloc_die ();
1006*18fd37a7SXin LI bptr->lines[1] = xmalloc (numlines * sizeof *bptr->lines[1]);
1007*18fd37a7SXin LI bptr->lengths[1] = xmalloc (numlines * sizeof *bptr->lengths[1]);
1008*18fd37a7SXin LI for (i = 0; i < numlines; i++)
1009*18fd37a7SXin LI scan_diff = scan_diff_line (scan_diff,
1010*18fd37a7SXin LI &(bptr->lines[1][i]),
1011*18fd37a7SXin LI &(bptr->lengths[1][i]),
1012*18fd37a7SXin LI diff_limit,
1013*18fd37a7SXin LI '>');
1014*18fd37a7SXin LI }
1015*18fd37a7SXin LI
1016*18fd37a7SXin LI /* Place this block on the blocklist. */
1017*18fd37a7SXin LI *block_list_end = bptr;
1018*18fd37a7SXin LI block_list_end = &bptr->next;
1019*18fd37a7SXin LI }
1020*18fd37a7SXin LI
1021*18fd37a7SXin LI *block_list_end = 0;
1022*18fd37a7SXin LI *last_block = bptr;
1023*18fd37a7SXin LI return block_list;
1024*18fd37a7SXin LI }
1025*18fd37a7SXin LI
1026*18fd37a7SXin LI /* Skip tabs and spaces, and return the first character after them. */
1027*18fd37a7SXin LI
1028*18fd37a7SXin LI static char *
skipwhite(char * s)1029*18fd37a7SXin LI skipwhite (char *s)
1030*18fd37a7SXin LI {
1031*18fd37a7SXin LI while (*s == ' ' || *s == '\t')
1032*18fd37a7SXin LI s++;
1033*18fd37a7SXin LI return s;
1034*18fd37a7SXin LI }
1035*18fd37a7SXin LI
1036*18fd37a7SXin LI /* Read a nonnegative line number from S, returning the address of the
1037*18fd37a7SXin LI first character after the line number, and storing the number into
1038*18fd37a7SXin LI *PNUM. Return 0 if S does not point to a valid line number. */
1039*18fd37a7SXin LI
1040*18fd37a7SXin LI static char *
readnum(char * s,lin * pnum)1041*18fd37a7SXin LI readnum (char *s, lin *pnum)
1042*18fd37a7SXin LI {
1043*18fd37a7SXin LI unsigned char c = *s;
1044*18fd37a7SXin LI lin num = 0;
1045*18fd37a7SXin LI
1046*18fd37a7SXin LI if (! ISDIGIT (c))
1047*18fd37a7SXin LI return 0;
1048*18fd37a7SXin LI
1049*18fd37a7SXin LI do
1050*18fd37a7SXin LI {
1051*18fd37a7SXin LI num = c - '0' + num * 10;
1052*18fd37a7SXin LI c = *++s;
1053*18fd37a7SXin LI }
1054*18fd37a7SXin LI while (ISDIGIT (c));
1055*18fd37a7SXin LI
1056*18fd37a7SXin LI *pnum = num;
1057*18fd37a7SXin LI return s;
1058*18fd37a7SXin LI }
1059*18fd37a7SXin LI
1060*18fd37a7SXin LI /* Parse a normal format diff control string. Return the type of the
1061*18fd37a7SXin LI diff (ERROR if the format is bad). All of the other important
1062*18fd37a7SXin LI information is filled into to the structure pointed to by db, and
1063*18fd37a7SXin LI the string pointer (whose location is passed to this routine) is
1064*18fd37a7SXin LI updated to point beyond the end of the string parsed. Note that
1065*18fd37a7SXin LI only the ranges in the diff_block will be set by this routine.
1066*18fd37a7SXin LI
1067*18fd37a7SXin LI If some specific pair of numbers has been reduced to a single
1068*18fd37a7SXin LI number, then both corresponding numbers in the diff block are set
1069*18fd37a7SXin LI to that number. In general these numbers are interpreted as ranges
1070*18fd37a7SXin LI inclusive, unless being used by the ADD or DELETE commands. It is
1071*18fd37a7SXin LI assumed that these will be special cased in a superior routine. */
1072*18fd37a7SXin LI
1073*18fd37a7SXin LI static enum diff_type
process_diff_control(char ** string,struct diff_block * db)1074*18fd37a7SXin LI process_diff_control (char **string, struct diff_block *db)
1075*18fd37a7SXin LI {
1076*18fd37a7SXin LI char *s = *string;
1077*18fd37a7SXin LI enum diff_type type;
1078*18fd37a7SXin LI
1079*18fd37a7SXin LI /* Read first set of digits */
1080*18fd37a7SXin LI s = readnum (skipwhite (s), &db->ranges[0][RANGE_START]);
1081*18fd37a7SXin LI if (! s)
1082*18fd37a7SXin LI return ERROR;
1083*18fd37a7SXin LI
1084*18fd37a7SXin LI /* Was that the only digit? */
1085*18fd37a7SXin LI s = skipwhite (s);
1086*18fd37a7SXin LI if (*s == ',')
1087*18fd37a7SXin LI {
1088*18fd37a7SXin LI s = readnum (s + 1, &db->ranges[0][RANGE_END]);
1089*18fd37a7SXin LI if (! s)
1090*18fd37a7SXin LI return ERROR;
1091*18fd37a7SXin LI }
1092*18fd37a7SXin LI else
1093*18fd37a7SXin LI db->ranges[0][RANGE_END] = db->ranges[0][RANGE_START];
1094*18fd37a7SXin LI
1095*18fd37a7SXin LI /* Get the letter */
1096*18fd37a7SXin LI s = skipwhite (s);
1097*18fd37a7SXin LI switch (*s)
1098*18fd37a7SXin LI {
1099*18fd37a7SXin LI case 'a':
1100*18fd37a7SXin LI type = ADD;
1101*18fd37a7SXin LI break;
1102*18fd37a7SXin LI case 'c':
1103*18fd37a7SXin LI type = CHANGE;
1104*18fd37a7SXin LI break;
1105*18fd37a7SXin LI case 'd':
1106*18fd37a7SXin LI type = DELETE;
1107*18fd37a7SXin LI break;
1108*18fd37a7SXin LI default:
1109*18fd37a7SXin LI return ERROR; /* Bad format */
1110*18fd37a7SXin LI }
1111*18fd37a7SXin LI s++; /* Past letter */
1112*18fd37a7SXin LI
1113*18fd37a7SXin LI /* Read second set of digits */
1114*18fd37a7SXin LI s = readnum (skipwhite (s), &db->ranges[1][RANGE_START]);
1115*18fd37a7SXin LI if (! s)
1116*18fd37a7SXin LI return ERROR;
1117*18fd37a7SXin LI
1118*18fd37a7SXin LI /* Was that the only digit? */
1119*18fd37a7SXin LI s = skipwhite (s);
1120*18fd37a7SXin LI if (*s == ',')
1121*18fd37a7SXin LI {
1122*18fd37a7SXin LI s = readnum (s + 1, &db->ranges[1][RANGE_END]);
1123*18fd37a7SXin LI if (! s)
1124*18fd37a7SXin LI return ERROR;
1125*18fd37a7SXin LI s = skipwhite (s); /* To move to end */
1126*18fd37a7SXin LI }
1127*18fd37a7SXin LI else
1128*18fd37a7SXin LI db->ranges[1][RANGE_END] = db->ranges[1][RANGE_START];
1129*18fd37a7SXin LI
1130*18fd37a7SXin LI *string = s;
1131*18fd37a7SXin LI return type;
1132*18fd37a7SXin LI }
1133*18fd37a7SXin LI
1134*18fd37a7SXin LI static char *
read_diff(char const * filea,char const * fileb,char ** output_placement)1135*18fd37a7SXin LI read_diff (char const *filea,
1136*18fd37a7SXin LI char const *fileb,
1137*18fd37a7SXin LI char **output_placement)
1138*18fd37a7SXin LI {
1139*18fd37a7SXin LI char *diff_result;
1140*18fd37a7SXin LI size_t current_chunk_size, total;
1141*18fd37a7SXin LI int fd, wstatus, status;
1142*18fd37a7SXin LI int werrno = 0;
1143*18fd37a7SXin LI struct stat pipestat;
1144*18fd37a7SXin LI
1145*18fd37a7SXin LI #if HAVE_WORKING_FORK || HAVE_WORKING_VFORK
1146*18fd37a7SXin LI
1147*18fd37a7SXin LI char const *argv[9];
1148*18fd37a7SXin LI char const **ap;
1149*18fd37a7SXin LI int fds[2];
1150*18fd37a7SXin LI pid_t pid;
1151*18fd37a7SXin LI
1152*18fd37a7SXin LI ap = argv;
1153*18fd37a7SXin LI *ap++ = diff_program;
1154*18fd37a7SXin LI if (text)
1155*18fd37a7SXin LI *ap++ = "-a";
1156*18fd37a7SXin LI if (strip_trailing_cr)
1157*18fd37a7SXin LI *ap++ = "--strip-trailing-cr";
1158*18fd37a7SXin LI *ap++ = "--horizon-lines=100";
1159*18fd37a7SXin LI *ap++ = "--";
1160*18fd37a7SXin LI *ap++ = filea;
1161*18fd37a7SXin LI *ap++ = fileb;
1162*18fd37a7SXin LI *ap = 0;
1163*18fd37a7SXin LI
1164*18fd37a7SXin LI if (pipe (fds) != 0)
1165*18fd37a7SXin LI perror_with_exit ("pipe");
1166*18fd37a7SXin LI
1167*18fd37a7SXin LI pid = vfork ();
1168*18fd37a7SXin LI if (pid == 0)
1169*18fd37a7SXin LI {
1170*18fd37a7SXin LI /* Child */
1171*18fd37a7SXin LI close (fds[0]);
1172*18fd37a7SXin LI if (fds[1] != STDOUT_FILENO)
1173*18fd37a7SXin LI {
1174*18fd37a7SXin LI dup2 (fds[1], STDOUT_FILENO);
1175*18fd37a7SXin LI close (fds[1]);
1176*18fd37a7SXin LI }
1177*18fd37a7SXin LI
1178*18fd37a7SXin LI /* The cast to (char **) is needed for portability to older
1179*18fd37a7SXin LI hosts with a nonstandard prototype for execvp. */
1180*18fd37a7SXin LI execvp (diff_program, (char **) argv);
1181*18fd37a7SXin LI
1182*18fd37a7SXin LI _exit (errno == ENOENT ? 127 : 126);
1183*18fd37a7SXin LI }
1184*18fd37a7SXin LI
1185*18fd37a7SXin LI if (pid == -1)
1186*18fd37a7SXin LI perror_with_exit ("fork");
1187*18fd37a7SXin LI
1188*18fd37a7SXin LI close (fds[1]); /* Prevent erroneous lack of EOF */
1189*18fd37a7SXin LI fd = fds[0];
1190*18fd37a7SXin LI
1191*18fd37a7SXin LI #else
1192*18fd37a7SXin LI
1193*18fd37a7SXin LI FILE *fpipe;
1194*18fd37a7SXin LI char const args[] = " --horizon-lines=100 -- ";
1195*18fd37a7SXin LI char *command = xmalloc (quote_system_arg (0, diff_program)
1196*18fd37a7SXin LI + sizeof "-a"
1197*18fd37a7SXin LI + sizeof "--strip-trailing-cr"
1198*18fd37a7SXin LI + sizeof args - 1
1199*18fd37a7SXin LI + quote_system_arg (0, filea) + 1
1200*18fd37a7SXin LI + quote_system_arg (0, fileb) + 1);
1201*18fd37a7SXin LI char *p = command;
1202*18fd37a7SXin LI p += quote_system_arg (p, diff_program);
1203*18fd37a7SXin LI if (text)
1204*18fd37a7SXin LI {
1205*18fd37a7SXin LI strcpy (p, " -a");
1206*18fd37a7SXin LI p += 3;
1207*18fd37a7SXin LI }
1208*18fd37a7SXin LI if (strip_trailing_cr)
1209*18fd37a7SXin LI {
1210*18fd37a7SXin LI strcpy (p, " --strip-trailing-cr");
1211*18fd37a7SXin LI p += 20;
1212*18fd37a7SXin LI }
1213*18fd37a7SXin LI strcpy (p, args);
1214*18fd37a7SXin LI p += sizeof args - 1;
1215*18fd37a7SXin LI p += quote_system_arg (p, filea);
1216*18fd37a7SXin LI *p++ = ' ';
1217*18fd37a7SXin LI p += quote_system_arg (p, fileb);
1218*18fd37a7SXin LI *p = 0;
1219*18fd37a7SXin LI errno = 0;
1220*18fd37a7SXin LI fpipe = popen (command, "r");
1221*18fd37a7SXin LI if (!fpipe)
1222*18fd37a7SXin LI perror_with_exit (command);
1223*18fd37a7SXin LI free (command);
1224*18fd37a7SXin LI fd = fileno (fpipe);
1225*18fd37a7SXin LI
1226*18fd37a7SXin LI #endif
1227*18fd37a7SXin LI
1228*18fd37a7SXin LI if (fstat (fd, &pipestat) != 0)
1229*18fd37a7SXin LI perror_with_exit ("fstat");
1230*18fd37a7SXin LI current_chunk_size = MAX (1, STAT_BLOCKSIZE (pipestat));
1231*18fd37a7SXin LI diff_result = xmalloc (current_chunk_size);
1232*18fd37a7SXin LI total = 0;
1233*18fd37a7SXin LI
1234*18fd37a7SXin LI for (;;)
1235*18fd37a7SXin LI {
1236*18fd37a7SXin LI size_t bytes_to_read = current_chunk_size - total;
1237*18fd37a7SXin LI size_t bytes = block_read (fd, diff_result + total, bytes_to_read);
1238*18fd37a7SXin LI total += bytes;
1239*18fd37a7SXin LI if (bytes != bytes_to_read)
1240*18fd37a7SXin LI {
1241*18fd37a7SXin LI if (bytes == SIZE_MAX)
1242*18fd37a7SXin LI perror_with_exit (_("read failed"));
1243*18fd37a7SXin LI break;
1244*18fd37a7SXin LI }
1245*18fd37a7SXin LI if (PTRDIFF_MAX / 2 <= current_chunk_size)
1246*18fd37a7SXin LI xalloc_die ();
1247*18fd37a7SXin LI current_chunk_size *= 2;
1248*18fd37a7SXin LI diff_result = xrealloc (diff_result, current_chunk_size);
1249*18fd37a7SXin LI }
1250*18fd37a7SXin LI
1251*18fd37a7SXin LI if (total != 0 && diff_result[total-1] != '\n')
1252*18fd37a7SXin LI fatal ("invalid diff format; incomplete last line");
1253*18fd37a7SXin LI
1254*18fd37a7SXin LI *output_placement = diff_result;
1255*18fd37a7SXin LI
1256*18fd37a7SXin LI #if ! (HAVE_WORKING_FORK || HAVE_WORKING_VFORK)
1257*18fd37a7SXin LI
1258*18fd37a7SXin LI wstatus = pclose (fpipe);
1259*18fd37a7SXin LI if (wstatus == -1)
1260*18fd37a7SXin LI werrno = errno;
1261*18fd37a7SXin LI
1262*18fd37a7SXin LI #else
1263*18fd37a7SXin LI
1264*18fd37a7SXin LI if (close (fd) != 0)
1265*18fd37a7SXin LI perror_with_exit ("close");
1266*18fd37a7SXin LI if (waitpid (pid, &wstatus, 0) < 0)
1267*18fd37a7SXin LI perror_with_exit ("waitpid");
1268*18fd37a7SXin LI
1269*18fd37a7SXin LI #endif
1270*18fd37a7SXin LI
1271*18fd37a7SXin LI status = ! werrno && WIFEXITED (wstatus) ? WEXITSTATUS (wstatus) : INT_MAX;
1272*18fd37a7SXin LI
1273*18fd37a7SXin LI if (EXIT_TROUBLE <= status)
1274*18fd37a7SXin LI error (EXIT_TROUBLE, werrno,
1275*18fd37a7SXin LI _(status == 126
1276*18fd37a7SXin LI ? "subsidiary program `%s' could not be invoked"
1277*18fd37a7SXin LI : status == 127
1278*18fd37a7SXin LI ? "subsidiary program `%s' not found"
1279*18fd37a7SXin LI : status == INT_MAX
1280*18fd37a7SXin LI ? "subsidiary program `%s' failed"
1281*18fd37a7SXin LI : "subsidiary program `%s' failed (exit status %d)"),
1282*18fd37a7SXin LI diff_program, status);
1283*18fd37a7SXin LI
1284*18fd37a7SXin LI return diff_result + total;
1285*18fd37a7SXin LI }
1286*18fd37a7SXin LI
1287*18fd37a7SXin LI
1288*18fd37a7SXin LI /* Scan a regular diff line (consisting of > or <, followed by a
1289*18fd37a7SXin LI space, followed by text (including nulls) up to a newline.
1290*18fd37a7SXin LI
1291*18fd37a7SXin LI This next routine began life as a macro and many parameters in it
1292*18fd37a7SXin LI are used as call-by-reference values. */
1293*18fd37a7SXin LI static char *
scan_diff_line(char * scan_ptr,char ** set_start,size_t * set_length,char * limit,char leadingchar)1294*18fd37a7SXin LI scan_diff_line (char *scan_ptr, char **set_start, size_t *set_length,
1295*18fd37a7SXin LI char *limit, char leadingchar)
1296*18fd37a7SXin LI {
1297*18fd37a7SXin LI char *line_ptr;
1298*18fd37a7SXin LI
1299*18fd37a7SXin LI if (!(scan_ptr[0] == leadingchar
1300*18fd37a7SXin LI && scan_ptr[1] == ' '))
1301*18fd37a7SXin LI fatal ("invalid diff format; incorrect leading line chars");
1302*18fd37a7SXin LI
1303*18fd37a7SXin LI *set_start = line_ptr = scan_ptr + 2;
1304*18fd37a7SXin LI while (*line_ptr++ != '\n')
1305*18fd37a7SXin LI continue;
1306*18fd37a7SXin LI
1307*18fd37a7SXin LI /* Include newline if the original line ended in a newline,
1308*18fd37a7SXin LI or if an edit script is being generated.
1309*18fd37a7SXin LI Copy any missing newline message to stderr if an edit script is being
1310*18fd37a7SXin LI generated, because edit scripts cannot handle missing newlines.
1311*18fd37a7SXin LI Return the beginning of the next line. */
1312*18fd37a7SXin LI *set_length = line_ptr - *set_start;
1313*18fd37a7SXin LI if (line_ptr < limit && *line_ptr == '\\')
1314*18fd37a7SXin LI {
1315*18fd37a7SXin LI if (edscript)
1316*18fd37a7SXin LI fprintf (stderr, "%s:", program_name);
1317*18fd37a7SXin LI else
1318*18fd37a7SXin LI --*set_length;
1319*18fd37a7SXin LI line_ptr++;
1320*18fd37a7SXin LI do
1321*18fd37a7SXin LI {
1322*18fd37a7SXin LI if (edscript)
1323*18fd37a7SXin LI putc (*line_ptr, stderr);
1324*18fd37a7SXin LI }
1325*18fd37a7SXin LI while (*line_ptr++ != '\n');
1326*18fd37a7SXin LI }
1327*18fd37a7SXin LI
1328*18fd37a7SXin LI return line_ptr;
1329*18fd37a7SXin LI }
1330*18fd37a7SXin LI
1331*18fd37a7SXin LI /* Output a three way diff passed as a list of diff3_block's. The
1332*18fd37a7SXin LI argument MAPPING is indexed by external file number (in the
1333*18fd37a7SXin LI argument list) and contains the internal file number (from the diff
1334*18fd37a7SXin LI passed). This is important because the user expects outputs in
1335*18fd37a7SXin LI terms of the argument list number, and the diff passed may have
1336*18fd37a7SXin LI been done slightly differently (if the last argument was "-", for
1337*18fd37a7SXin LI example). REV_MAPPING is the inverse of MAPPING. */
1338*18fd37a7SXin LI
1339*18fd37a7SXin LI static void
output_diff3(FILE * outputfile,struct diff3_block * diff,int const mapping[3],int const rev_mapping[3])1340*18fd37a7SXin LI output_diff3 (FILE *outputfile, struct diff3_block *diff,
1341*18fd37a7SXin LI int const mapping[3], int const rev_mapping[3])
1342*18fd37a7SXin LI {
1343*18fd37a7SXin LI int i;
1344*18fd37a7SXin LI int oddoneout;
1345*18fd37a7SXin LI char *cp;
1346*18fd37a7SXin LI struct diff3_block *ptr;
1347*18fd37a7SXin LI lin line;
1348*18fd37a7SXin LI size_t length;
1349*18fd37a7SXin LI int dontprint;
1350*18fd37a7SXin LI static int skew_increment[3] = { 2, 3, 1 }; /* 0==>2==>1==>3 */
1351*18fd37a7SXin LI char const *line_prefix = initial_tab ? "\t" : " ";
1352*18fd37a7SXin LI
1353*18fd37a7SXin LI for (ptr = diff; ptr; ptr = D_NEXT (ptr))
1354*18fd37a7SXin LI {
1355*18fd37a7SXin LI char x[2];
1356*18fd37a7SXin LI
1357*18fd37a7SXin LI switch (ptr->correspond)
1358*18fd37a7SXin LI {
1359*18fd37a7SXin LI case DIFF_ALL:
1360*18fd37a7SXin LI x[0] = 0;
1361*18fd37a7SXin LI dontprint = 3; /* Print them all */
1362*18fd37a7SXin LI oddoneout = 3; /* Nobody's odder than anyone else */
1363*18fd37a7SXin LI break;
1364*18fd37a7SXin LI case DIFF_1ST:
1365*18fd37a7SXin LI case DIFF_2ND:
1366*18fd37a7SXin LI case DIFF_3RD:
1367*18fd37a7SXin LI oddoneout = rev_mapping[ptr->correspond - DIFF_1ST];
1368*18fd37a7SXin LI
1369*18fd37a7SXin LI x[0] = oddoneout + '1';
1370*18fd37a7SXin LI x[1] = 0;
1371*18fd37a7SXin LI dontprint = oddoneout == 0;
1372*18fd37a7SXin LI break;
1373*18fd37a7SXin LI default:
1374*18fd37a7SXin LI fatal ("internal error: invalid diff type passed to output");
1375*18fd37a7SXin LI }
1376*18fd37a7SXin LI fprintf (outputfile, "====%s\n", x);
1377*18fd37a7SXin LI
1378*18fd37a7SXin LI /* Go 0, 2, 1 if the first and third outputs are equivalent. */
1379*18fd37a7SXin LI for (i = 0; i < 3;
1380*18fd37a7SXin LI i = (oddoneout == 1 ? skew_increment[i] : i + 1))
1381*18fd37a7SXin LI {
1382*18fd37a7SXin LI int realfile = mapping[i];
1383*18fd37a7SXin LI lin lowt = D_LOWLINE (ptr, realfile);
1384*18fd37a7SXin LI lin hight = D_HIGHLINE (ptr, realfile);
1385*18fd37a7SXin LI long int llowt = lowt;
1386*18fd37a7SXin LI long int lhight = hight;
1387*18fd37a7SXin LI
1388*18fd37a7SXin LI fprintf (outputfile, "%d:", i + 1);
1389*18fd37a7SXin LI switch (lowt - hight)
1390*18fd37a7SXin LI {
1391*18fd37a7SXin LI case 1:
1392*18fd37a7SXin LI fprintf (outputfile, "%lda\n", llowt - 1);
1393*18fd37a7SXin LI break;
1394*18fd37a7SXin LI case 0:
1395*18fd37a7SXin LI fprintf (outputfile, "%ldc\n", llowt);
1396*18fd37a7SXin LI break;
1397*18fd37a7SXin LI default:
1398*18fd37a7SXin LI fprintf (outputfile, "%ld,%ldc\n", llowt, lhight);
1399*18fd37a7SXin LI break;
1400*18fd37a7SXin LI }
1401*18fd37a7SXin LI
1402*18fd37a7SXin LI if (i == dontprint) continue;
1403*18fd37a7SXin LI
1404*18fd37a7SXin LI if (lowt <= hight)
1405*18fd37a7SXin LI {
1406*18fd37a7SXin LI line = 0;
1407*18fd37a7SXin LI do
1408*18fd37a7SXin LI {
1409*18fd37a7SXin LI fprintf (outputfile, line_prefix);
1410*18fd37a7SXin LI cp = D_RELNUM (ptr, realfile, line);
1411*18fd37a7SXin LI length = D_RELLEN (ptr, realfile, line);
1412*18fd37a7SXin LI fwrite (cp, sizeof (char), length, outputfile);
1413*18fd37a7SXin LI }
1414*18fd37a7SXin LI while (++line < hight - lowt + 1);
1415*18fd37a7SXin LI if (cp[length - 1] != '\n')
1416*18fd37a7SXin LI fprintf (outputfile, "\n\\ %s\n",
1417*18fd37a7SXin LI _("No newline at end of file"));
1418*18fd37a7SXin LI }
1419*18fd37a7SXin LI }
1420*18fd37a7SXin LI }
1421*18fd37a7SXin LI }
1422*18fd37a7SXin LI
1423*18fd37a7SXin LI
1424*18fd37a7SXin LI /* Output to OUTPUTFILE the lines of B taken from FILENUM. Double any
1425*18fd37a7SXin LI initial '.'s; yield nonzero if any initial '.'s were doubled. */
1426*18fd37a7SXin LI
1427*18fd37a7SXin LI static bool
dotlines(FILE * outputfile,struct diff3_block * b,int filenum)1428*18fd37a7SXin LI dotlines (FILE *outputfile, struct diff3_block *b, int filenum)
1429*18fd37a7SXin LI {
1430*18fd37a7SXin LI lin i;
1431*18fd37a7SXin LI bool leading_dot = false;
1432*18fd37a7SXin LI
1433*18fd37a7SXin LI for (i = 0;
1434*18fd37a7SXin LI i < D_NUMLINES (b, filenum);
1435*18fd37a7SXin LI i++)
1436*18fd37a7SXin LI {
1437*18fd37a7SXin LI char *line = D_RELNUM (b, filenum, i);
1438*18fd37a7SXin LI if (line[0] == '.')
1439*18fd37a7SXin LI {
1440*18fd37a7SXin LI leading_dot = true;
1441*18fd37a7SXin LI fprintf (outputfile, ".");
1442*18fd37a7SXin LI }
1443*18fd37a7SXin LI fwrite (line, sizeof (char),
1444*18fd37a7SXin LI D_RELLEN (b, filenum, i), outputfile);
1445*18fd37a7SXin LI }
1446*18fd37a7SXin LI
1447*18fd37a7SXin LI return leading_dot;
1448*18fd37a7SXin LI }
1449*18fd37a7SXin LI
1450*18fd37a7SXin LI /* Output to OUTPUTFILE a '.' line. If LEADING_DOT is true, also
1451*18fd37a7SXin LI output a command that removes initial '.'s starting with line START
1452*18fd37a7SXin LI and continuing for NUM lines. (START is long int, not lin, for
1453*18fd37a7SXin LI convenience with printf %ld formats.) */
1454*18fd37a7SXin LI
1455*18fd37a7SXin LI static void
undotlines(FILE * outputfile,bool leading_dot,long int start,lin num)1456*18fd37a7SXin LI undotlines (FILE *outputfile, bool leading_dot, long int start, lin num)
1457*18fd37a7SXin LI {
1458*18fd37a7SXin LI fprintf (outputfile, ".\n");
1459*18fd37a7SXin LI if (leading_dot)
1460*18fd37a7SXin LI {
1461*18fd37a7SXin LI if (num == 1)
1462*18fd37a7SXin LI fprintf (outputfile, "%lds/^\\.//\n", start);
1463*18fd37a7SXin LI else
1464*18fd37a7SXin LI fprintf (outputfile, "%ld,%lds/^\\.//\n", start, start + num - 1);
1465*18fd37a7SXin LI }
1466*18fd37a7SXin LI }
1467*18fd37a7SXin LI
1468*18fd37a7SXin LI /* Output a diff3 set of blocks as an ed script. This script applies
1469*18fd37a7SXin LI the changes between file's 2 & 3 to file 1. Take the precise
1470*18fd37a7SXin LI format of the ed script to be output from global variables set
1471*18fd37a7SXin LI during options processing. Reverse the order of
1472*18fd37a7SXin LI the set of diff3 blocks in DIFF; this gets
1473*18fd37a7SXin LI around the problems involved with changing line numbers in an ed
1474*18fd37a7SXin LI script.
1475*18fd37a7SXin LI
1476*18fd37a7SXin LI As in `output_diff3', the variable MAPPING maps from file number
1477*18fd37a7SXin LI according to the argument list to file number according to the diff
1478*18fd37a7SXin LI passed. All files listed below are in terms of the argument list.
1479*18fd37a7SXin LI REV_MAPPING is the inverse of MAPPING.
1480*18fd37a7SXin LI
1481*18fd37a7SXin LI FILE0, FILE1 and FILE2 are the strings to print as the names of the
1482*18fd37a7SXin LI three files. These may be the actual names, or may be the
1483*18fd37a7SXin LI arguments specified with -L.
1484*18fd37a7SXin LI
1485*18fd37a7SXin LI Return 1 if conflicts were found. */
1486*18fd37a7SXin LI
1487*18fd37a7SXin LI static bool
output_diff3_edscript(FILE * outputfile,struct diff3_block * diff,int const mapping[3],int const rev_mapping[3],char const * file0,char const * file1,char const * file2)1488*18fd37a7SXin LI output_diff3_edscript (FILE *outputfile, struct diff3_block *diff,
1489*18fd37a7SXin LI int const mapping[3], int const rev_mapping[3],
1490*18fd37a7SXin LI char const *file0, char const *file1, char const *file2)
1491*18fd37a7SXin LI {
1492*18fd37a7SXin LI bool leading_dot;
1493*18fd37a7SXin LI bool conflicts_found = false;
1494*18fd37a7SXin LI bool conflict;
1495*18fd37a7SXin LI struct diff3_block *b;
1496*18fd37a7SXin LI
1497*18fd37a7SXin LI for (b = reverse_diff3_blocklist (diff); b; b = b->next)
1498*18fd37a7SXin LI {
1499*18fd37a7SXin LI /* Must do mapping correctly. */
1500*18fd37a7SXin LI enum diff_type type
1501*18fd37a7SXin LI = (b->correspond == DIFF_ALL
1502*18fd37a7SXin LI ? DIFF_ALL
1503*18fd37a7SXin LI : DIFF_1ST + rev_mapping[b->correspond - DIFF_1ST]);
1504*18fd37a7SXin LI
1505*18fd37a7SXin LI long int low0, high0;
1506*18fd37a7SXin LI
1507*18fd37a7SXin LI /* If we aren't supposed to do this output block, skip it. */
1508*18fd37a7SXin LI switch (type)
1509*18fd37a7SXin LI {
1510*18fd37a7SXin LI default: continue;
1511*18fd37a7SXin LI case DIFF_2ND: if (!show_2nd) continue; conflict = true; break;
1512*18fd37a7SXin LI case DIFF_3RD: if (overlap_only) continue; conflict = false; break;
1513*18fd37a7SXin LI case DIFF_ALL: if (simple_only) continue; conflict = flagging; break;
1514*18fd37a7SXin LI }
1515*18fd37a7SXin LI
1516*18fd37a7SXin LI low0 = D_LOWLINE (b, mapping[FILE0]);
1517*18fd37a7SXin LI high0 = D_HIGHLINE (b, mapping[FILE0]);
1518*18fd37a7SXin LI
1519*18fd37a7SXin LI if (conflict)
1520*18fd37a7SXin LI {
1521*18fd37a7SXin LI conflicts_found = true;
1522*18fd37a7SXin LI
1523*18fd37a7SXin LI
1524*18fd37a7SXin LI /* Mark end of conflict. */
1525*18fd37a7SXin LI
1526*18fd37a7SXin LI fprintf (outputfile, "%lda\n", high0);
1527*18fd37a7SXin LI leading_dot = false;
1528*18fd37a7SXin LI if (type == DIFF_ALL)
1529*18fd37a7SXin LI {
1530*18fd37a7SXin LI if (show_2nd)
1531*18fd37a7SXin LI {
1532*18fd37a7SXin LI /* Append lines from FILE1. */
1533*18fd37a7SXin LI fprintf (outputfile, "||||||| %s\n", file1);
1534*18fd37a7SXin LI leading_dot = dotlines (outputfile, b, mapping[FILE1]);
1535*18fd37a7SXin LI }
1536*18fd37a7SXin LI /* Append lines from FILE2. */
1537*18fd37a7SXin LI fprintf (outputfile, "=======\n");
1538*18fd37a7SXin LI leading_dot |= dotlines (outputfile, b, mapping[FILE2]);
1539*18fd37a7SXin LI }
1540*18fd37a7SXin LI fprintf (outputfile, ">>>>>>> %s\n", file2);
1541*18fd37a7SXin LI undotlines (outputfile, leading_dot, high0 + 2,
1542*18fd37a7SXin LI (D_NUMLINES (b, mapping[FILE1])
1543*18fd37a7SXin LI + D_NUMLINES (b, mapping[FILE2]) + 1));
1544*18fd37a7SXin LI
1545*18fd37a7SXin LI
1546*18fd37a7SXin LI /* Mark start of conflict. */
1547*18fd37a7SXin LI
1548*18fd37a7SXin LI fprintf (outputfile, "%lda\n<<<<<<< %s\n", low0 - 1,
1549*18fd37a7SXin LI type == DIFF_ALL ? file0 : file1);
1550*18fd37a7SXin LI leading_dot = false;
1551*18fd37a7SXin LI if (type == DIFF_2ND)
1552*18fd37a7SXin LI {
1553*18fd37a7SXin LI /* Prepend lines from FILE1. */
1554*18fd37a7SXin LI leading_dot = dotlines (outputfile, b, mapping[FILE1]);
1555*18fd37a7SXin LI fprintf (outputfile, "=======\n");
1556*18fd37a7SXin LI }
1557*18fd37a7SXin LI undotlines (outputfile, leading_dot, low0 + 1,
1558*18fd37a7SXin LI D_NUMLINES (b, mapping[FILE1]));
1559*18fd37a7SXin LI }
1560*18fd37a7SXin LI else if (D_NUMLINES (b, mapping[FILE2]) == 0)
1561*18fd37a7SXin LI /* Write out a delete */
1562*18fd37a7SXin LI {
1563*18fd37a7SXin LI if (low0 == high0)
1564*18fd37a7SXin LI fprintf (outputfile, "%ldd\n", low0);
1565*18fd37a7SXin LI else
1566*18fd37a7SXin LI fprintf (outputfile, "%ld,%ldd\n", low0, high0);
1567*18fd37a7SXin LI }
1568*18fd37a7SXin LI else
1569*18fd37a7SXin LI /* Write out an add or change */
1570*18fd37a7SXin LI {
1571*18fd37a7SXin LI switch (high0 - low0)
1572*18fd37a7SXin LI {
1573*18fd37a7SXin LI case -1:
1574*18fd37a7SXin LI fprintf (outputfile, "%lda\n", high0);
1575*18fd37a7SXin LI break;
1576*18fd37a7SXin LI case 0:
1577*18fd37a7SXin LI fprintf (outputfile, "%ldc\n", high0);
1578*18fd37a7SXin LI break;
1579*18fd37a7SXin LI default:
1580*18fd37a7SXin LI fprintf (outputfile, "%ld,%ldc\n", low0, high0);
1581*18fd37a7SXin LI break;
1582*18fd37a7SXin LI }
1583*18fd37a7SXin LI
1584*18fd37a7SXin LI undotlines (outputfile, dotlines (outputfile, b, mapping[FILE2]),
1585*18fd37a7SXin LI low0, D_NUMLINES (b, mapping[FILE2]));
1586*18fd37a7SXin LI }
1587*18fd37a7SXin LI }
1588*18fd37a7SXin LI if (finalwrite) fprintf (outputfile, "w\nq\n");
1589*18fd37a7SXin LI return conflicts_found;
1590*18fd37a7SXin LI }
1591*18fd37a7SXin LI
1592*18fd37a7SXin LI /* Read from INFILE and output to OUTPUTFILE a set of diff3_blocks
1593*18fd37a7SXin LI DIFF as a merged file. This acts like 'ed file0
1594*18fd37a7SXin LI <[output_diff3_edscript]', except that it works even for binary
1595*18fd37a7SXin LI data or incomplete lines.
1596*18fd37a7SXin LI
1597*18fd37a7SXin LI As before, MAPPING maps from arg list file number to diff file
1598*18fd37a7SXin LI number, REV_MAPPING is its inverse, and FILE0, FILE1, and FILE2 are
1599*18fd37a7SXin LI the names of the files.
1600*18fd37a7SXin LI
1601*18fd37a7SXin LI Return 1 if conflicts were found. */
1602*18fd37a7SXin LI
1603*18fd37a7SXin LI static bool
output_diff3_merge(FILE * infile,FILE * outputfile,struct diff3_block * diff,int const mapping[3],int const rev_mapping[3],char const * file0,char const * file1,char const * file2)1604*18fd37a7SXin LI output_diff3_merge (FILE *infile, FILE *outputfile, struct diff3_block *diff,
1605*18fd37a7SXin LI int const mapping[3], int const rev_mapping[3],
1606*18fd37a7SXin LI char const *file0, char const *file1, char const *file2)
1607*18fd37a7SXin LI {
1608*18fd37a7SXin LI int c;
1609*18fd37a7SXin LI lin i;
1610*18fd37a7SXin LI bool conflicts_found = false;
1611*18fd37a7SXin LI bool conflict;
1612*18fd37a7SXin LI struct diff3_block *b;
1613*18fd37a7SXin LI lin linesread = 0;
1614*18fd37a7SXin LI
1615*18fd37a7SXin LI for (b = diff; b; b = b->next)
1616*18fd37a7SXin LI {
1617*18fd37a7SXin LI /* Must do mapping correctly. */
1618*18fd37a7SXin LI enum diff_type type
1619*18fd37a7SXin LI = ((b->correspond == DIFF_ALL)
1620*18fd37a7SXin LI ? DIFF_ALL
1621*18fd37a7SXin LI : DIFF_1ST + rev_mapping[b->correspond - DIFF_1ST]);
1622*18fd37a7SXin LI char const *format_2nd = "<<<<<<< %s\n";
1623*18fd37a7SXin LI
1624*18fd37a7SXin LI /* If we aren't supposed to do this output block, skip it. */
1625*18fd37a7SXin LI switch (type)
1626*18fd37a7SXin LI {
1627*18fd37a7SXin LI default: continue;
1628*18fd37a7SXin LI case DIFF_2ND: if (!show_2nd) continue; conflict = true; break;
1629*18fd37a7SXin LI case DIFF_3RD: if (overlap_only) continue; conflict = false; break;
1630*18fd37a7SXin LI case DIFF_ALL: if (simple_only) continue; conflict = flagging;
1631*18fd37a7SXin LI format_2nd = "||||||| %s\n";
1632*18fd37a7SXin LI break;
1633*18fd37a7SXin LI }
1634*18fd37a7SXin LI
1635*18fd37a7SXin LI /* Copy I lines from file 0. */
1636*18fd37a7SXin LI i = D_LOWLINE (b, FILE0) - linesread - 1;
1637*18fd37a7SXin LI linesread += i;
1638*18fd37a7SXin LI while (0 <= --i)
1639*18fd37a7SXin LI do
1640*18fd37a7SXin LI {
1641*18fd37a7SXin LI c = getc (infile);
1642*18fd37a7SXin LI if (c == EOF)
1643*18fd37a7SXin LI {
1644*18fd37a7SXin LI if (ferror (infile))
1645*18fd37a7SXin LI perror_with_exit (_("read failed"));
1646*18fd37a7SXin LI else if (feof (infile))
1647*18fd37a7SXin LI fatal ("input file shrank");
1648*18fd37a7SXin LI }
1649*18fd37a7SXin LI putc (c, outputfile);
1650*18fd37a7SXin LI }
1651*18fd37a7SXin LI while (c != '\n');
1652*18fd37a7SXin LI
1653*18fd37a7SXin LI if (conflict)
1654*18fd37a7SXin LI {
1655*18fd37a7SXin LI conflicts_found = true;
1656*18fd37a7SXin LI
1657*18fd37a7SXin LI if (type == DIFF_ALL)
1658*18fd37a7SXin LI {
1659*18fd37a7SXin LI /* Put in lines from FILE0 with bracket. */
1660*18fd37a7SXin LI fprintf (outputfile, "<<<<<<< %s\n", file0);
1661*18fd37a7SXin LI for (i = 0;
1662*18fd37a7SXin LI i < D_NUMLINES (b, mapping[FILE0]);
1663*18fd37a7SXin LI i++)
1664*18fd37a7SXin LI fwrite (D_RELNUM (b, mapping[FILE0], i), sizeof (char),
1665*18fd37a7SXin LI D_RELLEN (b, mapping[FILE0], i), outputfile);
1666*18fd37a7SXin LI }
1667*18fd37a7SXin LI
1668*18fd37a7SXin LI if (show_2nd)
1669*18fd37a7SXin LI {
1670*18fd37a7SXin LI /* Put in lines from FILE1 with bracket. */
1671*18fd37a7SXin LI fprintf (outputfile, format_2nd, file1);
1672*18fd37a7SXin LI for (i = 0;
1673*18fd37a7SXin LI i < D_NUMLINES (b, mapping[FILE1]);
1674*18fd37a7SXin LI i++)
1675*18fd37a7SXin LI fwrite (D_RELNUM (b, mapping[FILE1], i), sizeof (char),
1676*18fd37a7SXin LI D_RELLEN (b, mapping[FILE1], i), outputfile);
1677*18fd37a7SXin LI }
1678*18fd37a7SXin LI
1679*18fd37a7SXin LI fprintf (outputfile, "=======\n");
1680*18fd37a7SXin LI }
1681*18fd37a7SXin LI
1682*18fd37a7SXin LI /* Put in lines from FILE2. */
1683*18fd37a7SXin LI for (i = 0;
1684*18fd37a7SXin LI i < D_NUMLINES (b, mapping[FILE2]);
1685*18fd37a7SXin LI i++)
1686*18fd37a7SXin LI fwrite (D_RELNUM (b, mapping[FILE2], i), sizeof (char),
1687*18fd37a7SXin LI D_RELLEN (b, mapping[FILE2], i), outputfile);
1688*18fd37a7SXin LI
1689*18fd37a7SXin LI if (conflict)
1690*18fd37a7SXin LI fprintf (outputfile, ">>>>>>> %s\n", file2);
1691*18fd37a7SXin LI
1692*18fd37a7SXin LI /* Skip I lines in file 0. */
1693*18fd37a7SXin LI i = D_NUMLINES (b, FILE0);
1694*18fd37a7SXin LI linesread += i;
1695*18fd37a7SXin LI while (0 <= --i)
1696*18fd37a7SXin LI while ((c = getc (infile)) != '\n')
1697*18fd37a7SXin LI if (c == EOF)
1698*18fd37a7SXin LI {
1699*18fd37a7SXin LI if (ferror (infile))
1700*18fd37a7SXin LI perror_with_exit (_("read failed"));
1701*18fd37a7SXin LI else if (feof (infile))
1702*18fd37a7SXin LI {
1703*18fd37a7SXin LI if (i || b->next)
1704*18fd37a7SXin LI fatal ("input file shrank");
1705*18fd37a7SXin LI return conflicts_found;
1706*18fd37a7SXin LI }
1707*18fd37a7SXin LI }
1708*18fd37a7SXin LI }
1709*18fd37a7SXin LI /* Copy rest of common file. */
1710*18fd37a7SXin LI while ((c = getc (infile)) != EOF || !(ferror (infile) | feof (infile)))
1711*18fd37a7SXin LI putc (c, outputfile);
1712*18fd37a7SXin LI return conflicts_found;
1713*18fd37a7SXin LI }
1714*18fd37a7SXin LI
1715*18fd37a7SXin LI /* Reverse the order of the list of diff3 blocks. */
1716*18fd37a7SXin LI
1717*18fd37a7SXin LI static struct diff3_block *
reverse_diff3_blocklist(struct diff3_block * diff)1718*18fd37a7SXin LI reverse_diff3_blocklist (struct diff3_block *diff)
1719*18fd37a7SXin LI {
1720*18fd37a7SXin LI register struct diff3_block *tmp, *next, *prev;
1721*18fd37a7SXin LI
1722*18fd37a7SXin LI for (tmp = diff, prev = 0; tmp; tmp = next)
1723*18fd37a7SXin LI {
1724*18fd37a7SXin LI next = tmp->next;
1725*18fd37a7SXin LI tmp->next = prev;
1726*18fd37a7SXin LI prev = tmp;
1727*18fd37a7SXin LI }
1728*18fd37a7SXin LI
1729*18fd37a7SXin LI return prev;
1730*18fd37a7SXin LI }
1731*18fd37a7SXin LI
1732*18fd37a7SXin LI static void
fatal(char const * msgid)1733*18fd37a7SXin LI fatal (char const *msgid)
1734*18fd37a7SXin LI {
1735*18fd37a7SXin LI error (EXIT_TROUBLE, 0, "%s", _(msgid));
1736*18fd37a7SXin LI abort ();
1737*18fd37a7SXin LI }
1738*18fd37a7SXin LI
1739*18fd37a7SXin LI static void
perror_with_exit(char const * string)1740*18fd37a7SXin LI perror_with_exit (char const *string)
1741*18fd37a7SXin LI {
1742*18fd37a7SXin LI error (EXIT_TROUBLE, errno, "%s", string);
1743*18fd37a7SXin LI abort ();
1744*18fd37a7SXin LI }
1745