1*86d7f5d3SJohn Marino /* Compare RCS revisions. */
2*86d7f5d3SJohn Marino
3*86d7f5d3SJohn Marino /* Copyright 1982, 1988, 1989 Walter Tichy
4*86d7f5d3SJohn Marino Copyright 1990, 1991, 1992, 1993, 1994, 1995 Paul Eggert
5*86d7f5d3SJohn Marino Distributed under license by the Free Software Foundation, Inc.
6*86d7f5d3SJohn Marino
7*86d7f5d3SJohn Marino This file is part of RCS.
8*86d7f5d3SJohn Marino
9*86d7f5d3SJohn Marino RCS is free software; you can redistribute it and/or modify
10*86d7f5d3SJohn Marino it under the terms of the GNU General Public License as published by
11*86d7f5d3SJohn Marino the Free Software Foundation; either version 2, or (at your option)
12*86d7f5d3SJohn Marino any later version.
13*86d7f5d3SJohn Marino
14*86d7f5d3SJohn Marino RCS is distributed in the hope that it will be useful,
15*86d7f5d3SJohn Marino but WITHOUT ANY WARRANTY; without even the implied warranty of
16*86d7f5d3SJohn Marino MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17*86d7f5d3SJohn Marino GNU General Public License for more details.
18*86d7f5d3SJohn Marino
19*86d7f5d3SJohn Marino You should have received a copy of the GNU General Public License
20*86d7f5d3SJohn Marino along with RCS; see the file COPYING.
21*86d7f5d3SJohn Marino If not, write to the Free Software Foundation,
22*86d7f5d3SJohn Marino 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23*86d7f5d3SJohn Marino
24*86d7f5d3SJohn Marino Report problems and direct all questions to:
25*86d7f5d3SJohn Marino
26*86d7f5d3SJohn Marino rcs-bugs@cs.purdue.edu
27*86d7f5d3SJohn Marino
28*86d7f5d3SJohn Marino */
29*86d7f5d3SJohn Marino
30*86d7f5d3SJohn Marino /*
31*86d7f5d3SJohn Marino * $FreeBSD: src/gnu/usr.bin/rcs/rcsdiff/rcsdiff.c,v 1.8 1999/08/27 23:36:55 peter Exp $
32*86d7f5d3SJohn Marino * $DragonFly: src/gnu/usr.bin/rcs/rcsdiff/rcsdiff.c,v 1.2 2003/06/17 04:25:48 dillon Exp $
33*86d7f5d3SJohn Marino *
34*86d7f5d3SJohn Marino * Revision 5.19 1995/06/16 06:19:24 eggert
35*86d7f5d3SJohn Marino * Update FSF address.
36*86d7f5d3SJohn Marino *
37*86d7f5d3SJohn Marino * Revision 5.18 1995/06/01 16:23:43 eggert
38*86d7f5d3SJohn Marino * (main): Pass "--binary" if -kb and if --binary makes a difference.
39*86d7f5d3SJohn Marino * Don't treat + options specially.
40*86d7f5d3SJohn Marino *
41*86d7f5d3SJohn Marino * Revision 5.17 1994/03/17 14:05:48 eggert
42*86d7f5d3SJohn Marino * Specify subprocess input via file descriptor, not file name. Remove lint.
43*86d7f5d3SJohn Marino *
44*86d7f5d3SJohn Marino * Revision 5.16 1993/11/09 17:40:15 eggert
45*86d7f5d3SJohn Marino * -V now prints version on stdout and exits. Don't print usage twice.
46*86d7f5d3SJohn Marino *
47*86d7f5d3SJohn Marino * Revision 5.15 1993/11/03 17:42:27 eggert
48*86d7f5d3SJohn Marino * Add -z. Ignore -T. Pass -Vn to `co'. Add Name keyword.
49*86d7f5d3SJohn Marino * Put revision numbers in -c output. Improve quality of diagnostics.
50*86d7f5d3SJohn Marino *
51*86d7f5d3SJohn Marino * Revision 5.14 1992/07/28 16:12:44 eggert
52*86d7f5d3SJohn Marino * Add -V. Use co -M for better dates with traditional diff -c.
53*86d7f5d3SJohn Marino *
54*86d7f5d3SJohn Marino * Revision 5.13 1992/02/17 23:02:23 eggert
55*86d7f5d3SJohn Marino * Output more readable context diff headers.
56*86d7f5d3SJohn Marino * Suppress needless checkout and comparison of identical revisions.
57*86d7f5d3SJohn Marino *
58*86d7f5d3SJohn Marino * Revision 5.12 1992/01/24 18:44:19 eggert
59*86d7f5d3SJohn Marino * Add GNU diff 1.15.2's new options. lint -> RCS_lint
60*86d7f5d3SJohn Marino *
61*86d7f5d3SJohn Marino * Revision 5.11 1992/01/06 02:42:34 eggert
62*86d7f5d3SJohn Marino * Update usage string.
63*86d7f5d3SJohn Marino *
64*86d7f5d3SJohn Marino * Revision 5.10 1991/10/07 17:32:46 eggert
65*86d7f5d3SJohn Marino * Remove lint.
66*86d7f5d3SJohn Marino *
67*86d7f5d3SJohn Marino * Revision 5.9 1991/08/19 03:13:55 eggert
68*86d7f5d3SJohn Marino * Add RCSINIT, -r$. Tune.
69*86d7f5d3SJohn Marino *
70*86d7f5d3SJohn Marino * Revision 5.8 1991/04/21 11:58:21 eggert
71*86d7f5d3SJohn Marino * Add -x, RCSINIT, MS-DOS support.
72*86d7f5d3SJohn Marino *
73*86d7f5d3SJohn Marino * Revision 5.7 1990/12/13 06:54:07 eggert
74*86d7f5d3SJohn Marino * GNU diff 1.15 has -u.
75*86d7f5d3SJohn Marino *
76*86d7f5d3SJohn Marino * Revision 5.6 1990/11/01 05:03:39 eggert
77*86d7f5d3SJohn Marino * Remove unneeded setid check.
78*86d7f5d3SJohn Marino *
79*86d7f5d3SJohn Marino * Revision 5.5 1990/10/04 06:30:19 eggert
80*86d7f5d3SJohn Marino * Accumulate exit status across files.
81*86d7f5d3SJohn Marino *
82*86d7f5d3SJohn Marino * Revision 5.4 1990/09/27 01:31:43 eggert
83*86d7f5d3SJohn Marino * Yield 1, not EXIT_FAILURE, when diffs are found.
84*86d7f5d3SJohn Marino *
85*86d7f5d3SJohn Marino * Revision 5.3 1990/09/11 02:41:11 eggert
86*86d7f5d3SJohn Marino * Simplify -kkvl test.
87*86d7f5d3SJohn Marino *
88*86d7f5d3SJohn Marino * Revision 5.2 1990/09/04 17:07:19 eggert
89*86d7f5d3SJohn Marino * Diff's argv was too small by 1.
90*86d7f5d3SJohn Marino *
91*86d7f5d3SJohn Marino * Revision 5.1 1990/08/29 07:13:55 eggert
92*86d7f5d3SJohn Marino * Add -kkvl.
93*86d7f5d3SJohn Marino *
94*86d7f5d3SJohn Marino * Revision 5.0 1990/08/22 08:12:46 eggert
95*86d7f5d3SJohn Marino * Add -k, -V. Don't use access(). Add setuid support.
96*86d7f5d3SJohn Marino * Remove compile-time limits; use malloc instead.
97*86d7f5d3SJohn Marino * Don't pass arguments with leading '+' to diff; GNU DIFF treats them as options.
98*86d7f5d3SJohn Marino * Add GNU diff's flags. Make lock and temp files faster and safer.
99*86d7f5d3SJohn Marino * Ansify and Posixate.
100*86d7f5d3SJohn Marino *
101*86d7f5d3SJohn Marino * Revision 4.6 89/05/01 15:12:27 narten
102*86d7f5d3SJohn Marino * changed copyright header to reflect current distribution rules
103*86d7f5d3SJohn Marino *
104*86d7f5d3SJohn Marino * Revision 4.5 88/08/09 19:12:41 eggert
105*86d7f5d3SJohn Marino * Use execv(), not system(); yield exit status like diff(1)s; allow cc -R.
106*86d7f5d3SJohn Marino *
107*86d7f5d3SJohn Marino * Revision 4.4 87/12/18 11:37:46 narten
108*86d7f5d3SJohn Marino * changes Jay Lepreau made in the 4.3 BSD version, to add support for
109*86d7f5d3SJohn Marino * "-i", "-w", and "-t" flags and to permit flags to be bundled together,
110*86d7f5d3SJohn Marino * merged in.
111*86d7f5d3SJohn Marino *
112*86d7f5d3SJohn Marino * Revision 4.3 87/10/18 10:31:42 narten
113*86d7f5d3SJohn Marino * Updating version numbers. Changes relative to 1.1 actually
114*86d7f5d3SJohn Marino * relative to 4.1
115*86d7f5d3SJohn Marino *
116*86d7f5d3SJohn Marino * Revision 1.3 87/09/24 13:59:21 narten
117*86d7f5d3SJohn Marino * Sources now pass through lint (if you ignore printf/sprintf/fprintf
118*86d7f5d3SJohn Marino * warnings)
119*86d7f5d3SJohn Marino *
120*86d7f5d3SJohn Marino * Revision 1.2 87/03/27 14:22:15 jenkins
121*86d7f5d3SJohn Marino * Port to suns
122*86d7f5d3SJohn Marino *
123*86d7f5d3SJohn Marino * Revision 4.1 83/05/03 22:13:19 wft
124*86d7f5d3SJohn Marino * Added default branch, option -q, exit status like diff.
125*86d7f5d3SJohn Marino * Added fterror() to replace faterror().
126*86d7f5d3SJohn Marino *
127*86d7f5d3SJohn Marino * Revision 3.6 83/01/15 17:52:40 wft
128*86d7f5d3SJohn Marino * Expanded mainprogram to handle multiple RCS files.
129*86d7f5d3SJohn Marino *
130*86d7f5d3SJohn Marino * Revision 3.5 83/01/06 09:33:45 wft
131*86d7f5d3SJohn Marino * Fixed passing of -c (context) option to diff.
132*86d7f5d3SJohn Marino *
133*86d7f5d3SJohn Marino * Revision 3.4 82/12/24 15:28:38 wft
134*86d7f5d3SJohn Marino * Added call to catchsig().
135*86d7f5d3SJohn Marino *
136*86d7f5d3SJohn Marino * Revision 3.3 82/12/10 16:08:17 wft
137*86d7f5d3SJohn Marino * Corrected checking of return code from diff; improved error msgs.
138*86d7f5d3SJohn Marino *
139*86d7f5d3SJohn Marino * Revision 3.2 82/12/04 13:20:09 wft
140*86d7f5d3SJohn Marino * replaced getdelta() with gettree(). Changed diagnostics.
141*86d7f5d3SJohn Marino *
142*86d7f5d3SJohn Marino * Revision 3.1 82/11/28 19:25:04 wft
143*86d7f5d3SJohn Marino * Initial revision.
144*86d7f5d3SJohn Marino *
145*86d7f5d3SJohn Marino */
146*86d7f5d3SJohn Marino #include "rcsbase.h"
147*86d7f5d3SJohn Marino
148*86d7f5d3SJohn Marino #if DIFF_L
149*86d7f5d3SJohn Marino static char const *setup_label P((struct buf*,char const*,char const[datesize]));
150*86d7f5d3SJohn Marino #endif
151*86d7f5d3SJohn Marino static void cleanup P((void));
152*86d7f5d3SJohn Marino
153*86d7f5d3SJohn Marino static int exitstatus;
154*86d7f5d3SJohn Marino static RILE *workptr;
155*86d7f5d3SJohn Marino static struct stat workstat;
156*86d7f5d3SJohn Marino
157*86d7f5d3SJohn Marino mainProg(rcsdiffId, "rcsdiff", "$DragonFly: src/gnu/usr.bin/rcs/rcsdiff/rcsdiff.c,v 1.2 2003/06/17 04:25:48 dillon Exp $")
158*86d7f5d3SJohn Marino {
159*86d7f5d3SJohn Marino static char const cmdusage[] =
160*86d7f5d3SJohn Marino "\nrcsdiff usage: rcsdiff -ksubst -q -rrev1 [-rrev2] -Vn -xsuff -zzone [diff options] file ...";
161*86d7f5d3SJohn Marino
162*86d7f5d3SJohn Marino int revnums; /* counter for revision numbers given */
163*86d7f5d3SJohn Marino char const *rev1, *rev2; /* revision numbers from command line */
164*86d7f5d3SJohn Marino char const *xrev1, *xrev2; /* expanded revision numbers */
165*86d7f5d3SJohn Marino char const *expandarg, *lexpandarg, *suffixarg, *versionarg, *zonearg;
166*86d7f5d3SJohn Marino #if DIFF_L
167*86d7f5d3SJohn Marino static struct buf labelbuf[2];
168*86d7f5d3SJohn Marino int file_labels;
169*86d7f5d3SJohn Marino char const **diff_label1, **diff_label2;
170*86d7f5d3SJohn Marino char date2[datesize];
171*86d7f5d3SJohn Marino #endif
172*86d7f5d3SJohn Marino char const *cov[10 + !DIFF_L];
173*86d7f5d3SJohn Marino char const **diffv, **diffp, **diffpend; /* argv for subsidiary diff */
174*86d7f5d3SJohn Marino char const **pp, *p, *diffvstr;
175*86d7f5d3SJohn Marino struct buf commarg;
176*86d7f5d3SJohn Marino struct buf numericrev; /* expanded revision number */
177*86d7f5d3SJohn Marino struct hshentries *gendeltas; /* deltas to be generated */
178*86d7f5d3SJohn Marino struct hshentry * target;
179*86d7f5d3SJohn Marino char *a, *dcp, **newargv;
180*86d7f5d3SJohn Marino int no_diff_means_no_output;
181*86d7f5d3SJohn Marino register int c;
182*86d7f5d3SJohn Marino
183*86d7f5d3SJohn Marino exitstatus = DIFF_SUCCESS;
184*86d7f5d3SJohn Marino
185*86d7f5d3SJohn Marino bufautobegin(&commarg);
186*86d7f5d3SJohn Marino bufautobegin(&numericrev);
187*86d7f5d3SJohn Marino revnums = 0;
188*86d7f5d3SJohn Marino rev1 = rev2 = xrev2 = 0;
189*86d7f5d3SJohn Marino #if DIFF_L
190*86d7f5d3SJohn Marino file_labels = 0;
191*86d7f5d3SJohn Marino #endif
192*86d7f5d3SJohn Marino expandarg = suffixarg = versionarg = zonearg = 0;
193*86d7f5d3SJohn Marino no_diff_means_no_output = true;
194*86d7f5d3SJohn Marino suffixes = X_DEFAULT;
195*86d7f5d3SJohn Marino
196*86d7f5d3SJohn Marino /*
197*86d7f5d3SJohn Marino * Room for runv extra + args [+ --binary] [+ 2 labels]
198*86d7f5d3SJohn Marino * + 1 file + 1 trailing null.
199*86d7f5d3SJohn Marino */
200*86d7f5d3SJohn Marino diffv = tnalloc(char const*, 1 + argc + !!OPEN_O_BINARY + 2*DIFF_L + 2);
201*86d7f5d3SJohn Marino diffp = diffv + 1;
202*86d7f5d3SJohn Marino *diffp++ = DIFF;
203*86d7f5d3SJohn Marino
204*86d7f5d3SJohn Marino argc = getRCSINIT(argc, argv, &newargv);
205*86d7f5d3SJohn Marino argv = newargv;
206*86d7f5d3SJohn Marino while (a = *++argv, 0<--argc && *a++=='-') {
207*86d7f5d3SJohn Marino dcp = a;
208*86d7f5d3SJohn Marino while ((c = *a++)) switch (c) {
209*86d7f5d3SJohn Marino case 'r':
210*86d7f5d3SJohn Marino switch (++revnums) {
211*86d7f5d3SJohn Marino case 1: rev1=a; break;
212*86d7f5d3SJohn Marino case 2: rev2=a; break;
213*86d7f5d3SJohn Marino default: error("too many revision numbers");
214*86d7f5d3SJohn Marino }
215*86d7f5d3SJohn Marino goto option_handled;
216*86d7f5d3SJohn Marino case '-': case 'D':
217*86d7f5d3SJohn Marino no_diff_means_no_output = false;
218*86d7f5d3SJohn Marino /* fall into */
219*86d7f5d3SJohn Marino case 'C': case 'F': case 'I': case 'L': case 'W':
220*86d7f5d3SJohn Marino #if DIFF_L
221*86d7f5d3SJohn Marino if (c == 'L' && file_labels++ == 2)
222*86d7f5d3SJohn Marino faterror("too many -L options");
223*86d7f5d3SJohn Marino #endif
224*86d7f5d3SJohn Marino *dcp++ = c;
225*86d7f5d3SJohn Marino if (*a)
226*86d7f5d3SJohn Marino do *dcp++ = *a++;
227*86d7f5d3SJohn Marino while (*a);
228*86d7f5d3SJohn Marino else {
229*86d7f5d3SJohn Marino if (!--argc)
230*86d7f5d3SJohn Marino faterror("-%c needs following argument%s",
231*86d7f5d3SJohn Marino c, cmdusage
232*86d7f5d3SJohn Marino );
233*86d7f5d3SJohn Marino *diffp++ = *argv++;
234*86d7f5d3SJohn Marino }
235*86d7f5d3SJohn Marino break;
236*86d7f5d3SJohn Marino case 'y':
237*86d7f5d3SJohn Marino no_diff_means_no_output = false;
238*86d7f5d3SJohn Marino /* fall into */
239*86d7f5d3SJohn Marino case 'B': case 'H':
240*86d7f5d3SJohn Marino case '0': case '1': case '2': case '3': case '4':
241*86d7f5d3SJohn Marino case '5': case '6': case '7': case '8': case '9':
242*86d7f5d3SJohn Marino case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
243*86d7f5d3SJohn Marino case 'h': case 'i': case 'n': case 'p':
244*86d7f5d3SJohn Marino case 't': case 'u': case 'w':
245*86d7f5d3SJohn Marino *dcp++ = c;
246*86d7f5d3SJohn Marino break;
247*86d7f5d3SJohn Marino case 'q':
248*86d7f5d3SJohn Marino quietflag=true;
249*86d7f5d3SJohn Marino break;
250*86d7f5d3SJohn Marino case 'x':
251*86d7f5d3SJohn Marino suffixarg = *argv;
252*86d7f5d3SJohn Marino suffixes = *argv + 2;
253*86d7f5d3SJohn Marino goto option_handled;
254*86d7f5d3SJohn Marino case 'z':
255*86d7f5d3SJohn Marino zonearg = *argv;
256*86d7f5d3SJohn Marino zone_set(*argv + 2);
257*86d7f5d3SJohn Marino goto option_handled;
258*86d7f5d3SJohn Marino case 'T':
259*86d7f5d3SJohn Marino /* Ignore -T, so that RCSINIT can contain -T. */
260*86d7f5d3SJohn Marino if (*a)
261*86d7f5d3SJohn Marino goto unknown;
262*86d7f5d3SJohn Marino break;
263*86d7f5d3SJohn Marino case 'V':
264*86d7f5d3SJohn Marino versionarg = *argv;
265*86d7f5d3SJohn Marino setRCSversion(versionarg);
266*86d7f5d3SJohn Marino goto option_handled;
267*86d7f5d3SJohn Marino case 'k':
268*86d7f5d3SJohn Marino expandarg = *argv;
269*86d7f5d3SJohn Marino if (0 <= str2expmode(expandarg+2))
270*86d7f5d3SJohn Marino goto option_handled;
271*86d7f5d3SJohn Marino /* fall into */
272*86d7f5d3SJohn Marino default:
273*86d7f5d3SJohn Marino unknown:
274*86d7f5d3SJohn Marino error("unknown option: %s%s", *argv, cmdusage);
275*86d7f5d3SJohn Marino };
276*86d7f5d3SJohn Marino option_handled:
277*86d7f5d3SJohn Marino if (dcp != *argv+1) {
278*86d7f5d3SJohn Marino *dcp = 0;
279*86d7f5d3SJohn Marino *diffp++ = *argv;
280*86d7f5d3SJohn Marino }
281*86d7f5d3SJohn Marino } /* end of option processing */
282*86d7f5d3SJohn Marino
283*86d7f5d3SJohn Marino for (pp = diffv+2, c = 0; pp<diffp; )
284*86d7f5d3SJohn Marino c += strlen(*pp++) + 1;
285*86d7f5d3SJohn Marino diffvstr = a = tnalloc(char, c + 1);
286*86d7f5d3SJohn Marino for (pp = diffv+2; pp<diffp; ) {
287*86d7f5d3SJohn Marino p = *pp++;
288*86d7f5d3SJohn Marino *a++ = ' ';
289*86d7f5d3SJohn Marino while ((*a = *p++))
290*86d7f5d3SJohn Marino a++;
291*86d7f5d3SJohn Marino }
292*86d7f5d3SJohn Marino *a = 0;
293*86d7f5d3SJohn Marino
294*86d7f5d3SJohn Marino #if DIFF_L
295*86d7f5d3SJohn Marino diff_label1 = diff_label2 = 0;
296*86d7f5d3SJohn Marino if (file_labels < 2) {
297*86d7f5d3SJohn Marino if (!file_labels)
298*86d7f5d3SJohn Marino diff_label1 = diffp++;
299*86d7f5d3SJohn Marino diff_label2 = diffp++;
300*86d7f5d3SJohn Marino }
301*86d7f5d3SJohn Marino #endif
302*86d7f5d3SJohn Marino diffpend = diffp;
303*86d7f5d3SJohn Marino
304*86d7f5d3SJohn Marino cov[1] = CO;
305*86d7f5d3SJohn Marino cov[2] = "-q";
306*86d7f5d3SJohn Marino # if !DIFF_L
307*86d7f5d3SJohn Marino cov[3] = "-M";
308*86d7f5d3SJohn Marino # endif
309*86d7f5d3SJohn Marino
310*86d7f5d3SJohn Marino /* Now handle all pathnames. */
311*86d7f5d3SJohn Marino if (nerror)
312*86d7f5d3SJohn Marino cleanup();
313*86d7f5d3SJohn Marino else if (argc < 1)
314*86d7f5d3SJohn Marino faterror("no input file%s", cmdusage);
315*86d7f5d3SJohn Marino else
316*86d7f5d3SJohn Marino for (; 0 < argc; cleanup(), ++argv, --argc) {
317*86d7f5d3SJohn Marino ffree();
318*86d7f5d3SJohn Marino
319*86d7f5d3SJohn Marino if (pairnames(argc, argv, rcsreadopen, true, false) <= 0)
320*86d7f5d3SJohn Marino continue;
321*86d7f5d3SJohn Marino diagnose("===================================================================\nRCS file: %s\n",RCSname);
322*86d7f5d3SJohn Marino if (!rev2) {
323*86d7f5d3SJohn Marino /* Make sure work file is readable, and get its status. */
324*86d7f5d3SJohn Marino if (!(workptr = Iopen(workname, FOPEN_R_WORK, &workstat))) {
325*86d7f5d3SJohn Marino eerror(workname);
326*86d7f5d3SJohn Marino continue;
327*86d7f5d3SJohn Marino }
328*86d7f5d3SJohn Marino }
329*86d7f5d3SJohn Marino
330*86d7f5d3SJohn Marino
331*86d7f5d3SJohn Marino gettree(); /* reads in the delta tree */
332*86d7f5d3SJohn Marino
333*86d7f5d3SJohn Marino if (!Head) {
334*86d7f5d3SJohn Marino rcserror("no revisions present");
335*86d7f5d3SJohn Marino continue;
336*86d7f5d3SJohn Marino }
337*86d7f5d3SJohn Marino if (revnums==0 || !*rev1)
338*86d7f5d3SJohn Marino rev1 = Dbranch ? Dbranch : Head->num;
339*86d7f5d3SJohn Marino
340*86d7f5d3SJohn Marino if (!fexpandsym(rev1, &numericrev, workptr)) continue;
341*86d7f5d3SJohn Marino if (!(target=genrevs(numericrev.string,(char *)0,(char *)0,(char *)0,&gendeltas))) continue;
342*86d7f5d3SJohn Marino xrev1=target->num;
343*86d7f5d3SJohn Marino #if DIFF_L
344*86d7f5d3SJohn Marino if (diff_label1)
345*86d7f5d3SJohn Marino *diff_label1 = setup_label(&labelbuf[0], target->num, target->date);
346*86d7f5d3SJohn Marino #endif
347*86d7f5d3SJohn Marino
348*86d7f5d3SJohn Marino lexpandarg = expandarg;
349*86d7f5d3SJohn Marino if (revnums==2) {
350*86d7f5d3SJohn Marino if (!fexpandsym(
351*86d7f5d3SJohn Marino *rev2 ? rev2 : Dbranch ? Dbranch : Head->num,
352*86d7f5d3SJohn Marino &numericrev,
353*86d7f5d3SJohn Marino workptr
354*86d7f5d3SJohn Marino ))
355*86d7f5d3SJohn Marino continue;
356*86d7f5d3SJohn Marino if (!(target=genrevs(numericrev.string,(char *)0,(char *)0,(char *)0,&gendeltas))) continue;
357*86d7f5d3SJohn Marino xrev2=target->num;
358*86d7f5d3SJohn Marino if (no_diff_means_no_output && xrev1 == xrev2)
359*86d7f5d3SJohn Marino continue;
360*86d7f5d3SJohn Marino } else if (
361*86d7f5d3SJohn Marino target->lockedby
362*86d7f5d3SJohn Marino && !lexpandarg
363*86d7f5d3SJohn Marino && Expand == KEYVAL_EXPAND
364*86d7f5d3SJohn Marino && WORKMODE(RCSstat.st_mode,true) == workstat.st_mode
365*86d7f5d3SJohn Marino )
366*86d7f5d3SJohn Marino lexpandarg = "-kkvl";
367*86d7f5d3SJohn Marino Izclose(&workptr);
368*86d7f5d3SJohn Marino #if DIFF_L
369*86d7f5d3SJohn Marino if (diff_label2) {
370*86d7f5d3SJohn Marino if (revnums == 2)
371*86d7f5d3SJohn Marino *diff_label2 = setup_label(&labelbuf[1], target->num, target->date);
372*86d7f5d3SJohn Marino else {
373*86d7f5d3SJohn Marino time2date(workstat.st_mtime, date2);
374*86d7f5d3SJohn Marino *diff_label2 = setup_label(&labelbuf[1], (char*)0, date2);
375*86d7f5d3SJohn Marino }
376*86d7f5d3SJohn Marino }
377*86d7f5d3SJohn Marino #endif
378*86d7f5d3SJohn Marino
379*86d7f5d3SJohn Marino diagnose("retrieving revision %s\n", xrev1);
380*86d7f5d3SJohn Marino bufscpy(&commarg, "-p");
381*86d7f5d3SJohn Marino bufscat(&commarg, rev1); /* not xrev1, for $Name's sake */
382*86d7f5d3SJohn Marino
383*86d7f5d3SJohn Marino pp = &cov[3 + !DIFF_L];
384*86d7f5d3SJohn Marino *pp++ = commarg.string;
385*86d7f5d3SJohn Marino if (lexpandarg) *pp++ = lexpandarg;
386*86d7f5d3SJohn Marino if (suffixarg) *pp++ = suffixarg;
387*86d7f5d3SJohn Marino if (versionarg) *pp++ = versionarg;
388*86d7f5d3SJohn Marino if (zonearg) *pp++ = zonearg;
389*86d7f5d3SJohn Marino *pp++ = RCSname;
390*86d7f5d3SJohn Marino *pp = 0;
391*86d7f5d3SJohn Marino
392*86d7f5d3SJohn Marino diffp = diffpend;
393*86d7f5d3SJohn Marino # if OPEN_O_BINARY
394*86d7f5d3SJohn Marino if (Expand == BINARY_EXPAND)
395*86d7f5d3SJohn Marino *diffp++ = "--binary";
396*86d7f5d3SJohn Marino # endif
397*86d7f5d3SJohn Marino diffp[0] = maketemp(0);
398*86d7f5d3SJohn Marino if (runv(-1, diffp[0], cov)) {
399*86d7f5d3SJohn Marino rcserror("co failed");
400*86d7f5d3SJohn Marino continue;
401*86d7f5d3SJohn Marino }
402*86d7f5d3SJohn Marino if (!rev2) {
403*86d7f5d3SJohn Marino diffp[1] = workname;
404*86d7f5d3SJohn Marino if (*workname == '-') {
405*86d7f5d3SJohn Marino char *dp = ftnalloc(char, strlen(workname)+3);
406*86d7f5d3SJohn Marino diffp[1] = dp;
407*86d7f5d3SJohn Marino *dp++ = '.';
408*86d7f5d3SJohn Marino *dp++ = SLASH;
409*86d7f5d3SJohn Marino VOID strcpy(dp, workname);
410*86d7f5d3SJohn Marino }
411*86d7f5d3SJohn Marino } else {
412*86d7f5d3SJohn Marino diagnose("retrieving revision %s\n",xrev2);
413*86d7f5d3SJohn Marino bufscpy(&commarg, "-p");
414*86d7f5d3SJohn Marino bufscat(&commarg, rev2); /* not xrev2, for $Name's sake */
415*86d7f5d3SJohn Marino cov[3 + !DIFF_L] = commarg.string;
416*86d7f5d3SJohn Marino diffp[1] = maketemp(1);
417*86d7f5d3SJohn Marino if (runv(-1, diffp[1], cov)) {
418*86d7f5d3SJohn Marino rcserror("co failed");
419*86d7f5d3SJohn Marino continue;
420*86d7f5d3SJohn Marino }
421*86d7f5d3SJohn Marino }
422*86d7f5d3SJohn Marino if (!rev2)
423*86d7f5d3SJohn Marino diagnose("diff%s -r%s %s\n", diffvstr, xrev1, workname);
424*86d7f5d3SJohn Marino else
425*86d7f5d3SJohn Marino diagnose("diff%s -r%s -r%s\n", diffvstr, xrev1, xrev2);
426*86d7f5d3SJohn Marino
427*86d7f5d3SJohn Marino diffp[2] = 0;
428*86d7f5d3SJohn Marino switch (runv(-1, (char*)0, diffv)) {
429*86d7f5d3SJohn Marino case DIFF_SUCCESS:
430*86d7f5d3SJohn Marino break;
431*86d7f5d3SJohn Marino case DIFF_FAILURE:
432*86d7f5d3SJohn Marino if (exitstatus == DIFF_SUCCESS)
433*86d7f5d3SJohn Marino exitstatus = DIFF_FAILURE;
434*86d7f5d3SJohn Marino break;
435*86d7f5d3SJohn Marino default:
436*86d7f5d3SJohn Marino workerror("diff failed");
437*86d7f5d3SJohn Marino }
438*86d7f5d3SJohn Marino }
439*86d7f5d3SJohn Marino
440*86d7f5d3SJohn Marino tempunlink();
441*86d7f5d3SJohn Marino exitmain(exitstatus);
442*86d7f5d3SJohn Marino }
443*86d7f5d3SJohn Marino
444*86d7f5d3SJohn Marino static void
cleanup()445*86d7f5d3SJohn Marino cleanup()
446*86d7f5d3SJohn Marino {
447*86d7f5d3SJohn Marino if (nerror) exitstatus = DIFF_TROUBLE;
448*86d7f5d3SJohn Marino Izclose(&finptr);
449*86d7f5d3SJohn Marino Izclose(&workptr);
450*86d7f5d3SJohn Marino }
451*86d7f5d3SJohn Marino
452*86d7f5d3SJohn Marino #if RCS_lint
453*86d7f5d3SJohn Marino # define exiterr rdiffExit
454*86d7f5d3SJohn Marino #endif
455*86d7f5d3SJohn Marino void
exiterr()456*86d7f5d3SJohn Marino exiterr()
457*86d7f5d3SJohn Marino {
458*86d7f5d3SJohn Marino tempunlink();
459*86d7f5d3SJohn Marino _exit(DIFF_TROUBLE);
460*86d7f5d3SJohn Marino }
461*86d7f5d3SJohn Marino
462*86d7f5d3SJohn Marino #if DIFF_L
463*86d7f5d3SJohn Marino static char const *
setup_label(b,num,date)464*86d7f5d3SJohn Marino setup_label(b, num, date)
465*86d7f5d3SJohn Marino struct buf *b;
466*86d7f5d3SJohn Marino char const *num;
467*86d7f5d3SJohn Marino char const date[datesize];
468*86d7f5d3SJohn Marino {
469*86d7f5d3SJohn Marino char *p;
470*86d7f5d3SJohn Marino char datestr[datesize + zonelenmax];
471*86d7f5d3SJohn Marino VOID date2str(date, datestr);
472*86d7f5d3SJohn Marino bufalloc(b,
473*86d7f5d3SJohn Marino strlen(workname)
474*86d7f5d3SJohn Marino + sizeof datestr + 4
475*86d7f5d3SJohn Marino + (num ? strlen(num) : 0)
476*86d7f5d3SJohn Marino );
477*86d7f5d3SJohn Marino p = b->string;
478*86d7f5d3SJohn Marino if (num)
479*86d7f5d3SJohn Marino VOID sprintf(p, "-L%s\t%s\t%s", workname, datestr, num);
480*86d7f5d3SJohn Marino else
481*86d7f5d3SJohn Marino VOID sprintf(p, "-L%s\t%s", workname, datestr);
482*86d7f5d3SJohn Marino return p;
483*86d7f5d3SJohn Marino }
484*86d7f5d3SJohn Marino #endif
485