]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - gnu/usr.bin/rcs/lib/merger.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / gnu / usr.bin / rcs / lib / merger.c
1 /* three-way file merge internals */
2
3 /* Copyright 1991, 1992, 1993, 1994, 1995 Paul Eggert
4    Distributed under license by the Free Software Foundation, Inc.
5
6 This file is part of RCS.
7
8 RCS is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
11 any later version.
12
13 RCS is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with RCS; see the file COPYING.
20 If not, write to the Free Software Foundation,
21 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22
23 Report problems and direct all questions to:
24
25     rcs-bugs@cs.purdue.edu
26
27 */
28
29 #include "rcsbase.h"
30
31 libId(mergerId, "$FreeBSD$")
32
33         static char const *normalize_arg P((char const*,char**));
34         static char const *
35 normalize_arg(s, b)
36         char const *s;
37         char **b;
38 /*
39  * If S looks like an option, prepend ./ to it.  Yield the result.
40  * Set *B to the address of any storage that was allocated.
41  */
42 {
43         char *t;
44         if (*s == '-') {
45                 *b = t = testalloc(strlen(s) + 3);
46                 VOID sprintf(t, ".%c%s", SLASH, s);
47                 return t;
48         } else {
49                 *b = 0;
50                 return s;
51         }
52 }
53
54         int
55 merge(tostdout, edarg, label, argv)
56         int tostdout;
57         char const *edarg;
58         char const *const label[3];
59         char const *const argv[3];
60 /*
61  * Do `merge [-p] EDARG -L l0 -L l1 -L l2 a0 a1 a2',
62  * where TOSTDOUT specifies whether -p is present,
63  * EDARG gives the editing type (e.g. "-A", or null for the default),
64  * LABEL gives l0, l1 and l2, and ARGV gives a0, a1 and a2.
65  * Yield DIFF_SUCCESS or DIFF_FAILURE.
66  */
67 {
68         register int i;
69         FILE *f;
70         RILE *rt;
71         char const *a[3], *t;
72         char *b[3];
73         int s;
74 #if !DIFF3_BIN
75         char const *d[2];
76 #endif
77
78         for (i=3; 0<=--i; )
79                 a[i] = normalize_arg(argv[i], &b[i]);
80
81         if (!edarg)
82                 edarg = "-E";
83
84 #if DIFF3_BIN
85         t = 0;
86         if (!tostdout)
87                 t = maketemp(0);
88         s = run(
89                 -1, t,
90                 DIFF3, edarg, "-am",
91                 "-L", label[0],
92                 "-L", label[1],
93                 "-L", label[2],
94                 a[0], a[1], a[2], (char*)0
95         );
96         switch (s) {
97                 case DIFF_SUCCESS:
98                         break;
99                 case DIFF_FAILURE:
100                         warn("conflicts during merge");
101                         break;
102                 default:
103                         exiterr();
104         }
105         if (t) {
106                 if (!(f = fopenSafer(argv[0], "w")))
107                         efaterror(argv[0]);
108                 if (!(rt = Iopen(t, "r", (struct stat*)0)))
109                         efaterror(t);
110                 fastcopy(rt, f);
111                 Ifclose(rt);
112                 Ofclose(f);
113         }
114 #else
115         for (i=0; i<2; i++)
116                 switch (run(
117                         -1, d[i]=maketemp(i),
118                         DIFF, a[i], a[2], (char*)0
119                 )) {
120                         case DIFF_FAILURE: case DIFF_SUCCESS: break;
121                         default: faterror("diff failed");
122                 }
123         t = maketemp(2);
124         s = run(
125                 -1, t,
126                 DIFF3, edarg, d[0], d[1], a[0], a[1], a[2],
127                 label[0], label[2], (char*)0
128         );
129         if (s != DIFF_SUCCESS) {
130                 s = DIFF_FAILURE;
131                 warn("overlaps or other problems during merge");
132         }
133         if (!(f = fopenSafer(t, "a+")))
134                 efaterror(t);
135         aputs(tostdout ? "1,$p\n" : "w\n",  f);
136         Orewind(f);
137         aflush(f);
138         if (run(fileno(f), (char*)0, ED, "-", a[0], (char*)0))
139                 exiterr();
140         Ofclose(f);
141 #endif
142
143         tempunlink();
144         for (i=3; 0<=--i; )
145                 if (b[i])
146                         tfree(b[i]);
147         return s;
148 }