xref: /netbsd-src/external/gpl2/rcs/dist/src/rcsdiff.c (revision fa28c6faa16e0b00edee7acdcaf4899797043def)
1*fa28c6faSchristos /*	$NetBSD: rcsdiff.c,v 1.2 2016/01/14 04:22:39 christos Exp $	*/
27bdc2678Schristos 
37bdc2678Schristos /* Compare 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: rcsdiff.c,v
347bdc2678Schristos  * Revision 5.19  1995/06/16 06:19:24  eggert
357bdc2678Schristos  * Update FSF address.
367bdc2678Schristos  *
377bdc2678Schristos  * Revision 5.18  1995/06/01 16:23:43  eggert
387bdc2678Schristos  * (main): Pass "--binary" if -kb and if --binary makes a difference.
397bdc2678Schristos  * Don't treat + options specially.
407bdc2678Schristos  *
417bdc2678Schristos  * Revision 5.17  1994/03/17 14:05:48  eggert
427bdc2678Schristos  * Specify subprocess input via file descriptor, not file name.  Remove lint.
437bdc2678Schristos  *
447bdc2678Schristos  * Revision 5.16  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.15  1993/11/03 17:42:27  eggert
487bdc2678Schristos  * Add -z.  Ignore -T.  Pass -Vn to `co'.  Add Name keyword.
497bdc2678Schristos  * Put revision numbers in -c output.  Improve quality of diagnostics.
507bdc2678Schristos  *
517bdc2678Schristos  * Revision 5.14  1992/07/28  16:12:44  eggert
527bdc2678Schristos  * Add -V.  Use co -M for better dates with traditional diff -c.
537bdc2678Schristos  *
547bdc2678Schristos  * Revision 5.13  1992/02/17  23:02:23  eggert
557bdc2678Schristos  * Output more readable context diff headers.
567bdc2678Schristos  * Suppress needless checkout and comparison of identical revisions.
577bdc2678Schristos  *
587bdc2678Schristos  * Revision 5.12  1992/01/24  18:44:19  eggert
597bdc2678Schristos  * Add GNU diff 1.15.2's new options.  lint -> RCS_lint
607bdc2678Schristos  *
617bdc2678Schristos  * Revision 5.11  1992/01/06  02:42:34  eggert
627bdc2678Schristos  * Update usage string.
637bdc2678Schristos  *
647bdc2678Schristos  * Revision 5.10  1991/10/07  17:32:46  eggert
657bdc2678Schristos  * Remove lint.
667bdc2678Schristos  *
677bdc2678Schristos  * Revision 5.9  1991/08/19  03:13:55  eggert
687bdc2678Schristos  * Add RCSINIT, -r$.  Tune.
697bdc2678Schristos  *
707bdc2678Schristos  * Revision 5.8  1991/04/21  11:58:21  eggert
717bdc2678Schristos  * Add -x, RCSINIT, MS-DOS support.
727bdc2678Schristos  *
737bdc2678Schristos  * Revision 5.7  1990/12/13  06:54:07  eggert
747bdc2678Schristos  * GNU diff 1.15 has -u.
757bdc2678Schristos  *
767bdc2678Schristos  * Revision 5.6  1990/11/01  05:03:39  eggert
777bdc2678Schristos  * Remove unneeded setid check.
787bdc2678Schristos  *
797bdc2678Schristos  * Revision 5.5  1990/10/04  06:30:19  eggert
807bdc2678Schristos  * Accumulate exit status across files.
817bdc2678Schristos  *
827bdc2678Schristos  * Revision 5.4  1990/09/27  01:31:43  eggert
837bdc2678Schristos  * Yield 1, not EXIT_FAILURE, when diffs are found.
847bdc2678Schristos  *
857bdc2678Schristos  * Revision 5.3  1990/09/11  02:41:11  eggert
867bdc2678Schristos  * Simplify -kkvl test.
877bdc2678Schristos  *
887bdc2678Schristos  * Revision 5.2  1990/09/04  17:07:19  eggert
897bdc2678Schristos  * Diff's argv was too small by 1.
907bdc2678Schristos  *
917bdc2678Schristos  * Revision 5.1  1990/08/29  07:13:55  eggert
927bdc2678Schristos  * Add -kkvl.
937bdc2678Schristos  *
947bdc2678Schristos  * Revision 5.0  1990/08/22  08:12:46  eggert
957bdc2678Schristos  * Add -k, -V.  Don't use access().  Add setuid support.
967bdc2678Schristos  * Remove compile-time limits; use malloc instead.
977bdc2678Schristos  * Don't pass arguments with leading '+' to diff; GNU DIFF treats them as options.
987bdc2678Schristos  * Add GNU diff's flags.  Make lock and temp files faster and safer.
997bdc2678Schristos  * Ansify and Posixate.
1007bdc2678Schristos  *
1017bdc2678Schristos  * Revision 4.6  89/05/01  15:12:27  narten
1027bdc2678Schristos  * changed copyright header to reflect current distribution rules
1037bdc2678Schristos  *
1047bdc2678Schristos  * Revision 4.5  88/08/09  19:12:41  eggert
1057bdc2678Schristos  * Use execv(), not system(); yield exit status like diff(1)s; allow cc -R.
1067bdc2678Schristos  *
1077bdc2678Schristos  * Revision 4.4  87/12/18  11:37:46  narten
1087bdc2678Schristos  * changes Jay Lepreau made in the 4.3 BSD version, to add support for
1097bdc2678Schristos  * "-i", "-w", and "-t" flags and to permit flags to be bundled together,
1107bdc2678Schristos  * merged in.
1117bdc2678Schristos  *
1127bdc2678Schristos  * Revision 4.3  87/10/18  10:31:42  narten
1137bdc2678Schristos  * Updating version numbers. Changes relative to 1.1 actually
1147bdc2678Schristos  * relative to 4.1
1157bdc2678Schristos  *
1167bdc2678Schristos  * Revision 1.3  87/09/24  13:59:21  narten
1177bdc2678Schristos  * Sources now pass through lint (if you ignore printf/sprintf/fprintf
1187bdc2678Schristos  * warnings)
1197bdc2678Schristos  *
1207bdc2678Schristos  * Revision 1.2  87/03/27  14:22:15  jenkins
1217bdc2678Schristos  * Port to suns
1227bdc2678Schristos  *
1237bdc2678Schristos  * Revision 4.1  83/05/03  22:13:19  wft
1247bdc2678Schristos  * Added default branch, option -q, exit status like diff.
1257bdc2678Schristos  * Added fterror() to replace faterror().
1267bdc2678Schristos  *
1277bdc2678Schristos  * Revision 3.6  83/01/15  17:52:40  wft
1287bdc2678Schristos  * Expanded mainprogram to handle multiple RCS files.
1297bdc2678Schristos  *
1307bdc2678Schristos  * Revision 3.5  83/01/06  09:33:45  wft
1317bdc2678Schristos  * Fixed passing of -c (context) option to diff.
1327bdc2678Schristos  *
1337bdc2678Schristos  * Revision 3.4  82/12/24  15:28:38  wft
1347bdc2678Schristos  * Added call to catchsig().
1357bdc2678Schristos  *
1367bdc2678Schristos  * Revision 3.3  82/12/10  16:08:17  wft
1377bdc2678Schristos  * Corrected checking of return code from diff; improved error msgs.
1387bdc2678Schristos  *
1397bdc2678Schristos  * Revision 3.2  82/12/04  13:20:09  wft
1407bdc2678Schristos  * replaced getdelta() with gettree(). Changed diagnostics.
1417bdc2678Schristos  *
1427bdc2678Schristos  * Revision 3.1  82/11/28  19:25:04  wft
1437bdc2678Schristos  * Initial revision.
1447bdc2678Schristos  *
1457bdc2678Schristos  */
1467bdc2678Schristos #include "rcsbase.h"
1477bdc2678Schristos 
1487bdc2678Schristos #if DIFF_L
1497bdc2678Schristos static char const *setup_label P((struct buf*,char const*,char const[datesize]));
1507bdc2678Schristos #endif
1517bdc2678Schristos static void cleanup P((void));
1527bdc2678Schristos 
1537bdc2678Schristos static int exitstatus;
1547bdc2678Schristos static RILE *workptr;
1557bdc2678Schristos static struct stat workstat;
1567bdc2678Schristos 
1577bdc2678Schristos mainProg(rcsdiffId, "rcsdiff", "Id: rcsdiff.c,v 5.19 1995/06/16 06:19:24 eggert Exp ")
1587bdc2678Schristos {
1597bdc2678Schristos     static char const cmdusage[] =
1607bdc2678Schristos 	    "\nrcsdiff usage: rcsdiff -ksubst -q -rrev1 [-rrev2] -Vn -xsuff -zzone [diff options] file ...";
1617bdc2678Schristos 
1627bdc2678Schristos     int  revnums;                 /* counter for revision numbers given */
1637bdc2678Schristos     char const *rev1, *rev2;	/* revision numbers from command line */
1647bdc2678Schristos     char const *xrev1, *xrev2;	/* expanded revision numbers */
1657bdc2678Schristos     char const *expandarg, *lexpandarg, *suffixarg, *versionarg, *zonearg;
1667bdc2678Schristos #if DIFF_L
1677bdc2678Schristos     static struct buf labelbuf[2];
1687bdc2678Schristos     int file_labels;
1697bdc2678Schristos     char const **diff_label1, **diff_label2;
1707bdc2678Schristos     char date2[datesize];
1717bdc2678Schristos #endif
1727bdc2678Schristos     char const *cov[10 + !DIFF_L];
1737bdc2678Schristos     char const **diffv, **diffp, **diffpend;	/* argv for subsidiary diff */
1747bdc2678Schristos     char const **pp, *p, *diffvstr;
1757bdc2678Schristos     struct buf commarg;
1767bdc2678Schristos     struct buf numericrev;	/* expanded revision number */
1777bdc2678Schristos     struct hshentries *gendeltas;	/* deltas to be generated */
1787bdc2678Schristos     struct hshentry * target;
1797bdc2678Schristos     char *a, *dcp, **newargv;
1807bdc2678Schristos     int no_diff_means_no_output;
181*fa28c6faSchristos     int c;
1827bdc2678Schristos 
1837bdc2678Schristos     exitstatus = DIFF_SUCCESS;
1847bdc2678Schristos 
1857bdc2678Schristos     bufautobegin(&commarg);
1867bdc2678Schristos     bufautobegin(&numericrev);
1877bdc2678Schristos     revnums = 0;
1887bdc2678Schristos     rev1 = rev2 = xrev2 = 0;
1897bdc2678Schristos #if DIFF_L
1907bdc2678Schristos     file_labels = 0;
1917bdc2678Schristos #endif
1927bdc2678Schristos     expandarg = suffixarg = versionarg = zonearg = 0;
1937bdc2678Schristos     no_diff_means_no_output = true;
1947bdc2678Schristos     suffixes = X_DEFAULT;
1957bdc2678Schristos 
1967bdc2678Schristos     /*
1977bdc2678Schristos     * Room for runv extra + args [+ --binary] [+ 2 labels]
1987bdc2678Schristos     * + 1 file + 1 trailing null.
1997bdc2678Schristos     */
2007bdc2678Schristos     diffv = tnalloc(char const*, 1 + argc + !!OPEN_O_BINARY + 2*DIFF_L + 2);
2017bdc2678Schristos     diffp = diffv + 1;
2027bdc2678Schristos     *diffp++ = DIFF;
2037bdc2678Schristos 
2047bdc2678Schristos     argc = getRCSINIT(argc, argv, &newargv);
2057bdc2678Schristos     argv = newargv;
2067bdc2678Schristos     while (a = *++argv,  0<--argc && *a++=='-') {
2077bdc2678Schristos 	dcp = a;
2087bdc2678Schristos 	while ((c = *a++)) switch (c) {
2097bdc2678Schristos 	    case 'r':
2107bdc2678Schristos 		    switch (++revnums) {
2117bdc2678Schristos 			case 1: rev1=a; break;
2127bdc2678Schristos 			case 2: rev2=a; break;
2137bdc2678Schristos 			default: error("too many revision numbers");
2147bdc2678Schristos 		    }
2157bdc2678Schristos 		    goto option_handled;
2167bdc2678Schristos 	    case '-': case 'D':
2177bdc2678Schristos 		    no_diff_means_no_output = false;
2187bdc2678Schristos 		    /* fall into */
219*fa28c6faSchristos 	    case 'C': case 'F': case 'I': case 'L': case 'W': case 'U':
2207bdc2678Schristos #if DIFF_L
221*fa28c6faSchristos 		    if (c == 'L'  &&  file_labels++ == 2)
2227bdc2678Schristos 			faterror("too many -L options");
2237bdc2678Schristos #endif
2247bdc2678Schristos 		    *dcp++ = c;
2257bdc2678Schristos 		    if (*a)
2267bdc2678Schristos 			do *dcp++ = *a++;
2277bdc2678Schristos 			while (*a);
2287bdc2678Schristos 		    else {
2297bdc2678Schristos 			if (!--argc)
2307bdc2678Schristos 			    faterror("-%c needs following argument%s",
2317bdc2678Schristos 				    c, cmdusage
2327bdc2678Schristos 			    );
2337bdc2678Schristos 			*diffp++ = *argv++;
2347bdc2678Schristos 		    }
2357bdc2678Schristos 		    break;
2367bdc2678Schristos 	    case 'y':
2377bdc2678Schristos 		    no_diff_means_no_output = false;
2387bdc2678Schristos 		    /* fall into */
2397bdc2678Schristos 	    case 'B': case 'H':
2407bdc2678Schristos 	    case '0': case '1': case '2': case '3': case '4':
2417bdc2678Schristos 	    case '5': case '6': case '7': case '8': case '9':
2427bdc2678Schristos 	    case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
2437bdc2678Schristos 	    case 'h': case 'i': case 'n': case 'p':
2447bdc2678Schristos 	    case 't': case 'u': case 'w':
2457bdc2678Schristos 		    *dcp++ = c;
2467bdc2678Schristos 		    break;
2477bdc2678Schristos 	    case 'q':
2487bdc2678Schristos 		    quietflag=true;
2497bdc2678Schristos 		    break;
2507bdc2678Schristos 	    case 'x':
2517bdc2678Schristos 		    suffixarg = *argv;
2527bdc2678Schristos 		    suffixes = *argv + 2;
2537bdc2678Schristos 		    goto option_handled;
2547bdc2678Schristos 	    case 'z':
2557bdc2678Schristos 		    zonearg = *argv;
2567bdc2678Schristos 		    zone_set(*argv + 2);
2577bdc2678Schristos 		    goto option_handled;
2587bdc2678Schristos 	    case 'T':
2597bdc2678Schristos 		    /* Ignore -T, so that RCSINIT can contain -T.  */
2607bdc2678Schristos 		    if (*a)
2617bdc2678Schristos 			    goto unknown;
2627bdc2678Schristos 		    break;
2637bdc2678Schristos 	    case 'V':
2647bdc2678Schristos 		    versionarg = *argv;
2657bdc2678Schristos 		    setRCSversion(versionarg);
2667bdc2678Schristos 		    goto option_handled;
2677bdc2678Schristos 	    case 'k':
2687bdc2678Schristos 		    expandarg = *argv;
2697bdc2678Schristos 		    if (0 <= str2expmode(expandarg+2))
2707bdc2678Schristos 			goto option_handled;
2717bdc2678Schristos 		    /* fall into */
2727bdc2678Schristos 	    default:
2737bdc2678Schristos 	    unknown:
2747bdc2678Schristos 		    error("unknown option: %s%s", *argv, cmdusage);
2757bdc2678Schristos 	    };
2767bdc2678Schristos       option_handled:
2777bdc2678Schristos 	if (dcp != *argv+1) {
2787bdc2678Schristos 	    *dcp = 0;
2797bdc2678Schristos 	    *diffp++ = *argv;
2807bdc2678Schristos 	}
2817bdc2678Schristos     } /* end of option processing */
2827bdc2678Schristos 
2837bdc2678Schristos     for (pp = diffv+2, c = 0;  pp<diffp;  )
2847bdc2678Schristos 	    c += strlen(*pp++) + 1;
2857bdc2678Schristos     diffvstr = a = tnalloc(char, c + 1);
2867bdc2678Schristos     for (pp = diffv+2;  pp<diffp;  ) {
2877bdc2678Schristos 	    p = *pp++;
2887bdc2678Schristos 	    *a++ = ' ';
2897bdc2678Schristos 	    while ((*a = *p++))
2907bdc2678Schristos 		    a++;
2917bdc2678Schristos     }
2927bdc2678Schristos     *a = 0;
2937bdc2678Schristos 
2947bdc2678Schristos #if DIFF_L
2957bdc2678Schristos     diff_label1 = diff_label2 = 0;
2967bdc2678Schristos     if (file_labels < 2) {
2977bdc2678Schristos 	    if (!file_labels)
2987bdc2678Schristos 		    diff_label1 = diffp++;
2997bdc2678Schristos 	    diff_label2 = diffp++;
3007bdc2678Schristos     }
3017bdc2678Schristos #endif
3027bdc2678Schristos     diffpend = diffp;
3037bdc2678Schristos 
3047bdc2678Schristos     cov[1] = CO;
3057bdc2678Schristos     cov[2] = "-q";
3067bdc2678Schristos #   if !DIFF_L
3077bdc2678Schristos 	cov[3] = "-M";
3087bdc2678Schristos #   endif
3097bdc2678Schristos 
3107bdc2678Schristos     /* Now handle all pathnames.  */
3117bdc2678Schristos     if (nerror)
3127bdc2678Schristos 	cleanup();
3137bdc2678Schristos     else if (argc < 1)
3147bdc2678Schristos 	faterror("no input file%s", cmdusage);
3157bdc2678Schristos     else
3167bdc2678Schristos 	for (;  0 < argc;  cleanup(), ++argv, --argc) {
3177bdc2678Schristos 	    ffree();
3187bdc2678Schristos 
3197bdc2678Schristos 	    if (pairnames(argc, argv, rcsreadopen, true, false)  <=  0)
3207bdc2678Schristos 		    continue;
3217bdc2678Schristos 	    diagnose("===================================================================\nRCS file: %s\n",RCSname);
3227bdc2678Schristos 	    if (!rev2) {
3237bdc2678Schristos 		/* Make sure work file is readable, and get its status.  */
3247bdc2678Schristos 		if (!(workptr = Iopen(workname, FOPEN_R_WORK, &workstat))) {
3257bdc2678Schristos 		    eerror(workname);
3267bdc2678Schristos 		    continue;
3277bdc2678Schristos 		}
3287bdc2678Schristos 	    }
3297bdc2678Schristos 
3307bdc2678Schristos 
3317bdc2678Schristos 	    gettree(); /* reads in the delta tree */
3327bdc2678Schristos 
3337bdc2678Schristos 	    if (!Head) {
3347bdc2678Schristos 		    rcserror("no revisions present");
3357bdc2678Schristos 		    continue;
3367bdc2678Schristos 	    }
3377bdc2678Schristos 	    if (revnums==0  ||  !*rev1)
3387bdc2678Schristos 		    rev1  =  Dbranch ? Dbranch : Head->num;
3397bdc2678Schristos 
3407bdc2678Schristos 	    if (!fexpandsym(rev1, &numericrev, workptr)) continue;
3417bdc2678Schristos 	    if (!(target=genrevs(numericrev.string,(char *)0,(char *)0,(char *)0,&gendeltas))) continue;
3427bdc2678Schristos 	    xrev1=target->num;
3437bdc2678Schristos #if DIFF_L
3447bdc2678Schristos 	    if (diff_label1)
3457bdc2678Schristos 		*diff_label1 = setup_label(&labelbuf[0], target->num, target->date);
3467bdc2678Schristos #endif
3477bdc2678Schristos 
3487bdc2678Schristos 	    lexpandarg = expandarg;
3497bdc2678Schristos 	    if (revnums==2) {
3507bdc2678Schristos 		    if (!fexpandsym(
3517bdc2678Schristos 			    *rev2 ? rev2  : Dbranch ? Dbranch  : Head->num,
3527bdc2678Schristos 			    &numericrev,
3537bdc2678Schristos 			    workptr
3547bdc2678Schristos 		    ))
3557bdc2678Schristos 			continue;
3567bdc2678Schristos 		    if (!(target=genrevs(numericrev.string,(char *)0,(char *)0,(char *)0,&gendeltas))) continue;
3577bdc2678Schristos 		    xrev2=target->num;
3587bdc2678Schristos 		    if (no_diff_means_no_output  &&  xrev1 == xrev2)
3597bdc2678Schristos 			continue;
3607bdc2678Schristos 	    } else if (
3617bdc2678Schristos 			target->lockedby
3627bdc2678Schristos 		&&	!lexpandarg
3637bdc2678Schristos 		&&	Expand == KEYVAL_EXPAND
3647bdc2678Schristos 		&&	WORKMODE(RCSstat.st_mode,true) == workstat.st_mode
3657bdc2678Schristos 	    )
3667bdc2678Schristos 		    lexpandarg = "-kkvl";
3677bdc2678Schristos 	    Izclose(&workptr);
3687bdc2678Schristos #if DIFF_L
369*fa28c6faSchristos 	    if (diff_label2) {
3707bdc2678Schristos 		if (revnums == 2)
3717bdc2678Schristos 		    *diff_label2 = setup_label(&labelbuf[1], target->num, target->date);
3727bdc2678Schristos 		else {
3737bdc2678Schristos 		    time2date(workstat.st_mtime, date2);
3747bdc2678Schristos 		    *diff_label2 = setup_label(&labelbuf[1], (char*)0, date2);
3757bdc2678Schristos 		}
376*fa28c6faSchristos 	    }
3777bdc2678Schristos #endif
3787bdc2678Schristos 
3797bdc2678Schristos 	    diagnose("retrieving revision %s\n", xrev1);
3807bdc2678Schristos 	    bufscpy(&commarg, "-p");
3817bdc2678Schristos 	    bufscat(&commarg, rev1); /* not xrev1, for $Name's sake */
3827bdc2678Schristos 
3837bdc2678Schristos 	    pp = &cov[3 + !DIFF_L];
3847bdc2678Schristos 	    *pp++ = commarg.string;
3857bdc2678Schristos 	    if (lexpandarg) *pp++ = lexpandarg;
3867bdc2678Schristos 	    if (suffixarg) *pp++ = suffixarg;
3877bdc2678Schristos 	    if (versionarg) *pp++ = versionarg;
3887bdc2678Schristos 	    if (zonearg) *pp++ = zonearg;
3897bdc2678Schristos 	    *pp++ = RCSname;
3907bdc2678Schristos 	    *pp = 0;
3917bdc2678Schristos 
3927bdc2678Schristos 	    diffp = diffpend;
3937bdc2678Schristos #	    if OPEN_O_BINARY
3947bdc2678Schristos 		    if (Expand == BINARY_EXPAND)
3957bdc2678Schristos 			    *diffp++ = "--binary";
3967bdc2678Schristos #	    endif
3977bdc2678Schristos 	    diffp[0] = maketemp(0);
3987bdc2678Schristos 	    if (runv(-1, diffp[0], cov)) {
3997bdc2678Schristos 		    rcserror("co failed");
4007bdc2678Schristos 		    continue;
4017bdc2678Schristos 	    }
4027bdc2678Schristos 	    if (!rev2) {
4037bdc2678Schristos 		    diffp[1] = workname;
4047bdc2678Schristos 		    if (*workname == '-') {
4057bdc2678Schristos 			char *dp = ftnalloc(char, strlen(workname)+3);
4067bdc2678Schristos 			diffp[1] = dp;
4077bdc2678Schristos 			*dp++ = '.';
4087bdc2678Schristos 			*dp++ = SLASH;
4097bdc2678Schristos 			VOID strcpy(dp, workname);
4107bdc2678Schristos 		    }
4117bdc2678Schristos 	    } else {
4127bdc2678Schristos 		    diagnose("retrieving revision %s\n",xrev2);
4137bdc2678Schristos 		    bufscpy(&commarg, "-p");
4147bdc2678Schristos 		    bufscat(&commarg, rev2); /* not xrev2, for $Name's sake */
4157bdc2678Schristos 		    cov[3 + !DIFF_L] = commarg.string;
4167bdc2678Schristos 		    diffp[1] = maketemp(1);
4177bdc2678Schristos 		    if (runv(-1, diffp[1], cov)) {
4187bdc2678Schristos 			    rcserror("co failed");
4197bdc2678Schristos 			    continue;
4207bdc2678Schristos 		    }
4217bdc2678Schristos 	    }
4227bdc2678Schristos 	    if (!rev2)
4237bdc2678Schristos 		    diagnose("diff%s -r%s %s\n", diffvstr, xrev1, workname);
4247bdc2678Schristos 	    else
4257bdc2678Schristos 		    diagnose("diff%s -r%s -r%s\n", diffvstr, xrev1, xrev2);
4267bdc2678Schristos 
4277bdc2678Schristos 	    diffp[2] = 0;
4287bdc2678Schristos 	    switch (runv(-1, (char*)0, diffv)) {
4297bdc2678Schristos 		    case DIFF_SUCCESS:
4307bdc2678Schristos 			    break;
4317bdc2678Schristos 		    case DIFF_FAILURE:
4327bdc2678Schristos 			    if (exitstatus == DIFF_SUCCESS)
4337bdc2678Schristos 				    exitstatus = DIFF_FAILURE;
4347bdc2678Schristos 			    break;
4357bdc2678Schristos 		    default:
4367bdc2678Schristos 			    workerror("diff failed");
4377bdc2678Schristos 	    }
4387bdc2678Schristos 	}
4397bdc2678Schristos 
4407bdc2678Schristos     tempunlink();
4417bdc2678Schristos     exitmain(exitstatus);
4427bdc2678Schristos }
4437bdc2678Schristos 
4447bdc2678Schristos     static void
cleanup()4457bdc2678Schristos cleanup()
4467bdc2678Schristos {
4477bdc2678Schristos     if (nerror) exitstatus = DIFF_TROUBLE;
4487bdc2678Schristos     Izclose(&finptr);
4497bdc2678Schristos     Izclose(&workptr);
4507bdc2678Schristos }
4517bdc2678Schristos 
4527bdc2678Schristos #if RCS_lint
4537bdc2678Schristos #	define exiterr rdiffExit
4547bdc2678Schristos #endif
4557bdc2678Schristos     void
exiterr()4567bdc2678Schristos exiterr()
4577bdc2678Schristos {
4587bdc2678Schristos     tempunlink();
4597bdc2678Schristos     _exit(DIFF_TROUBLE);
4607bdc2678Schristos }
4617bdc2678Schristos 
4627bdc2678Schristos #if DIFF_L
4637bdc2678Schristos 	static char const *
setup_label(b,num,date)4647bdc2678Schristos setup_label(b, num, date)
4657bdc2678Schristos 	struct buf *b;
4667bdc2678Schristos 	char const *num;
4677bdc2678Schristos 	char const date[datesize];
4687bdc2678Schristos {
4697bdc2678Schristos 	char *p;
4707bdc2678Schristos 	char datestr[datesize + zonelenmax];
4717bdc2678Schristos 	VOID date2str(date, datestr);
4727bdc2678Schristos 	bufalloc(b,
4737bdc2678Schristos 		strlen(workname)
4747bdc2678Schristos 		+ sizeof datestr + 4
4757bdc2678Schristos 		+ (num ? strlen(num) : 0)
4767bdc2678Schristos 	);
4777bdc2678Schristos 	p = b->string;
4787bdc2678Schristos 	if (num)
4797bdc2678Schristos 		VOID sprintf(p, "-L%s\t%s\t%s", workname, datestr, num);
4807bdc2678Schristos 	else
4817bdc2678Schristos 		VOID sprintf(p, "-L%s\t%s", workname, datestr);
4827bdc2678Schristos 	return p;
4837bdc2678Schristos }
4847bdc2678Schristos #endif
485