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
6This file is part of RCS.
7
8RCS is free software; you can redistribute it and/or modify
9it under the terms of the GNU General Public License as published by
10the Free Software Foundation; either version 2, or (at your option)
11any later version.
12
13RCS is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16GNU General Public License for more details.
17
18You should have received a copy of the GNU General Public License
19along with RCS; see the file COPYING.
20If not, write to the Free Software Foundation,
2159 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22
23Report problems and direct all questions to:
24
25    rcs-bugs@cs.purdue.edu
26
27*/
28
29#include "rcsbase.h"
30
31libId(mergerId, "$FreeBSD$")
32
33	static char const *normalize_arg P((char const*,char**));
34	static char const *
35normalize_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
55merge(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}
149