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