merger.c revision 9
19Sjkh/* merger - three-way file merge internals */
29Sjkh
39Sjkh/* Copyright 1991 by Paul Eggert
49Sjkh   Distributed under license by the Free Software Foundation, Inc.
59Sjkh
69SjkhThis file is part of RCS.
79Sjkh
89SjkhRCS is free software; you can redistribute it and/or modify
99Sjkhit under the terms of the GNU General Public License as published by
109Sjkhthe Free Software Foundation; either version 2, or (at your option)
119Sjkhany later version.
129Sjkh
139SjkhRCS is distributed in the hope that it will be useful,
149Sjkhbut WITHOUT ANY WARRANTY; without even the implied warranty of
159SjkhMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
169SjkhGNU General Public License for more details.
179Sjkh
189SjkhYou should have received a copy of the GNU General Public License
199Sjkhalong with RCS; see the file COPYING.  If not, write to
209Sjkhthe Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
219Sjkh
229SjkhReport problems and direct all questions to:
239Sjkh
249Sjkh    rcs-bugs@cs.purdue.edu
259Sjkh
269Sjkh*/
279Sjkh
289Sjkh#include "rcsbase.h"
299Sjkh
309SjkhlibId(mergerId, "$Id: merger.c,v 1.3 1991/08/20 23:05:00 eggert Exp $")
319Sjkh
329Sjkh	static char const *
339Sjkhnormalize_arg(s, b)
349Sjkh	char const *s;
359Sjkh	char **b;
369Sjkh/*
379Sjkh * If S looks like an option, prepend ./ to it.  Yield the result.
389Sjkh * Set *B to the address of any storage that was allocated..
399Sjkh */
409Sjkh{
419Sjkh	char *t;
429Sjkh	switch (*s) {
439Sjkh		case '-': case '+':
449Sjkh			*b = t = testalloc(strlen(s) + 3);
459Sjkh			VOID sprintf(t, ".%c%s", SLASH, s);
469Sjkh			return t;
479Sjkh		default:
489Sjkh			*b = 0;
499Sjkh			return s;
509Sjkh	}
519Sjkh}
529Sjkh
539Sjkh	int
549Sjkhmerge(tostdout, label, argv)
559Sjkh	int tostdout;
569Sjkh	char const *const label[2];
579Sjkh	char const *const argv[3];
589Sjkh/*
599Sjkh * Do `merge [-p] -L l0 -L l1 a0 a1 a2',
609Sjkh * where TOSTDOUT specifies whether -p is present,
619Sjkh * LABEL gives l0 and l1, and ARGV gives a0, a1, and a2.
629Sjkh * Yield DIFF_SUCCESS or DIFF_FAILURE.
639Sjkh */
649Sjkh{
659Sjkh	register int i;
669Sjkh	FILE *f;
679Sjkh	RILE *rt;
689Sjkh	char const *a[3], *t;
699Sjkh	char *b[3];
709Sjkh	int s;
719Sjkh#if !DIFF3_BIN
729Sjkh	char const *d[2];
739Sjkh#endif
749Sjkh
759Sjkh	for (i=3; 0<=--i; )
769Sjkh		a[i] = normalize_arg(argv[i], &b[i]);
779Sjkh
789Sjkh#if DIFF3_BIN
799Sjkh	t = 0;
809Sjkh	if (!tostdout)
819Sjkh		t = maketemp(0);
829Sjkh	s = run(
839Sjkh		(char*)0, t,
849Sjkh		DIFF3, "-am", "-L", label[0], "-L", label[1],
859Sjkh		a[0], a[1], a[2], (char*)0
869Sjkh	);
879Sjkh	switch (s) {
889Sjkh		case DIFF_SUCCESS:
899Sjkh			break;
909Sjkh		case DIFF_FAILURE:
919Sjkh			if (!quietflag)
929Sjkh				warn("overlaps during merge");
939Sjkh			break;
949Sjkh		default:
959Sjkh			exiterr();
969Sjkh	}
979Sjkh	if (t) {
989Sjkh		if (!(f = fopen(argv[0], FOPEN_W)))
999Sjkh			efaterror(argv[0]);
1009Sjkh		if (!(rt = Iopen(t, FOPEN_R, (struct stat*)0)))
1019Sjkh			efaterror(t);
1029Sjkh		fastcopy(rt, f);
1039Sjkh		Ifclose(rt);
1049Sjkh		Ofclose(f);
1059Sjkh	}
1069Sjkh#else
1079Sjkh	for (i=0; i<2; i++)
1089Sjkh		switch (run(
1099Sjkh			(char*)0, d[i]=maketemp(i),
1109Sjkh			DIFF, a[i], a[2], (char*)0
1119Sjkh		)) {
1129Sjkh			case DIFF_FAILURE: case DIFF_SUCCESS: break;
1139Sjkh			default: exiterr();
1149Sjkh		}
1159Sjkh	t = maketemp(2);
1169Sjkh	s = run(
1179Sjkh		(char*)0, t,
1189Sjkh		DIFF3, "-E", d[0], d[1], a[0], a[1], a[2],
1199Sjkh		label[0], label[1], (char*)0
1209Sjkh	);
1219Sjkh	if (s != DIFF_SUCCESS) {
1229Sjkh		s = DIFF_FAILURE;
1239Sjkh		if (!quietflag)
1249Sjkh			warn("overlaps or other problems during merge");
1259Sjkh	}
1269Sjkh	if (!(f = fopen(t, "a")))
1279Sjkh		efaterror(t);
1289Sjkh	aputs(tostdout ? "1,$p\n" : "w\n",  f);
1299Sjkh	Ofclose(f);
1309Sjkh	if (run(t, (char*)0, ED, "-", a[0], (char*)0))
1319Sjkh		exiterr();
1329Sjkh#endif
1339Sjkh
1349Sjkh	tempunlink();
1359Sjkh	for (i=3; 0<=--i; )
1369Sjkh		if (b[i])
1379Sjkh			tfree(b[i]);
1389Sjkh	return s;
1399Sjkh}
140