Sync usage with man page.
[netbsd-mini2440.git] / usr.bin / rcs / src / rcsdiff.c
blobbfc9aa2a49f8fa11d50e26b2692dede7df10e850
1 /*
2 * RCS rcsdiff operation
3 */
4 #ifndef lint
5 static char rcsid[]=
6 "$Header: /pub/NetBSD/misc/repositories/cvsroot/src/usr.bin/rcs/src/Attic/rcsdiff.c,v 1.1 1993/03/21 09:58:07 cgd Exp $ Purdue CS";
7 #endif
8 /*****************************************************************************
9 * generate difference between RCS revisions
10 *****************************************************************************
13 /* Copyright (C) 1982, 1988, 1989 Walter Tichy
14 * All rights reserved.
16 * Redistribution and use in source and binary forms are permitted
17 * provided that the above copyright notice and this paragraph are
18 * duplicated in all such forms and that any documentation,
19 * advertising materials, and other materials related to such
20 * distribution and use acknowledge that the software was developed
21 * by Walter Tichy.
22 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
24 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
26 * Report all problems and direct all questions to:
27 * rcs-bugs@cs.purdue.edu
41 /* $Log: rcsdiff.c,v $
42 * Revision 3.12 91/02/22 00:11:20 elan
43 * *** empty log message ***
45 * Revision 3.11 89/08/15 21:37:01 bostic
46 * Version 4 from Tom Narten at Purdue
48 * Revision 4.6 89/05/01 15:12:27 narten
49 * changed copyright header to reflect current distribution rules
51 * Revision 4.5 88/11/08 12:01:51 narten
52 * changes from eggert@sm.unisys.com (Paul Eggert)
54 * Revision 4.5 88/08/09 19:12:41 eggert
55 * Use execv(), not system(); yield exit status like diff(1)s; allow cc -R.
57 * Revision 4.4 87/12/18 11:37:46 narten
58 * changes Jay Lepreau made in the 4.3 BSD version, to add support for
59 * "-i", "-w", and "-t" flags and to permit flags to be bundled together,
60 * merged in.
62 * Revision 4.3 87/10/18 10:31:42 narten
63 * Updating version numbers. Changes relative to 1.1 actually
64 * relative to 4.1
66 * Revision 1.3 87/09/24 13:59:21 narten
67 * Sources now pass through lint (if you ignore printf/sprintf/fprintf
68 * warnings)
70 * Revision 1.2 87/03/27 14:22:15 jenkins
71 * Port to suns
73 * Revision 1.1 84/01/23 14:50:18 kcs
74 * Initial revision
76 * Revision 4.1 83/05/03 22:13:19 wft
77 * Added default branch, option -q, exit status like diff.
78 * Added fterror() to replace faterror().
80 * Revision 3.6 83/01/15 17:52:40 wft
81 * Expanded mainprogram to handle multiple RCS files.
83 * Revision 3.5 83/01/06 09:33:45 wft
84 * Fixed passing of -c (context) option to diff.
86 * Revision 3.4 82/12/24 15:28:38 wft
87 * Added call to catchsig().
89 * Revision 3.3 82/12/10 16:08:17 wft
90 * Corrected checking of return code from diff; improved error msgs.
92 * Revision 3.2 82/12/04 13:20:09 wft
93 * replaced getdelta() with gettree(). Changed diagnostics.
95 * Revision 3.1 82/11/28 19:25:04 wft
96 * Initial revision.
99 #include <ctype.h>
100 #include "rcsbase.h"
101 #define ERRCODE 2 /*error code for exit status */
102 extern char *rindex();
103 #ifndef lint
104 static char rcsbaseid[] = RCSBASE;
105 #endif
106 static char co[] = CO;
108 extern int cleanup(); /* cleanup after signals */
109 extern char * mktempfile(); /*temporary file name generator */
110 extern int fterror(); /*forward for special fatal error func. */
111 extern struct hshentry * genrevs(); /*generate delta numbers */
112 extern int nerror; /*counter for errors */
113 extern int quietflag; /*suppresses diagnostics */
114 extern FILE * finptr; /* RCS input file */
116 char *RCSfilename;
117 char *workfilename;
118 char * temp1file, * temp2file;
120 char bops[10];
121 char otherops[10];
123 main (argc, argv)
124 int argc; char **argv;
126 char * cmdusage;
127 char commarg[revlength+3];
128 int revnums; /* counter for revision numbers given */
129 char * rev1, * rev2; /* revision numbers from command line */
130 char numericrev[revlength]; /* holds expanded revision number */
131 char * xrev1, * xrev2; /* expanded revision numbers */
132 struct hshentry * gendeltas[hshsize];/*stores deltas to be generated*/
133 struct hshentry * target;
134 char * boption, * otheroption;
135 int exit_stats;
136 int diffs_found;
137 char *argp;
138 register c;
140 catchints();
141 otheroption = otherops + 2;
142 boption = bops + 2;
143 cmdid = "rcsdiff";
144 cmdusage = "command format:\n rcsdiff [-biwt] [-q] [-cefhn] [-rrev1] [-rrev2] file";
145 diffs_found=revnums=0;
146 while (--argc,++argv, argc>=1 && ((*argv)[0] == '-')) {
147 argp = &((*argv)[1]);
148 while (c = *argp++) switch (c) {
149 case 'r':
150 if (*argp!='\0') {
151 if (revnums==0) {
152 rev1= argp; revnums=1;
153 } elif (revnums==1) {
154 rev2= argp; revnums=2;
155 } else {
156 fterror("too many revision numbers");
158 } /* do nothing for empty -r */
159 argp += strlen(argp);
160 break;
161 case 'b':
162 case 'i':
163 case 'w':
164 case 't':
165 if (!rindex(bops + 2, c))
166 *boption++ = c;
167 break;
168 case 'q':
169 quietflag=true;
170 break;
171 case 'c':
172 case 'e':
173 case 'f':
174 case 'h':
175 case 'n':
176 if (otheroption == otherops + 2) {
177 *otheroption++ = c;
178 if (c == 'c' && isdigit(*argp)) {
179 while (isdigit(*argp) && otheroption < otherops+sizeof(otherops)-1)
180 *otheroption++ = *argp++;
181 if (*argp)
182 faterror("-c: bad count");
183 argp = "";
185 } else {
186 fterror("Options c,e,f,h,n are mutually exclusive");
188 break;
189 default:
190 fterror("unknown option: %s\n%s", *argv,cmdusage);
192 } /* end of option processing */
194 if (boption != bops + 2) {
195 bops[0] = ' ';
196 bops[1] = '-';
197 boption = bops;
199 if (otheroption != otherops + 2) {
200 otherops[0] = ' ';
201 otherops[1] = '-';
202 otheroption = otherops;
204 if (argc<1) fterror("No input file\n%s",cmdusage);
206 /* now handle all filenames */
207 do {
208 finptr=NULL;
210 if (pairfilenames(argc,argv,true,false)!=1) continue;
211 diagnose("===================================================================");
212 diagnose("RCS file: %s",RCSfilename);
213 if (revnums<2 && !(access(workfilename,4)==0)) {
214 error("Can't open %s",workfilename);
215 continue;
217 if (!trysema(RCSfilename,false)) continue; /* give up */
220 gettree(); /* reads in the delta tree */
222 if (Head==nil) {
223 error("no revisions present");
224 continue;
226 if (revnums==0)
227 rev1=Dbranch!=nil?Dbranch->num:Head->num; /* default rev1 */
229 if (!expandsym(rev1,numericrev)) continue;
230 if (!(target=genrevs(numericrev,(char *)nil,(char *)nil,(char *)nil,gendeltas))) continue;
231 xrev1=target->num;
233 if (revnums==2) {
234 if (!expandsym(rev2,numericrev)) continue;
235 if (!(target=genrevs(numericrev,(char *)nil,(char *)nil,(char *)nil,gendeltas))) continue;
236 xrev2=target->num;
240 temp1file=mktempfile("/tmp/",TMPFILE1);
241 diagnose("retrieving revision %s",xrev1);
242 VOID sprintf(commarg,"-p%s",xrev1);
243 if (run((char*)nil,temp1file, co,"-q",commarg,RCSfilename,(char*)nil)){
244 error("co failed");
245 continue;
247 if (revnums<=1) {
248 temp2file=workfilename;
249 diagnose("diff%s%s -r%s %s",boption,otheroption,xrev1,workfilename);
250 } else {
251 temp2file=mktempfile("/tmp/",TMPFILE2);
252 diagnose("retrieving revision %s",xrev2);
253 VOID sprintf(commarg,"-p%s",xrev2);
254 if (run((char*)nil,temp2file, co,"-q",commarg,RCSfilename,(char *)nil)){
255 error("co failed");
256 continue;
258 diagnose("diff%s%s -r%s -r%s",boption,otheroption,xrev1,xrev2);
261 exit_stats =
262 *boption
263 ? *otheroption
264 ? run((char*)nil,(char*)nil, DIFF, boption+1, otheroption+1, temp1file,temp2file,(char*)nil)
265 : run((char*)nil,(char*)nil, DIFF, boption+1, temp1file,temp2file,(char*)nil)
266 : *otheroption
267 ? run((char*)nil,(char*)nil, DIFF, otheroption+1, temp1file,temp2file,(char*)nil)
268 : run((char*)nil,(char*)nil, DIFF, temp1file,temp2file,(char*)nil);
270 if (exit_stats == (1 << BYTESIZ))
271 diffs_found = 1;
272 else if (exit_stats != 0) {
273 error ("diff failed");
274 continue;
276 } while (cleanup(),
277 ++argv, --argc >=1);
280 exit(nerror ? ERRCODE : diffs_found);
284 /*VARARGS3*/
285 fterror(e, e1, e2)
286 char * e, * e1, * e2;
287 /* prints error message and terminates program with ERRCODE */
288 { nerror++;
289 VOID fprintf(stderr,"%s error: ",cmdid);
290 VOID fprintf(stderr,e, e1, e2);
291 VOID fprintf(stderr,"\n%s aborted\n",cmdid);
292 VOID cleanup();
293 exit(ERRCODE);