|
|
1.1 root 1: /*
2: * RCS rcsdiff operation
3: */
4: #ifndef lint
5: static char rcsid[]=
6: "$Header: /usr/src/contrib/rcs/src/RCS/rcsdiff.c,v 3.11 89/08/15 21:37:01 bostic Exp $ Purdue CS";
7: #endif
8: /*****************************************************************************
9: * generate difference between RCS revisions
10: *****************************************************************************
11: */
12:
13: /* Copyright (C) 1982, 1988, 1989 Walter Tichy
14: * All rights reserved.
15: *
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.
25: *
26: * Report all problems and direct all questions to:
27: * [email protected]
28: *
29:
30:
31:
32:
33:
34:
35:
36: */
37:
38:
39:
40:
41: /* $Log: rcsdiff.c,v $
42: * Revision 3.11 89/08/15 21:37:01 bostic
43: * Version 4 from Tom Narten at Purdue
44: *
45: * Revision 4.6 89/05/01 15:12:27 narten
46: * changed copyright header to reflect current distribution rules
47: *
48: * Revision 4.5 88/11/08 12:01:51 narten
49: * changes from [email protected] (Paul Eggert)
50: *
51: * Revision 4.5 88/08/09 19:12:41 eggert
52: * Use execv(), not system(); yield exit status like diff(1)s; allow cc -R.
53: *
54: * Revision 4.4 87/12/18 11:37:46 narten
55: * changes Jay Lepreau made in the 4.3 BSD version, to add support for
56: * "-i", "-w", and "-t" flags and to permit flags to be bundled together,
57: * merged in.
58: *
59: * Revision 4.3 87/10/18 10:31:42 narten
60: * Updating version numbers. Changes relative to 1.1 actually
61: * relative to 4.1
62: *
63: * Revision 1.3 87/09/24 13:59:21 narten
64: * Sources now pass through lint (if you ignore printf/sprintf/fprintf
65: * warnings)
66: *
67: * Revision 1.2 87/03/27 14:22:15 jenkins
68: * Port to suns
69: *
70: * Revision 1.1 84/01/23 14:50:18 kcs
71: * Initial revision
72: *
73: * Revision 4.1 83/05/03 22:13:19 wft
74: * Added default branch, option -q, exit status like diff.
75: * Added fterror() to replace faterror().
76: *
77: * Revision 3.6 83/01/15 17:52:40 wft
78: * Expanded mainprogram to handle multiple RCS files.
79: *
80: * Revision 3.5 83/01/06 09:33:45 wft
81: * Fixed passing of -c (context) option to diff.
82: *
83: * Revision 3.4 82/12/24 15:28:38 wft
84: * Added call to catchsig().
85: *
86: * Revision 3.3 82/12/10 16:08:17 wft
87: * Corrected checking of return code from diff; improved error msgs.
88: *
89: * Revision 3.2 82/12/04 13:20:09 wft
90: * replaced getdelta() with gettree(). Changed diagnostics.
91: *
92: * Revision 3.1 82/11/28 19:25:04 wft
93: * Initial revision.
94: *
95: */
96: #include <ctype.h>
97: #include "rcsbase.h"
98: #define ERRCODE 2 /*error code for exit status */
99: extern char *rindex();
100: #ifndef lint
101: static char rcsbaseid[] = RCSBASE;
102: #endif
103: static char co[] = CO;
104:
105: extern int cleanup(); /* cleanup after signals */
106: extern char * mktempfile(); /*temporary file name generator */
107: extern int fterror(); /*forward for special fatal error func. */
108: extern struct hshentry * genrevs(); /*generate delta numbers */
109: extern int nerror; /*counter for errors */
110: extern int quietflag; /*suppresses diagnostics */
111: extern FILE * finptr; /* RCS input file */
112:
113: char *RCSfilename;
114: char *workfilename;
115: char * temp1file, * temp2file;
116:
117: char bops[10];
118: char otherops[10];
119:
120: main (argc, argv)
121: int argc; char **argv;
122: {
123: char * cmdusage;
124: char commarg[revlength+3];
125: int revnums; /* counter for revision numbers given */
126: char * rev1, * rev2; /* revision numbers from command line */
127: char numericrev[revlength]; /* holds expanded revision number */
128: char * xrev1, * xrev2; /* expanded revision numbers */
129: struct hshentry * gendeltas[hshsize];/*stores deltas to be generated*/
130: struct hshentry * target;
131: char * boption, * otheroption;
132: int exit_stats;
133: int diffs_found;
134: char *argp;
135: register c;
136:
137: catchints();
138: otheroption = otherops + 2;
139: boption = bops + 2;
140: cmdid = "rcsdiff";
141: cmdusage = "command format:\n rcsdiff [-biwt] [-q] [-cefhn] [-rrev1] [-rrev2] file";
142: diffs_found=revnums=0;
143: while (--argc,++argv, argc>=1 && ((*argv)[0] == '-')) {
144: argp = &((*argv)[1]);
145: while (c = *argp++) switch (c) {
146: case 'r':
147: if (*argp!='\0') {
148: if (revnums==0) {
149: rev1= argp; revnums=1;
150: } elif (revnums==1) {
151: rev2= argp; revnums=2;
152: } else {
153: fterror("too many revision numbers");
154: }
155: } /* do nothing for empty -r */
156: argp += strlen(argp);
157: break;
158: case 'b':
159: case 'i':
160: case 'w':
161: case 't':
162: if (!rindex(bops + 2, c))
163: *boption++ = c;
164: break;
165: case 'q':
166: quietflag=true;
167: break;
168: case 'c':
169: case 'e':
170: case 'f':
171: case 'h':
172: case 'n':
173: if (otheroption == otherops + 2) {
174: *otheroption++ = c;
175: if (c == 'c' && isdigit(*argp)) {
176: while (isdigit(*argp) && otheroption < otherops+sizeof(otherops)-1)
177: *otheroption++ = *argp++;
178: if (*argp)
179: faterror("-c: bad count");
180: argp = "";
181: }
182: } else {
183: fterror("Options c,e,f,h,n are mutually exclusive");
184: }
185: break;
186: default:
187: fterror("unknown option: %s\n%s", *argv,cmdusage);
188: };
189: } /* end of option processing */
190:
191: if (boption != bops + 2) {
192: bops[0] = ' ';
193: bops[1] = '-';
194: boption = bops;
195: }
196: if (otheroption != otherops + 2) {
197: otherops[0] = ' ';
198: otherops[1] = '-';
199: otheroption = otherops;
200: }
201: if (argc<1) fterror("No input file\n%s",cmdusage);
202:
203: /* now handle all filenames */
204: do {
205: finptr=NULL;
206:
207: if (pairfilenames(argc,argv,true,false)!=1) continue;
208: diagnose("===================================================================");
209: diagnose("RCS file: %s",RCSfilename);
210: if (revnums<2 && !(access(workfilename,4)==0)) {
211: error("Can't open %s",workfilename);
212: continue;
213: }
214: if (!trysema(RCSfilename,false)) continue; /* give up */
215:
216:
217: gettree(); /* reads in the delta tree */
218:
219: if (Head==nil) {
220: error("no revisions present");
221: continue;
222: }
223: if (revnums==0)
224: rev1=Dbranch!=nil?Dbranch->num:Head->num; /* default rev1 */
225:
226: if (!expandsym(rev1,numericrev)) continue;
227: if (!(target=genrevs(numericrev,(char *)nil,(char *)nil,(char *)nil,gendeltas))) continue;
228: xrev1=target->num;
229:
230: if (revnums==2) {
231: if (!expandsym(rev2,numericrev)) continue;
232: if (!(target=genrevs(numericrev,(char *)nil,(char *)nil,(char *)nil,gendeltas))) continue;
233: xrev2=target->num;
234: }
235:
236:
237: temp1file=mktempfile("/tmp/",TMPFILE1);
238: diagnose("retrieving revision %s",xrev1);
239: VOID sprintf(commarg,"-p%s",xrev1);
240: if (run((char*)nil,temp1file, co,"-q",commarg,RCSfilename,(char*)nil)){
241: error("co failed");
242: continue;
243: }
244: if (revnums<=1) {
245: temp2file=workfilename;
246: diagnose("diff%s%s -r%s %s",boption,otheroption,xrev1,workfilename);
247: } else {
248: temp2file=mktempfile("/tmp/",TMPFILE2);
249: diagnose("retrieving revision %s",xrev2);
250: VOID sprintf(commarg,"-p%s",xrev2);
251: if (run((char*)nil,temp2file, co,"-q",commarg,RCSfilename,(char *)nil)){
252: error("co failed");
253: continue;
254: }
255: diagnose("diff%s%s -r%s -r%s",boption,otheroption,xrev1,xrev2);
256: }
257:
258: exit_stats =
259: *boption
260: ? *otheroption
261: ? run((char*)nil,(char*)nil, DIFF, boption+1, otheroption+1, temp1file,temp2file,(char*)nil)
262: : run((char*)nil,(char*)nil, DIFF, boption+1, temp1file,temp2file,(char*)nil)
263: : *otheroption
264: ? run((char*)nil,(char*)nil, DIFF, otheroption+1, temp1file,temp2file,(char*)nil)
265: : run((char*)nil,(char*)nil, DIFF, temp1file,temp2file,(char*)nil);
266:
267: if (exit_stats == (1 << BYTESIZ))
268: diffs_found = 1;
269: else if (exit_stats != 0) {
270: error ("diff failed");
271: continue;
272: }
273: } while (cleanup(),
274: ++argv, --argc >=1);
275:
276:
277: exit(nerror ? ERRCODE : diffs_found);
278: }
279:
280:
281: /*VARARGS3*/
282: fterror(e, e1, e2)
283: char * e, * e1, * e2;
284: /* prints error message and terminates program with ERRCODE */
285: { nerror++;
286: VOID fprintf(stderr,"%s error: ",cmdid);
287: VOID fprintf(stderr,e, e1, e2);
288: VOID fprintf(stderr,"\n%s aborted\n",cmdid);
289: VOID cleanup();
290: exit(ERRCODE);
291: }
292:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.