merger.c revision 22996
1128707Sru/* three-way file merge internals */
2128707Sru
3128707Sru/* Copyright 1991, 1992, 1993, 1994, 1995 Paul Eggert
4128707Sru   Distributed under license by the Free Software Foundation, Inc.
5128707Sru
6128707SruThis file is part of RCS.
7128707Sru
8128707SruRCS is free software; you can redistribute it and/or modify
9128707Sruit under the terms of the GNU General Public License as published by
10128707Sruthe Free Software Foundation; either version 2, or (at your option)
11128707Sruany later version.
12128707Sru
13128707SruRCS is distributed in the hope that it will be useful,
14128707Srubut WITHOUT ANY WARRANTY; without even the implied warranty of
15128707SruMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16128707SruGNU General Public License for more details.
17125932Sru
18129240SruYou should have received a copy of the GNU General Public License
19129240Srualong with RCS; see the file COPYING.
20125932SruIf not, write to the Free Software Foundation,
21125932Sru59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22125932Sru
23125932SruReport problems and direct all questions to:
24125932Sru
25125932Sru    rcs-bugs@cs.purdue.edu
26125932Sru
27241301Savg*/
28125932Sru
29220337Srdivacky#include "rcsbase.h"
30220337Srdivacky
31129240SrulibId(mergerId, "$Id$")
32129240Sru
33129240Sru	static char const *normalize_arg P((char const*,char**));
34220337Srdivacky	static char const *
35129240Srunormalize_arg(s, b)
36220337Srdivacky	char const *s;
37129240Sru	char **b;
38129240Sru/*
39129240Sru * If S looks like an option, prepend ./ to it.  Yield the result.
40129240Sru * Set *B to the address of any storage that was allocated.
41129240Sru */
42129240Sru{
43242804Sdim	char *t;
44125932Sru	if (*s == '-') {
45241301Savg		*b = t = testalloc(strlen(s) + 3);
46125932Sru		VOID sprintf(t, ".%c%s", SLASH, s);
47242804Sdim		return t;
48241301Savg	} else {
49241301Savg		*b = 0;
50241301Savg		return s;
51241301Savg	}
52241301Savg}
53241301Savg
54125932Sru	int
55128707Srumerge(tostdout, edarg, label, argv)
56125932Sru	int tostdout;
57220337Srdivacky	char const *edarg;
58220337Srdivacky	char const *const label[3];
59129240Sru	char const *const argv[3];
60129240Sru/*
61129240Sru * Do `merge [-p] EDARG -L l0 -L l1 -L l2 a0 a1 a2',
62129240Sru * where TOSTDOUT specifies whether -p is present,
63129240Sru * EDARG gives the editing type (e.g. "-A", or null for the default),
64129240Sru * LABEL gives l0, l1 and l2, and ARGV gives a0, a1 and a2.
65220337Srdivacky * Yield DIFF_SUCCESS or DIFF_FAILURE.
66129240Sru */
67129240Sru{
68220337Srdivacky	register int i;
69125932Sru	FILE *f;
70128707Sru	RILE *rt;
71125932Sru	char const *a[3], *t;
72129240Sru	char *b[3];
73129240Sru	int s;
74129240Sru#if !DIFF3_BIN
75129240Sru	char const *d[2];
76129240Sru#endif
77125932Sru
78128707Sru	for (i=3; 0<=--i; )
79125932Sru		a[i] = normalize_arg(argv[i], &b[i]);
80129240Sru
81129240Sru	if (!edarg)
82129240Sru		edarg = "-E";
83129240Sru
84129240Sru#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