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