xref: /netbsd-src/external/gpl2/rcs/dist/src/rcsmerge.c (revision fa28c6faa16e0b00edee7acdcaf4899797043def)
1*fa28c6faSchristos /*	$NetBSD: rcsmerge.c,v 1.2 2016/01/14 04:22:39 christos Exp $	*/
27bdc2678Schristos 
37bdc2678Schristos /* Merge RCS revisions.  */
47bdc2678Schristos 
57bdc2678Schristos /* Copyright 1982, 1988, 1989 Walter Tichy
67bdc2678Schristos    Copyright 1990, 1991, 1992, 1993, 1994, 1995 Paul Eggert
77bdc2678Schristos    Distributed under license by the Free Software Foundation, Inc.
87bdc2678Schristos 
97bdc2678Schristos This file is part of RCS.
107bdc2678Schristos 
117bdc2678Schristos RCS is free software; you can redistribute it and/or modify
127bdc2678Schristos it under the terms of the GNU General Public License as published by
137bdc2678Schristos the Free Software Foundation; either version 2, or (at your option)
147bdc2678Schristos any later version.
157bdc2678Schristos 
167bdc2678Schristos RCS is distributed in the hope that it will be useful,
177bdc2678Schristos but WITHOUT ANY WARRANTY; without even the implied warranty of
187bdc2678Schristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
197bdc2678Schristos GNU General Public License for more details.
207bdc2678Schristos 
217bdc2678Schristos You should have received a copy of the GNU General Public License
227bdc2678Schristos along with RCS; see the file COPYING.
237bdc2678Schristos If not, write to the Free Software Foundation,
247bdc2678Schristos 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
257bdc2678Schristos 
267bdc2678Schristos Report problems and direct all questions to:
277bdc2678Schristos 
287bdc2678Schristos     rcs-bugs@cs.purdue.edu
297bdc2678Schristos 
307bdc2678Schristos */
317bdc2678Schristos 
327bdc2678Schristos /*
337bdc2678Schristos  * Log: rcsmerge.c,v
347bdc2678Schristos  * Revision 5.15  1995/06/16 06:19:24  eggert
357bdc2678Schristos  * Update FSF address.
367bdc2678Schristos  *
377bdc2678Schristos  * Revision 5.14  1995/06/01 16:23:43  eggert
387bdc2678Schristos  * (main): Report an error if -kb, so don't worry about binary stdout.
397bdc2678Schristos  * Punctuate messages properly.  Rewrite to avoid `goto end'.
407bdc2678Schristos  *
417bdc2678Schristos  * Revision 5.13  1994/03/17 14:05:48  eggert
427bdc2678Schristos  * Specify subprocess input via file descriptor, not file name.  Remove lint.
437bdc2678Schristos  *
447bdc2678Schristos  * Revision 5.12  1993/11/09 17:40:15  eggert
457bdc2678Schristos  * -V now prints version on stdout and exits.  Don't print usage twice.
467bdc2678Schristos  *
477bdc2678Schristos  * Revision 5.11  1993/11/03 17:42:27  eggert
487bdc2678Schristos  * Add -A, -E, -e, -z.  Ignore -T.  Allow up to three file labels.
497bdc2678Schristos  * Pass -Vn to `co'.  Pass unexpanded revision name to `co', so that Name works.
507bdc2678Schristos  *
517bdc2678Schristos  * Revision 5.10  1992/07/28  16:12:44  eggert
527bdc2678Schristos  * Add -V.
537bdc2678Schristos  *
547bdc2678Schristos  * Revision 5.9  1992/01/24  18:44:19  eggert
557bdc2678Schristos  * lint -> RCS_lint
567bdc2678Schristos  *
577bdc2678Schristos  * Revision 5.8  1992/01/06  02:42:34  eggert
587bdc2678Schristos  * Update usage string.
597bdc2678Schristos  *
607bdc2678Schristos  * Revision 5.7  1991/11/20  17:58:09  eggert
617bdc2678Schristos  * Don't Iopen(f, "r+"); it's not portable.
627bdc2678Schristos  *
637bdc2678Schristos  * Revision 5.6  1991/08/19  03:13:55  eggert
647bdc2678Schristos  * Add -r$.  Tune.
657bdc2678Schristos  *
667bdc2678Schristos  * Revision 5.5  1991/04/21  11:58:27  eggert
677bdc2678Schristos  * Add -x, RCSINIT, MS-DOS support.
687bdc2678Schristos  *
697bdc2678Schristos  * Revision 5.4  1991/02/25  07:12:43  eggert
707bdc2678Schristos  * Merging a revision to itself is no longer an error.
717bdc2678Schristos  *
727bdc2678Schristos  * Revision 5.3  1990/11/01  05:03:50  eggert
737bdc2678Schristos  * Remove unneeded setid check.
747bdc2678Schristos  *
757bdc2678Schristos  * Revision 5.2  1990/09/04  08:02:28  eggert
767bdc2678Schristos  * Check for I/O error when reading working file.
777bdc2678Schristos  *
787bdc2678Schristos  * Revision 5.1  1990/08/29  07:14:04  eggert
797bdc2678Schristos  * Add -q.  Pass -L options to merge.
807bdc2678Schristos  *
817bdc2678Schristos  * Revision 5.0  1990/08/22  08:13:41  eggert
827bdc2678Schristos  * Propagate merge's exit status.
837bdc2678Schristos  * Remove compile-time limits; use malloc instead.
847bdc2678Schristos  * Make lock and temp files faster and safer.  Ansify and Posixate.  Add -V.
857bdc2678Schristos  * Don't use access().  Tune.
867bdc2678Schristos  *
877bdc2678Schristos  * Revision 4.5  89/05/01  15:13:16  narten
887bdc2678Schristos  * changed copyright header to reflect current distribution rules
897bdc2678Schristos  *
907bdc2678Schristos  * Revision 4.4  88/08/09  19:13:13  eggert
917bdc2678Schristos  * Beware merging into a readonly file.
927bdc2678Schristos  * Beware merging a revision to itself (no change).
937bdc2678Schristos  * Use execv(), not system(); yield exit status like diff(1)'s.
947bdc2678Schristos  *
957bdc2678Schristos  * Revision 4.3  87/10/18  10:38:02  narten
967bdc2678Schristos  * Updating version numbers. Changes relative to version 1.1
977bdc2678Schristos  * actually relative to 4.1
987bdc2678Schristos  *
997bdc2678Schristos  * Revision 1.3  87/09/24  14:00:31  narten
1007bdc2678Schristos  * Sources now pass through lint (if you ignore printf/sprintf/fprintf
1017bdc2678Schristos  * warnings)
1027bdc2678Schristos  *
1037bdc2678Schristos  * Revision 1.2  87/03/27  14:22:36  jenkins
1047bdc2678Schristos  * Port to suns
1057bdc2678Schristos  *
1067bdc2678Schristos  * Revision 4.1  83/03/28  11:14:57  wft
1077bdc2678Schristos  * Added handling of default branch.
1087bdc2678Schristos  *
1097bdc2678Schristos  * Revision 3.3  82/12/24  15:29:00  wft
1107bdc2678Schristos  * Added call to catchsig().
1117bdc2678Schristos  *
1127bdc2678Schristos  * Revision 3.2  82/12/10  21:32:02  wft
1137bdc2678Schristos  * Replaced getdelta() with gettree(); improved error messages.
1147bdc2678Schristos  *
1157bdc2678Schristos  * Revision 3.1  82/11/28  19:27:44  wft
1167bdc2678Schristos  * Initial revision.
1177bdc2678Schristos  *
1187bdc2678Schristos  */
1197bdc2678Schristos #include "rcsbase.h"
1207bdc2678Schristos 
1217bdc2678Schristos static char const co[] = CO;
1227bdc2678Schristos 
1237bdc2678Schristos mainProg(rcsmergeId, "rcsmerge", "Id: rcsmerge.c,v 5.15 1995/06/16 06:19:24 eggert Exp ")
1247bdc2678Schristos {
1257bdc2678Schristos 	static char const cmdusage[] =
1267bdc2678Schristos 		"\nrcsmerge usage: rcsmerge -rrev1 [-rrev2] -ksubst -{pq}[rev] -Vn -xsuff -zzone file";
1277bdc2678Schristos 	static char const quietarg[] = "-q";
1287bdc2678Schristos 
1297bdc2678Schristos 	register int i;
1307bdc2678Schristos 	char *a, **newargv;
1317bdc2678Schristos 	char const *arg[3];
1327bdc2678Schristos 	char const *rev[3], *xrev[3]; /*revision numbers*/
1337bdc2678Schristos 	char const *edarg, *expandarg, *suffixarg, *versionarg, *zonearg;
1347bdc2678Schristos         int tostdout;
1357bdc2678Schristos 	int status;
1367bdc2678Schristos 	RILE *workptr;
1377bdc2678Schristos 	struct buf commarg;
1387bdc2678Schristos 	struct buf numericrev; /* holds expanded revision number */
1397bdc2678Schristos 	struct hshentries *gendeltas; /* deltas to be generated */
1407bdc2678Schristos         struct hshentry * target;
1417bdc2678Schristos 
1427bdc2678Schristos 	bufautobegin(&commarg);
1437bdc2678Schristos 	bufautobegin(&numericrev);
1447bdc2678Schristos 	edarg = rev[1] = rev[2] = 0;
1457bdc2678Schristos 	status = 0; /* Keep lint happy.  */
1467bdc2678Schristos 	tostdout = false;
1477bdc2678Schristos 	expandarg = suffixarg = versionarg = zonearg = quietarg; /* no-op */
1487bdc2678Schristos 	suffixes = X_DEFAULT;
1497bdc2678Schristos 
1507bdc2678Schristos 	argc = getRCSINIT(argc, argv, &newargv);
1517bdc2678Schristos 	argv = newargv;
1527bdc2678Schristos 	while (a = *++argv,  0<--argc && *a++=='-') {
1537bdc2678Schristos 		switch (*a++) {
1547bdc2678Schristos                 case 'p':
1557bdc2678Schristos                         tostdout=true;
1567bdc2678Schristos 			goto revno;
1577bdc2678Schristos 
1587bdc2678Schristos 		case 'q':
1597bdc2678Schristos 			quietflag = true;
1607bdc2678Schristos 		revno:
1617bdc2678Schristos 			if (!*a)
1627bdc2678Schristos 				break;
1637bdc2678Schristos                         /* falls into -r */
1647bdc2678Schristos                 case 'r':
1657bdc2678Schristos 			if (!rev[1])
1667bdc2678Schristos 				rev[1] = a;
1677bdc2678Schristos 			else if (!rev[2])
1687bdc2678Schristos 				rev[2] = a;
1697bdc2678Schristos 			else
1707bdc2678Schristos 				error("too many revision numbers");
1717bdc2678Schristos                         break;
1727bdc2678Schristos 
1737bdc2678Schristos 		case 'A': case 'E': case 'e':
1747bdc2678Schristos 			if (*a)
1757bdc2678Schristos 				goto unknown;
1767bdc2678Schristos 			edarg = *argv;
1777bdc2678Schristos 			break;
1787bdc2678Schristos 
1797bdc2678Schristos 		case 'x':
1807bdc2678Schristos 			suffixarg = *argv;
1817bdc2678Schristos 			suffixes = a;
1827bdc2678Schristos 			break;
1837bdc2678Schristos 		case 'z':
1847bdc2678Schristos 			zonearg = *argv;
1857bdc2678Schristos 			zone_set(a);
1867bdc2678Schristos 			break;
1877bdc2678Schristos 		case 'T':
1887bdc2678Schristos 			/* Ignore -T, so that RCSINIT can contain -T.  */
1897bdc2678Schristos 			if (*a)
1907bdc2678Schristos 				goto unknown;
1917bdc2678Schristos 			break;
1927bdc2678Schristos 		case 'V':
1937bdc2678Schristos 			versionarg = *argv;
1947bdc2678Schristos 			setRCSversion(versionarg);
1957bdc2678Schristos 			break;
1967bdc2678Schristos 
1977bdc2678Schristos 		case 'k':
1987bdc2678Schristos 			expandarg = *argv;
1997bdc2678Schristos 			if (0 <= str2expmode(expandarg+2))
2007bdc2678Schristos 			    break;
2017bdc2678Schristos 			/* fall into */
2027bdc2678Schristos                 default:
2037bdc2678Schristos 		unknown:
2047bdc2678Schristos 			error("unknown option: %s%s", *argv, cmdusage);
2057bdc2678Schristos                 };
2067bdc2678Schristos         } /* end of option processing */
2077bdc2678Schristos 
2087bdc2678Schristos 	if (!rev[1]) faterror("no base revision number given");
2097bdc2678Schristos 
2107bdc2678Schristos 	/* Now handle all pathnames.  */
2117bdc2678Schristos 
2127bdc2678Schristos 	if (!nerror) {
2137bdc2678Schristos 	    if (argc < 1)
2147bdc2678Schristos 		faterror("no input file%s", cmdusage);
2157bdc2678Schristos 	    if (0 < pairnames(argc, argv, rcsreadopen, true, false)) {
2167bdc2678Schristos 
2177bdc2678Schristos                 if (argc>2  ||  (argc==2 && argv[1]))
2187bdc2678Schristos 			warn("excess arguments ignored");
2197bdc2678Schristos 		if (Expand == BINARY_EXPAND)
2207bdc2678Schristos 			workerror("merging binary files");
2217bdc2678Schristos 		diagnose("RCS file: %s\n", RCSname);
2227bdc2678Schristos 		if (!(workptr = Iopen(workname, FOPEN_R_WORK, (struct stat*)0)))
2237bdc2678Schristos 			efaterror(workname);
2247bdc2678Schristos 
2257bdc2678Schristos                 gettree();  /* reads in the delta tree */
2267bdc2678Schristos 
2277bdc2678Schristos 		if (!Head) rcsfaterror("no revisions present");
2287bdc2678Schristos 
2297bdc2678Schristos 		if (!*rev[1])
2307bdc2678Schristos 			rev[1]  =  Dbranch ? Dbranch : Head->num;
2317bdc2678Schristos 		if (fexpandsym(rev[1], &numericrev, workptr)
2327bdc2678Schristos 		    && (target=genrevs(numericrev.string, (char *)0, (char *)0, (char*)0, &gendeltas))
2337bdc2678Schristos 		) {
2347bdc2678Schristos 		  xrev[1] = target->num;
2357bdc2678Schristos 		  if (!rev[2] || !*rev[2])
2367bdc2678Schristos 			rev[2]  =  Dbranch ? Dbranch : Head->num;
2377bdc2678Schristos 		  if (fexpandsym(rev[2], &numericrev, workptr)
2387bdc2678Schristos 		      && (target=genrevs(numericrev.string, (char *)0, (char *)0, (char *)0, &gendeltas))
2397bdc2678Schristos 		  ) {
2407bdc2678Schristos 		    xrev[2] = target->num;
2417bdc2678Schristos 
2427bdc2678Schristos 		    if (strcmp(xrev[1],xrev[2]) == 0) {
2437bdc2678Schristos 		      if (tostdout) {
2447bdc2678Schristos 			fastcopy(workptr, stdout);
2457bdc2678Schristos 			Ofclose(stdout);
2467bdc2678Schristos 		      }
2477bdc2678Schristos 		    } else {
2487bdc2678Schristos 		      Izclose(&workptr);
2497bdc2678Schristos 
2507bdc2678Schristos 		      for (i=1; i<=2; i++) {
2517bdc2678Schristos 			diagnose("retrieving revision %s\n", xrev[i]);
2527bdc2678Schristos 			bufscpy(&commarg, "-p");
2537bdc2678Schristos 			bufscat(&commarg, rev[i]); /* not xrev[i], for $Name's sake */
2547bdc2678Schristos 			if (run(
2557bdc2678Schristos 				-1,
2567bdc2678Schristos 				/* Do not collide with merger.c maketemp().  */
2577bdc2678Schristos 				arg[i] = maketemp(i+2),
2587bdc2678Schristos 				co, quietarg, commarg.string,
2597bdc2678Schristos 				expandarg, suffixarg, versionarg, zonearg,
2607bdc2678Schristos 				RCSname, (char*)0
2617bdc2678Schristos 			))
2627bdc2678Schristos 				rcsfaterror("co failed");
2637bdc2678Schristos 		      }
2647bdc2678Schristos 		      diagnose("Merging differences between %s and %s into %s%s\n",
2657bdc2678Schristos 			       xrev[1], xrev[2], workname,
2667bdc2678Schristos 			       tostdout?"; result to stdout":"");
2677bdc2678Schristos 
2687bdc2678Schristos 		      arg[0] = xrev[0] = workname;
2697bdc2678Schristos 		      status = merge(tostdout, edarg, xrev, arg);
2707bdc2678Schristos 		    }
2717bdc2678Schristos 		  }
2727bdc2678Schristos 		}
2737bdc2678Schristos 
2747bdc2678Schristos 		Izclose(&workptr);
2757bdc2678Schristos 	    }
2767bdc2678Schristos         }
2777bdc2678Schristos 	tempunlink();
2787bdc2678Schristos 	exitmain(nerror ? DIFF_TROUBLE : status);
2797bdc2678Schristos }
2807bdc2678Schristos 
2817bdc2678Schristos #if RCS_lint
2827bdc2678Schristos #	define exiterr rmergeExit
2837bdc2678Schristos #endif
2847bdc2678Schristos 	void
exiterr()2857bdc2678Schristos exiterr()
2867bdc2678Schristos {
2877bdc2678Schristos 	tempunlink();
2887bdc2678Schristos 	_exit(DIFF_TROUBLE);
2897bdc2678Schristos }
290