1 /* three-way file merge internals
2 
3    Copyright (C) 2010-2020 Thien-Thi Nguyen
4    Copyright (C) 1991, 1992, 1993, 1994, 1995 Paul Eggert
5 
6    This file is part of GNU RCS.
7 
8    GNU RCS is free software: you can redistribute it and/or modify it
9    under the terms of the GNU General Public License as published by
10    the Free Software Foundation, either version 3 of the License, or
11    (at your option) any later version.
12 
13    GNU RCS is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty
15    of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16    See the GNU General Public License for more details.
17 
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 */
21 
22 #include "base.h"
23 #include <string.h>
24 #include <stdlib.h>
25 #include "b-complain.h"
26 #include "b-divvy.h"
27 #include "b-fb.h"
28 #include "b-feph.h"
29 #include "b-fro.h"
30 #include "b-merger.h"
31 
32 int
merge(bool tostdout,char const * edarg,struct symdef three_manifestations[3])33 merge (bool tostdout, char const *edarg, struct symdef three_manifestations[3])
34 /* Do ‘merge [-p] EDARG -L l0 -L l1 -L l2 a0 a1 a2’, where ‘tostdout’
35    specifies whether ‘-p’ is present, ‘edarg’ gives the editing type
36    (e.g. "-A", or null for the default), and lN and aN are taken from
37    three_manifestations[N].{meaningful,underlying}, respectively.
38    Return ‘DIFF_SUCCESS’ or ‘DIFF_FAILURE’.  */
39 {
40   register int i;
41   FILE *f;
42   struct fro *rt;
43   char const *a[3], *t;
44   int s;
45 
46   for (i = 3; 0 <= --i;)
47     {
48       char const *filename = FNAME (i);
49 
50       /* If a filename begins with hyphen, prepend ‘./’.  */
51       if ('-' == filename[0])
52         {
53           accf (PLEXUS, ".%c", SLASH);
54           a[i] = str_save (filename);
55         }
56       else
57         a[i] = filename;
58     }
59 
60   if (!edarg)
61     edarg = "-E";
62 
63   if (DIFF3_BIN)
64     {
65       t = NULL;
66       if (!tostdout)
67         t = maketemp (0);
68       s = run (-1, t, prog_diff3, edarg, "-am",
69                "-L", LABEL (0), "-L", LABEL (1), "-L", LABEL (2),
70                a[0], a[1], a[2], NULL);
71       if (DIFF_TROUBLE == s)
72         BOW_OUT ();
73       if (DIFF_FAILURE == s)
74         PWARN ("conflicts during merge");
75       if (t)
76         {
77           if (!(f = fopen_safer (FNAME (0), "w")))
78             fatal_sys (FNAME (0));
79           if (!(rt = fro_open (t, "r", NULL)))
80             fatal_sys (t);
81           fro_spew (rt, f);
82           fro_close (rt);
83           Ozclose (&f);
84         }
85     }
86   else
87     {
88       char const *d[2];
89 
90       for (i = 0; i < 2; i++)
91         if (DIFF_TROUBLE == run (-1, d[i] = maketemp (i), prog_diff,
92                                  a[i], a[2], NULL))
93           PFATAL ("diff failed");
94       t = maketemp (2);
95       s = run (-1, t,
96                prog_diff3, edarg, d[0], d[1], a[0], a[1], a[2],
97                LABEL (0), LABEL (2), NULL);
98       if (s != DIFF_SUCCESS)
99         {
100           s = DIFF_FAILURE;
101           PWARN ("overlaps or other problems during merge");
102         }
103       if (!(f = fopen_safer (t, "a+")))
104         fatal_sys (t);
105       aputs (tostdout ? "1,$p\n" : "w\n", f);
106       rewind (f);
107       aflush (f);
108       if (run (fileno (f), NULL, ED, "-", a[0], NULL))
109         BOW_OUT ();
110       Ozclose (&f);
111     }
112 
113   tempunlink ();
114   return s;
115 }
116 
117 /* merger.c ends here */
118