186d7f5d3SJohn Marino /* Compare RCS revisions. */
286d7f5d3SJohn Marino
386d7f5d3SJohn Marino /* Copyright 1982, 1988, 1989 Walter Tichy
486d7f5d3SJohn Marino Copyright 1990, 1991, 1992, 1993, 1994, 1995 Paul Eggert
586d7f5d3SJohn Marino Distributed under license by the Free Software Foundation, Inc.
686d7f5d3SJohn Marino
786d7f5d3SJohn Marino This file is part of RCS.
886d7f5d3SJohn Marino
986d7f5d3SJohn Marino RCS is free software; you can redistribute it and/or modify
1086d7f5d3SJohn Marino it under the terms of the GNU General Public License as published by
1186d7f5d3SJohn Marino the Free Software Foundation; either version 2, or (at your option)
1286d7f5d3SJohn Marino any later version.
1386d7f5d3SJohn Marino
1486d7f5d3SJohn Marino RCS is distributed in the hope that it will be useful,
1586d7f5d3SJohn Marino but WITHOUT ANY WARRANTY; without even the implied warranty of
1686d7f5d3SJohn Marino MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1786d7f5d3SJohn Marino GNU General Public License for more details.
1886d7f5d3SJohn Marino
1986d7f5d3SJohn Marino You should have received a copy of the GNU General Public License
2086d7f5d3SJohn Marino along with RCS; see the file COPYING.
2186d7f5d3SJohn Marino If not, write to the Free Software Foundation,
2286d7f5d3SJohn Marino 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
2386d7f5d3SJohn Marino
2486d7f5d3SJohn Marino Report problems and direct all questions to:
2586d7f5d3SJohn Marino
2686d7f5d3SJohn Marino rcs-bugs@cs.purdue.edu
2786d7f5d3SJohn Marino
2886d7f5d3SJohn Marino */
2986d7f5d3SJohn Marino
3086d7f5d3SJohn Marino /*
3186d7f5d3SJohn Marino * $FreeBSD: src/gnu/usr.bin/rcs/rcsdiff/rcsdiff.c,v 1.8 1999/08/27 23:36:55 peter Exp $
3286d7f5d3SJohn Marino * $DragonFly: src/gnu/usr.bin/rcs/rcsdiff/rcsdiff.c,v 1.2 2003/06/17 04:25:48 dillon Exp $
3386d7f5d3SJohn Marino *
3486d7f5d3SJohn Marino * Revision 5.19 1995/06/16 06:19:24 eggert
3586d7f5d3SJohn Marino * Update FSF address.
3686d7f5d3SJohn Marino *
3786d7f5d3SJohn Marino * Revision 5.18 1995/06/01 16:23:43 eggert
3886d7f5d3SJohn Marino * (main): Pass "--binary" if -kb and if --binary makes a difference.
3986d7f5d3SJohn Marino * Don't treat + options specially.
4086d7f5d3SJohn Marino *
4186d7f5d3SJohn Marino * Revision 5.17 1994/03/17 14:05:48 eggert
4286d7f5d3SJohn Marino * Specify subprocess input via file descriptor, not file name. Remove lint.
4386d7f5d3SJohn Marino *
4486d7f5d3SJohn Marino * Revision 5.16 1993/11/09 17:40:15 eggert
4586d7f5d3SJohn Marino * -V now prints version on stdout and exits. Don't print usage twice.
4686d7f5d3SJohn Marino *
4786d7f5d3SJohn Marino * Revision 5.15 1993/11/03 17:42:27 eggert
4886d7f5d3SJohn Marino * Add -z. Ignore -T. Pass -Vn to `co'. Add Name keyword.
4986d7f5d3SJohn Marino * Put revision numbers in -c output. Improve quality of diagnostics.
5086d7f5d3SJohn Marino *
5186d7f5d3SJohn Marino * Revision 5.14 1992/07/28 16:12:44 eggert
5286d7f5d3SJohn Marino * Add -V. Use co -M for better dates with traditional diff -c.
5386d7f5d3SJohn Marino *
5486d7f5d3SJohn Marino * Revision 5.13 1992/02/17 23:02:23 eggert
5586d7f5d3SJohn Marino * Output more readable context diff headers.
5686d7f5d3SJohn Marino * Suppress needless checkout and comparison of identical revisions.
5786d7f5d3SJohn Marino *
5886d7f5d3SJohn Marino * Revision 5.12 1992/01/24 18:44:19 eggert
5986d7f5d3SJohn Marino * Add GNU diff 1.15.2's new options. lint -> RCS_lint
6086d7f5d3SJohn Marino *
6186d7f5d3SJohn Marino * Revision 5.11 1992/01/06 02:42:34 eggert
6286d7f5d3SJohn Marino * Update usage string.
6386d7f5d3SJohn Marino *
6486d7f5d3SJohn Marino * Revision 5.10 1991/10/07 17:32:46 eggert
6586d7f5d3SJohn Marino * Remove lint.
6686d7f5d3SJohn Marino *
6786d7f5d3SJohn Marino * Revision 5.9 1991/08/19 03:13:55 eggert
6886d7f5d3SJohn Marino * Add RCSINIT, -r$. Tune.
6986d7f5d3SJohn Marino *
7086d7f5d3SJohn Marino * Revision 5.8 1991/04/21 11:58:21 eggert
7186d7f5d3SJohn Marino * Add -x, RCSINIT, MS-DOS support.
7286d7f5d3SJohn Marino *
7386d7f5d3SJohn Marino * Revision 5.7 1990/12/13 06:54:07 eggert
7486d7f5d3SJohn Marino * GNU diff 1.15 has -u.
7586d7f5d3SJohn Marino *
7686d7f5d3SJohn Marino * Revision 5.6 1990/11/01 05:03:39 eggert
7786d7f5d3SJohn Marino * Remove unneeded setid check.
7886d7f5d3SJohn Marino *
7986d7f5d3SJohn Marino * Revision 5.5 1990/10/04 06:30:19 eggert
8086d7f5d3SJohn Marino * Accumulate exit status across files.
8186d7f5d3SJohn Marino *
8286d7f5d3SJohn Marino * Revision 5.4 1990/09/27 01:31:43 eggert
8386d7f5d3SJohn Marino * Yield 1, not EXIT_FAILURE, when diffs are found.
8486d7f5d3SJohn Marino *
8586d7f5d3SJohn Marino * Revision 5.3 1990/09/11 02:41:11 eggert
8686d7f5d3SJohn Marino * Simplify -kkvl test.
8786d7f5d3SJohn Marino *
8886d7f5d3SJohn Marino * Revision 5.2 1990/09/04 17:07:19 eggert
8986d7f5d3SJohn Marino * Diff's argv was too small by 1.
9086d7f5d3SJohn Marino *
9186d7f5d3SJohn Marino * Revision 5.1 1990/08/29 07:13:55 eggert
9286d7f5d3SJohn Marino * Add -kkvl.
9386d7f5d3SJohn Marino *
9486d7f5d3SJohn Marino * Revision 5.0 1990/08/22 08:12:46 eggert
9586d7f5d3SJohn Marino * Add -k, -V. Don't use access(). Add setuid support.
9686d7f5d3SJohn Marino * Remove compile-time limits; use malloc instead.
9786d7f5d3SJohn Marino * Don't pass arguments with leading '+' to diff; GNU DIFF treats them as options.
9886d7f5d3SJohn Marino * Add GNU diff's flags. Make lock and temp files faster and safer.
9986d7f5d3SJohn Marino * Ansify and Posixate.
10086d7f5d3SJohn Marino *
10186d7f5d3SJohn Marino * Revision 4.6 89/05/01 15:12:27 narten
10286d7f5d3SJohn Marino * changed copyright header to reflect current distribution rules
10386d7f5d3SJohn Marino *
10486d7f5d3SJohn Marino * Revision 4.5 88/08/09 19:12:41 eggert
10586d7f5d3SJohn Marino * Use execv(), not system(); yield exit status like diff(1)s; allow cc -R.
10686d7f5d3SJohn Marino *
10786d7f5d3SJohn Marino * Revision 4.4 87/12/18 11:37:46 narten
10886d7f5d3SJohn Marino * changes Jay Lepreau made in the 4.3 BSD version, to add support for
10986d7f5d3SJohn Marino * "-i", "-w", and "-t" flags and to permit flags to be bundled together,
11086d7f5d3SJohn Marino * merged in.
11186d7f5d3SJohn Marino *
11286d7f5d3SJohn Marino * Revision 4.3 87/10/18 10:31:42 narten
11386d7f5d3SJohn Marino * Updating version numbers. Changes relative to 1.1 actually
11486d7f5d3SJohn Marino * relative to 4.1
11586d7f5d3SJohn Marino *
11686d7f5d3SJohn Marino * Revision 1.3 87/09/24 13:59:21 narten
11786d7f5d3SJohn Marino * Sources now pass through lint (if you ignore printf/sprintf/fprintf
11886d7f5d3SJohn Marino * warnings)
11986d7f5d3SJohn Marino *
12086d7f5d3SJohn Marino * Revision 1.2 87/03/27 14:22:15 jenkins
12186d7f5d3SJohn Marino * Port to suns
12286d7f5d3SJohn Marino *
12386d7f5d3SJohn Marino * Revision 4.1 83/05/03 22:13:19 wft
12486d7f5d3SJohn Marino * Added default branch, option -q, exit status like diff.
12586d7f5d3SJohn Marino * Added fterror() to replace faterror().
12686d7f5d3SJohn Marino *
12786d7f5d3SJohn Marino * Revision 3.6 83/01/15 17:52:40 wft
12886d7f5d3SJohn Marino * Expanded mainprogram to handle multiple RCS files.
12986d7f5d3SJohn Marino *
13086d7f5d3SJohn Marino * Revision 3.5 83/01/06 09:33:45 wft
13186d7f5d3SJohn Marino * Fixed passing of -c (context) option to diff.
13286d7f5d3SJohn Marino *
13386d7f5d3SJohn Marino * Revision 3.4 82/12/24 15:28:38 wft
13486d7f5d3SJohn Marino * Added call to catchsig().
13586d7f5d3SJohn Marino *
13686d7f5d3SJohn Marino * Revision 3.3 82/12/10 16:08:17 wft
13786d7f5d3SJohn Marino * Corrected checking of return code from diff; improved error msgs.
13886d7f5d3SJohn Marino *
13986d7f5d3SJohn Marino * Revision 3.2 82/12/04 13:20:09 wft
14086d7f5d3SJohn Marino * replaced getdelta() with gettree(). Changed diagnostics.
14186d7f5d3SJohn Marino *
14286d7f5d3SJohn Marino * Revision 3.1 82/11/28 19:25:04 wft
14386d7f5d3SJohn Marino * Initial revision.
14486d7f5d3SJohn Marino *
14586d7f5d3SJohn Marino */
14686d7f5d3SJohn Marino #include "rcsbase.h"
14786d7f5d3SJohn Marino
14886d7f5d3SJohn Marino #if DIFF_L
14986d7f5d3SJohn Marino static char const *setup_label P((struct buf*,char const*,char const[datesize]));
15086d7f5d3SJohn Marino #endif
15186d7f5d3SJohn Marino static void cleanup P((void));
15286d7f5d3SJohn Marino
15386d7f5d3SJohn Marino static int exitstatus;
15486d7f5d3SJohn Marino static RILE *workptr;
15586d7f5d3SJohn Marino static struct stat workstat;
15686d7f5d3SJohn Marino
15786d7f5d3SJohn Marino mainProg(rcsdiffId, "rcsdiff", "$DragonFly: src/gnu/usr.bin/rcs/rcsdiff/rcsdiff.c,v 1.2 2003/06/17 04:25:48 dillon Exp $")
15886d7f5d3SJohn Marino {
15986d7f5d3SJohn Marino static char const cmdusage[] =
16086d7f5d3SJohn Marino "\nrcsdiff usage: rcsdiff -ksubst -q -rrev1 [-rrev2] -Vn -xsuff -zzone [diff options] file ...";
16186d7f5d3SJohn Marino
16286d7f5d3SJohn Marino int revnums; /* counter for revision numbers given */
16386d7f5d3SJohn Marino char const *rev1, *rev2; /* revision numbers from command line */
16486d7f5d3SJohn Marino char const *xrev1, *xrev2; /* expanded revision numbers */
16586d7f5d3SJohn Marino char const *expandarg, *lexpandarg, *suffixarg, *versionarg, *zonearg;
16686d7f5d3SJohn Marino #if DIFF_L
16786d7f5d3SJohn Marino static struct buf labelbuf[2];
16886d7f5d3SJohn Marino int file_labels;
16986d7f5d3SJohn Marino char const **diff_label1, **diff_label2;
17086d7f5d3SJohn Marino char date2[datesize];
17186d7f5d3SJohn Marino #endif
17286d7f5d3SJohn Marino char const *cov[10 + !DIFF_L];
17386d7f5d3SJohn Marino char const **diffv, **diffp, **diffpend; /* argv for subsidiary diff */
17486d7f5d3SJohn Marino char const **pp, *p, *diffvstr;
17586d7f5d3SJohn Marino struct buf commarg;
17686d7f5d3SJohn Marino struct buf numericrev; /* expanded revision number */
17786d7f5d3SJohn Marino struct hshentries *gendeltas; /* deltas to be generated */
17886d7f5d3SJohn Marino struct hshentry * target;
17986d7f5d3SJohn Marino char *a, *dcp, **newargv;
18086d7f5d3SJohn Marino int no_diff_means_no_output;
18186d7f5d3SJohn Marino register int c;
18286d7f5d3SJohn Marino
18386d7f5d3SJohn Marino exitstatus = DIFF_SUCCESS;
18486d7f5d3SJohn Marino
18586d7f5d3SJohn Marino bufautobegin(&commarg);
18686d7f5d3SJohn Marino bufautobegin(&numericrev);
18786d7f5d3SJohn Marino revnums = 0;
18886d7f5d3SJohn Marino rev1 = rev2 = xrev2 = 0;
18986d7f5d3SJohn Marino #if DIFF_L
19086d7f5d3SJohn Marino file_labels = 0;
19186d7f5d3SJohn Marino #endif
19286d7f5d3SJohn Marino expandarg = suffixarg = versionarg = zonearg = 0;
19386d7f5d3SJohn Marino no_diff_means_no_output = true;
19486d7f5d3SJohn Marino suffixes = X_DEFAULT;
19586d7f5d3SJohn Marino
19686d7f5d3SJohn Marino /*
19786d7f5d3SJohn Marino * Room for runv extra + args [+ --binary] [+ 2 labels]
19886d7f5d3SJohn Marino * + 1 file + 1 trailing null.
19986d7f5d3SJohn Marino */
20086d7f5d3SJohn Marino diffv = tnalloc(char const*, 1 + argc + !!OPEN_O_BINARY + 2*DIFF_L + 2);
20186d7f5d3SJohn Marino diffp = diffv + 1;
20286d7f5d3SJohn Marino *diffp++ = DIFF;
20386d7f5d3SJohn Marino
20486d7f5d3SJohn Marino argc = getRCSINIT(argc, argv, &newargv);
20586d7f5d3SJohn Marino argv = newargv;
20686d7f5d3SJohn Marino while (a = *++argv, 0<--argc && *a++=='-') {
20786d7f5d3SJohn Marino dcp = a;
20886d7f5d3SJohn Marino while ((c = *a++)) switch (c) {
20986d7f5d3SJohn Marino case 'r':
21086d7f5d3SJohn Marino switch (++revnums) {
21186d7f5d3SJohn Marino case 1: rev1=a; break;
21286d7f5d3SJohn Marino case 2: rev2=a; break;
21386d7f5d3SJohn Marino default: error("too many revision numbers");
21486d7f5d3SJohn Marino }
21586d7f5d3SJohn Marino goto option_handled;
21686d7f5d3SJohn Marino case '-': case 'D':
21786d7f5d3SJohn Marino no_diff_means_no_output = false;
21886d7f5d3SJohn Marino /* fall into */
21986d7f5d3SJohn Marino case 'C': case 'F': case 'I': case 'L': case 'W':
22086d7f5d3SJohn Marino #if DIFF_L
22186d7f5d3SJohn Marino if (c == 'L' && file_labels++ == 2)
22286d7f5d3SJohn Marino faterror("too many -L options");
22386d7f5d3SJohn Marino #endif
22486d7f5d3SJohn Marino *dcp++ = c;
22586d7f5d3SJohn Marino if (*a)
22686d7f5d3SJohn Marino do *dcp++ = *a++;
22786d7f5d3SJohn Marino while (*a);
22886d7f5d3SJohn Marino else {
22986d7f5d3SJohn Marino if (!--argc)
23086d7f5d3SJohn Marino faterror("-%c needs following argument%s",
23186d7f5d3SJohn Marino c, cmdusage
23286d7f5d3SJohn Marino );
23386d7f5d3SJohn Marino *diffp++ = *argv++;
23486d7f5d3SJohn Marino }
23586d7f5d3SJohn Marino break;
23686d7f5d3SJohn Marino case 'y':
23786d7f5d3SJohn Marino no_diff_means_no_output = false;
23886d7f5d3SJohn Marino /* fall into */
23986d7f5d3SJohn Marino case 'B': case 'H':
24086d7f5d3SJohn Marino case '0': case '1': case '2': case '3': case '4':
24186d7f5d3SJohn Marino case '5': case '6': case '7': case '8': case '9':
24286d7f5d3SJohn Marino case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
24386d7f5d3SJohn Marino case 'h': case 'i': case 'n': case 'p':
24486d7f5d3SJohn Marino case 't': case 'u': case 'w':
24586d7f5d3SJohn Marino *dcp++ = c;
24686d7f5d3SJohn Marino break;
24786d7f5d3SJohn Marino case 'q':
24886d7f5d3SJohn Marino quietflag=true;
24986d7f5d3SJohn Marino break;
25086d7f5d3SJohn Marino case 'x':
25186d7f5d3SJohn Marino suffixarg = *argv;
25286d7f5d3SJohn Marino suffixes = *argv + 2;
25386d7f5d3SJohn Marino goto option_handled;
25486d7f5d3SJohn Marino case 'z':
25586d7f5d3SJohn Marino zonearg = *argv;
25686d7f5d3SJohn Marino zone_set(*argv + 2);
25786d7f5d3SJohn Marino goto option_handled;
25886d7f5d3SJohn Marino case 'T':
25986d7f5d3SJohn Marino /* Ignore -T, so that RCSINIT can contain -T. */
26086d7f5d3SJohn Marino if (*a)
26186d7f5d3SJohn Marino goto unknown;
26286d7f5d3SJohn Marino break;
26386d7f5d3SJohn Marino case 'V':
26486d7f5d3SJohn Marino versionarg = *argv;
26586d7f5d3SJohn Marino setRCSversion(versionarg);
26686d7f5d3SJohn Marino goto option_handled;
26786d7f5d3SJohn Marino case 'k':
26886d7f5d3SJohn Marino expandarg = *argv;
26986d7f5d3SJohn Marino if (0 <= str2expmode(expandarg+2))
27086d7f5d3SJohn Marino goto option_handled;
27186d7f5d3SJohn Marino /* fall into */
27286d7f5d3SJohn Marino default:
27386d7f5d3SJohn Marino unknown:
27486d7f5d3SJohn Marino error("unknown option: %s%s", *argv, cmdusage);
27586d7f5d3SJohn Marino };
27686d7f5d3SJohn Marino option_handled:
27786d7f5d3SJohn Marino if (dcp != *argv+1) {
27886d7f5d3SJohn Marino *dcp = 0;
27986d7f5d3SJohn Marino *diffp++ = *argv;
28086d7f5d3SJohn Marino }
28186d7f5d3SJohn Marino } /* end of option processing */
28286d7f5d3SJohn Marino
28386d7f5d3SJohn Marino for (pp = diffv+2, c = 0; pp<diffp; )
28486d7f5d3SJohn Marino c += strlen(*pp++) + 1;
28586d7f5d3SJohn Marino diffvstr = a = tnalloc(char, c + 1);
28686d7f5d3SJohn Marino for (pp = diffv+2; pp<diffp; ) {
28786d7f5d3SJohn Marino p = *pp++;
28886d7f5d3SJohn Marino *a++ = ' ';
28986d7f5d3SJohn Marino while ((*a = *p++))
29086d7f5d3SJohn Marino a++;
29186d7f5d3SJohn Marino }
29286d7f5d3SJohn Marino *a = 0;
29386d7f5d3SJohn Marino
29486d7f5d3SJohn Marino #if DIFF_L
29586d7f5d3SJohn Marino diff_label1 = diff_label2 = 0;
29686d7f5d3SJohn Marino if (file_labels < 2) {
29786d7f5d3SJohn Marino if (!file_labels)
29886d7f5d3SJohn Marino diff_label1 = diffp++;
29986d7f5d3SJohn Marino diff_label2 = diffp++;
30086d7f5d3SJohn Marino }
30186d7f5d3SJohn Marino #endif
30286d7f5d3SJohn Marino diffpend = diffp;
30386d7f5d3SJohn Marino
30486d7f5d3SJohn Marino cov[1] = CO;
30586d7f5d3SJohn Marino cov[2] = "-q";
30686d7f5d3SJohn Marino # if !DIFF_L
30786d7f5d3SJohn Marino cov[3] = "-M";
30886d7f5d3SJohn Marino # endif
30986d7f5d3SJohn Marino
31086d7f5d3SJohn Marino /* Now handle all pathnames. */
31186d7f5d3SJohn Marino if (nerror)
31286d7f5d3SJohn Marino cleanup();
31386d7f5d3SJohn Marino else if (argc < 1)
31486d7f5d3SJohn Marino faterror("no input file%s", cmdusage);
31586d7f5d3SJohn Marino else
31686d7f5d3SJohn Marino for (; 0 < argc; cleanup(), ++argv, --argc) {
31786d7f5d3SJohn Marino ffree();
31886d7f5d3SJohn Marino
31986d7f5d3SJohn Marino if (pairnames(argc, argv, rcsreadopen, true, false) <= 0)
32086d7f5d3SJohn Marino continue;
32186d7f5d3SJohn Marino diagnose("===================================================================\nRCS file: %s\n",RCSname);
32286d7f5d3SJohn Marino if (!rev2) {
32386d7f5d3SJohn Marino /* Make sure work file is readable, and get its status. */
32486d7f5d3SJohn Marino if (!(workptr = Iopen(workname, FOPEN_R_WORK, &workstat))) {
32586d7f5d3SJohn Marino eerror(workname);
32686d7f5d3SJohn Marino continue;
32786d7f5d3SJohn Marino }
32886d7f5d3SJohn Marino }
32986d7f5d3SJohn Marino
33086d7f5d3SJohn Marino
33186d7f5d3SJohn Marino gettree(); /* reads in the delta tree */
33286d7f5d3SJohn Marino
33386d7f5d3SJohn Marino if (!Head) {
33486d7f5d3SJohn Marino rcserror("no revisions present");
33586d7f5d3SJohn Marino continue;
33686d7f5d3SJohn Marino }
33786d7f5d3SJohn Marino if (revnums==0 || !*rev1)
33886d7f5d3SJohn Marino rev1 = Dbranch ? Dbranch : Head->num;
33986d7f5d3SJohn Marino
34086d7f5d3SJohn Marino if (!fexpandsym(rev1, &numericrev, workptr)) continue;
34186d7f5d3SJohn Marino if (!(target=genrevs(numericrev.string,(char *)0,(char *)0,(char *)0,&gendeltas))) continue;
34286d7f5d3SJohn Marino xrev1=target->num;
34386d7f5d3SJohn Marino #if DIFF_L
34486d7f5d3SJohn Marino if (diff_label1)
34586d7f5d3SJohn Marino *diff_label1 = setup_label(&labelbuf[0], target->num, target->date);
34686d7f5d3SJohn Marino #endif
34786d7f5d3SJohn Marino
34886d7f5d3SJohn Marino lexpandarg = expandarg;
34986d7f5d3SJohn Marino if (revnums==2) {
35086d7f5d3SJohn Marino if (!fexpandsym(
35186d7f5d3SJohn Marino *rev2 ? rev2 : Dbranch ? Dbranch : Head->num,
35286d7f5d3SJohn Marino &numericrev,
35386d7f5d3SJohn Marino workptr
35486d7f5d3SJohn Marino ))
35586d7f5d3SJohn Marino continue;
35686d7f5d3SJohn Marino if (!(target=genrevs(numericrev.string,(char *)0,(char *)0,(char *)0,&gendeltas))) continue;
35786d7f5d3SJohn Marino xrev2=target->num;
35886d7f5d3SJohn Marino if (no_diff_means_no_output && xrev1 == xrev2)
35986d7f5d3SJohn Marino continue;
36086d7f5d3SJohn Marino } else if (
36186d7f5d3SJohn Marino target->lockedby
36286d7f5d3SJohn Marino && !lexpandarg
36386d7f5d3SJohn Marino && Expand == KEYVAL_EXPAND
36486d7f5d3SJohn Marino && WORKMODE(RCSstat.st_mode,true) == workstat.st_mode
36586d7f5d3SJohn Marino )
36686d7f5d3SJohn Marino lexpandarg = "-kkvl";
36786d7f5d3SJohn Marino Izclose(&workptr);
36886d7f5d3SJohn Marino #if DIFF_L
36986d7f5d3SJohn Marino if (diff_label2) {
37086d7f5d3SJohn Marino if (revnums == 2)
37186d7f5d3SJohn Marino *diff_label2 = setup_label(&labelbuf[1], target->num, target->date);
37286d7f5d3SJohn Marino else {
37386d7f5d3SJohn Marino time2date(workstat.st_mtime, date2);
37486d7f5d3SJohn Marino *diff_label2 = setup_label(&labelbuf[1], (char*)0, date2);
37586d7f5d3SJohn Marino }
37686d7f5d3SJohn Marino }
37786d7f5d3SJohn Marino #endif
37886d7f5d3SJohn Marino
37986d7f5d3SJohn Marino diagnose("retrieving revision %s\n", xrev1);
38086d7f5d3SJohn Marino bufscpy(&commarg, "-p");
38186d7f5d3SJohn Marino bufscat(&commarg, rev1); /* not xrev1, for $Name's sake */
38286d7f5d3SJohn Marino
38386d7f5d3SJohn Marino pp = &cov[3 + !DIFF_L];
38486d7f5d3SJohn Marino *pp++ = commarg.string;
38586d7f5d3SJohn Marino if (lexpandarg) *pp++ = lexpandarg;
38686d7f5d3SJohn Marino if (suffixarg) *pp++ = suffixarg;
38786d7f5d3SJohn Marino if (versionarg) *pp++ = versionarg;
38886d7f5d3SJohn Marino if (zonearg) *pp++ = zonearg;
38986d7f5d3SJohn Marino *pp++ = RCSname;
39086d7f5d3SJohn Marino *pp = 0;
39186d7f5d3SJohn Marino
39286d7f5d3SJohn Marino diffp = diffpend;
39386d7f5d3SJohn Marino # if OPEN_O_BINARY
39486d7f5d3SJohn Marino if (Expand == BINARY_EXPAND)
39586d7f5d3SJohn Marino *diffp++ = "--binary";
39686d7f5d3SJohn Marino # endif
39786d7f5d3SJohn Marino diffp[0] = maketemp(0);
39886d7f5d3SJohn Marino if (runv(-1, diffp[0], cov)) {
39986d7f5d3SJohn Marino rcserror("co failed");
40086d7f5d3SJohn Marino continue;
40186d7f5d3SJohn Marino }
40286d7f5d3SJohn Marino if (!rev2) {
40386d7f5d3SJohn Marino diffp[1] = workname;
40486d7f5d3SJohn Marino if (*workname == '-') {
40586d7f5d3SJohn Marino char *dp = ftnalloc(char, strlen(workname)+3);
40686d7f5d3SJohn Marino diffp[1] = dp;
40786d7f5d3SJohn Marino *dp++ = '.';
40886d7f5d3SJohn Marino *dp++ = SLASH;
40986d7f5d3SJohn Marino VOID strcpy(dp, workname);
41086d7f5d3SJohn Marino }
41186d7f5d3SJohn Marino } else {
41286d7f5d3SJohn Marino diagnose("retrieving revision %s\n",xrev2);
41386d7f5d3SJohn Marino bufscpy(&commarg, "-p");
41486d7f5d3SJohn Marino bufscat(&commarg, rev2); /* not xrev2, for $Name's sake */
41586d7f5d3SJohn Marino cov[3 + !DIFF_L] = commarg.string;
41686d7f5d3SJohn Marino diffp[1] = maketemp(1);
41786d7f5d3SJohn Marino if (runv(-1, diffp[1], cov)) {
41886d7f5d3SJohn Marino rcserror("co failed");
41986d7f5d3SJohn Marino continue;
42086d7f5d3SJohn Marino }
42186d7f5d3SJohn Marino }
42286d7f5d3SJohn Marino if (!rev2)
42386d7f5d3SJohn Marino diagnose("diff%s -r%s %s\n", diffvstr, xrev1, workname);
42486d7f5d3SJohn Marino else
42586d7f5d3SJohn Marino diagnose("diff%s -r%s -r%s\n", diffvstr, xrev1, xrev2);
42686d7f5d3SJohn Marino
42786d7f5d3SJohn Marino diffp[2] = 0;
42886d7f5d3SJohn Marino switch (runv(-1, (char*)0, diffv)) {
42986d7f5d3SJohn Marino case DIFF_SUCCESS:
43086d7f5d3SJohn Marino break;
43186d7f5d3SJohn Marino case DIFF_FAILURE:
43286d7f5d3SJohn Marino if (exitstatus == DIFF_SUCCESS)
43386d7f5d3SJohn Marino exitstatus = DIFF_FAILURE;
43486d7f5d3SJohn Marino break;
43586d7f5d3SJohn Marino default:
43686d7f5d3SJohn Marino workerror("diff failed");
43786d7f5d3SJohn Marino }
43886d7f5d3SJohn Marino }
43986d7f5d3SJohn Marino
44086d7f5d3SJohn Marino tempunlink();
44186d7f5d3SJohn Marino exitmain(exitstatus);
44286d7f5d3SJohn Marino }
44386d7f5d3SJohn Marino
44486d7f5d3SJohn Marino static void
cleanup()44586d7f5d3SJohn Marino cleanup()
44686d7f5d3SJohn Marino {
44786d7f5d3SJohn Marino if (nerror) exitstatus = DIFF_TROUBLE;
44886d7f5d3SJohn Marino Izclose(&finptr);
44986d7f5d3SJohn Marino Izclose(&workptr);
45086d7f5d3SJohn Marino }
45186d7f5d3SJohn Marino
45286d7f5d3SJohn Marino #if RCS_lint
45386d7f5d3SJohn Marino # define exiterr rdiffExit
45486d7f5d3SJohn Marino #endif
45586d7f5d3SJohn Marino void
exiterr()45686d7f5d3SJohn Marino exiterr()
45786d7f5d3SJohn Marino {
45886d7f5d3SJohn Marino tempunlink();
45986d7f5d3SJohn Marino _exit(DIFF_TROUBLE);
46086d7f5d3SJohn Marino }
46186d7f5d3SJohn Marino
46286d7f5d3SJohn Marino #if DIFF_L
46386d7f5d3SJohn Marino static char const *
setup_label(b,num,date)46486d7f5d3SJohn Marino setup_label(b, num, date)
46586d7f5d3SJohn Marino struct buf *b;
46686d7f5d3SJohn Marino char const *num;
46786d7f5d3SJohn Marino char const date[datesize];
46886d7f5d3SJohn Marino {
46986d7f5d3SJohn Marino char *p;
47086d7f5d3SJohn Marino char datestr[datesize + zonelenmax];
47186d7f5d3SJohn Marino VOID date2str(date, datestr);
47286d7f5d3SJohn Marino bufalloc(b,
47386d7f5d3SJohn Marino strlen(workname)
47486d7f5d3SJohn Marino + sizeof datestr + 4
47586d7f5d3SJohn Marino + (num ? strlen(num) : 0)
47686d7f5d3SJohn Marino );
47786d7f5d3SJohn Marino p = b->string;
47886d7f5d3SJohn Marino if (num)
47986d7f5d3SJohn Marino VOID sprintf(p, "-L%s\t%s\t%s", workname, datestr, num);
48086d7f5d3SJohn Marino else
48186d7f5d3SJohn Marino VOID sprintf(p, "-L%s\t%s", workname, datestr);
48286d7f5d3SJohn Marino return p;
48386d7f5d3SJohn Marino }
48486d7f5d3SJohn Marino #endif
485