merger.c revision 9
1/* merger - three-way file merge internals */
2
3/* Copyright 1991 by 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.  If not, write to
20the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
21
22Report problems and direct all questions to:
23
24    rcs-bugs@cs.purdue.edu
25
26*/
27
28#include "rcsbase.h"
29
30libId(mergerId, "$Id: merger.c,v 1.3 1991/08/20 23:05:00 eggert Exp $")
31
32	static char const *
33normalize_arg(s, b)
34	char const *s;
35	char **b;
36/*
37 * If S looks like an option, prepend ./ to it.  Yield the result.
38 * Set *B to the address of any storage that was allocated..
39 */
40{
41	char *t;
42	switch (*s) {
43		case '-': case '+':
44			*b = t = testalloc(strlen(s) + 3);
45			VOID sprintf(t, ".%c%s", SLASH, s);
46			return t;
47		default:
48			*b = 0;
49			return s;
50	}
51}
52
53	int
54merge(tostdout, label, argv)
55	int tostdout;
56	char const *const label[2];
57	char const *const argv[3];
58/*
59 * Do `merge [-p] -L l0 -L l1 a0 a1 a2',
60 * where TOSTDOUT specifies whether -p is present,
61 * LABEL gives l0 and l1, and ARGV gives a0, a1, and a2.
62 * Yield DIFF_SUCCESS or DIFF_FAILURE.
63 */
64{
65	register int i;
66	FILE *f;
67	RILE *rt;
68	char const *a[3], *t;
69	char *b[3];
70	int s;
71#if !DIFF3_BIN
72	char const *d[2];
73#endif
74
75	for (i=3; 0<=--i; )
76		a[i] = normalize_arg(argv[i], &b[i]);
77
78#if DIFF3_BIN
79	t = 0;
80	if (!tostdout)
81		t = maketemp(0);
82	s = run(
83		(char*)0, t,
84		DIFF3, "-am", "-L", label[0], "-L", label[1],
85		a[0], a[1], a[2], (char*)0
86	);
87	switch (s) {
88		case DIFF_SUCCESS:
89			break;
90		case DIFF_FAILURE:
91			if (!quietflag)
92				warn("overlaps during merge");
93			break;
94		default:
95			exiterr();
96	}
97	if (t) {
98		if (!(f = fopen(argv[0], FOPEN_W)))
99			efaterror(argv[0]);
100		if (!(rt = Iopen(t, FOPEN_R, (struct stat*)0)))
101			efaterror(t);
102		fastcopy(rt, f);
103		Ifclose(rt);
104		Ofclose(f);
105	}
106#else
107	for (i=0; i<2; i++)
108		switch (run(
109			(char*)0, d[i]=maketemp(i),
110			DIFF, a[i], a[2], (char*)0
111		)) {
112			case DIFF_FAILURE: case DIFF_SUCCESS: break;
113			default: exiterr();
114		}
115	t = maketemp(2);
116	s = run(
117		(char*)0, t,
118		DIFF3, "-E", d[0], d[1], a[0], a[1], a[2],
119		label[0], label[1], (char*)0
120	);
121	if (s != DIFF_SUCCESS) {
122		s = DIFF_FAILURE;
123		if (!quietflag)
124			warn("overlaps or other problems during merge");
125	}
126	if (!(f = fopen(t, "a")))
127		efaterror(t);
128	aputs(tostdout ? "1,$p\n" : "w\n",  f);
129	Ofclose(f);
130	if (run(t, (char*)0, ED, "-", a[0], (char*)0))
131		exiterr();
132#endif
133
134	tempunlink();
135	for (i=3; 0<=--i; )
136		if (b[i])
137			tfree(b[i]);
138	return s;
139}
140