remove traces of benchmarks from test/.
[minix.git] / commands / simple / cdiff.c
blobe8eaa0ab9eb6e45399a8c19def5ac7377681cfff
1 /* cdiff - context diff Author: Larry Wall */
3 /* Cdiff - turns a regular diff into a new-style context diff
5 * Usage: cdiff file1 file2
6 */
8 #define PATCHLEVEL 2
10 #include <sys/types.h>
11 #include <sys/stat.h>
12 #include <sys/wait.h>
13 #include <ctype.h>
14 #include <fcntl.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #include <time.h>
18 #include <unistd.h>
19 #include <limits.h>
20 #include <stdio.h>
22 char buff[512];
24 FILE *inputfp, *oldfp, *newfp;
26 int oldmin, oldmax, newmin, newmax;
27 int oldbeg, oldend, newbeg, newend;
28 int preoldmax, prenewmax;
29 int preoldbeg, preoldend, prenewbeg, prenewend;
30 int oldwanted, newwanted;
32 char *oldhunk, *newhunk;
33 char *progname;
34 size_t oldsize, oldalloc, newsize, newalloc;
36 _PROTOTYPE(int main, (int argc, char **argv));
37 _PROTOTYPE(void dumphunk, (void));
38 _PROTOTYPE(char *getold, (int targ));
39 _PROTOTYPE(char *getnew, (int targ));
40 _PROTOTYPE(void *xmalloc, (size_t size));
41 _PROTOTYPE(void *xrealloc, (void *ptr, size_t size));
43 #define Nullfp (FILE*)0
44 #define Nullch (char*)0
45 #define ENOUGH (NAME_MAX + PATH_MAX + 1)
46 #define CRC_END 12
48 int main(argc, argv)
49 int argc;
50 char **argv;
52 FILE *crcfp;
53 char *old, *new;
54 int context = 3;
55 struct stat statbuf;
56 register char *s;
57 char op;
58 char *newmark, *oldmark;
59 char sysbuf1[ENOUGH], sysbuf2[ENOUGH];
60 int len;
61 char *line;
62 int i;
63 int status;
65 progname = argv[0];
66 oldalloc = 512;
67 oldhunk = (char *) xmalloc(oldalloc);
68 newalloc = 512;
69 newhunk = (char *) xmalloc(newalloc);
71 for (argc--, argv++; argc; argc--, argv++) {
72 if (argv[0][0] != '-') break;
74 if (argv[0][1] == 'c') context = atoi(argv[0] + 2);
77 if (argc != 2) {
78 fprintf(stderr, "Usage: cdiff old new\n");
79 exit(2);
81 old = argv[0];
82 new = argv[1];
84 oldfp = fopen(old, "r");
85 if (!oldfp) {
86 fprintf(stderr, "Can't open %s\n", old);
87 exit(2);
89 newfp = fopen(new, "r");
90 if (!newfp) {
91 fprintf(stderr, "Can't open %s\n", new);
92 exit(2);
95 /* Compute crcs by popen()ing crc and reading the output. Do this before
96 * popen()ing diff to do the work. popen() attempts to support multiple
97 * clients, but the 1.3-1.6.24b versions don't succeed.
99 sprintf(sysbuf1, "crc %s", old);
100 crcfp = popen(sysbuf1, "r");
101 if (!crcfp) {
102 /* The only advantage of cdiff over diff is that it prints crcs, so
103 * give up easily if crc fails.
105 fprintf(stderr, "Can't execute crc %s\n", old);
106 exit(2);
108 fgets(sysbuf1, sizeof(sysbuf1), crcfp);
109 sysbuf1[CRC_END] = '\0';
110 status = pclose(crcfp);
111 if (status != 0) {
112 fprintf(stderr, "crc %s returned bad status %d\n", old, status);
113 exit(2);
115 sprintf(sysbuf2, "crc %s", new);
116 crcfp = popen(sysbuf2, "r");
117 if (!crcfp) {
118 fprintf(stderr, "Can't execute crc %s\n", new);
119 exit(2);
121 fgets(sysbuf2, sizeof(sysbuf2), crcfp);
122 sysbuf2[CRC_END] = '\0';
123 status = pclose(crcfp);
124 if (status != 0) {
125 fprintf(stderr, "crc %s returned bad status %d\n", new, status);
126 exit(2);
129 sprintf(buff, "diff %s %s 2>/dev/null", old, new);
130 inputfp = popen(buff, "r");
131 if (!inputfp) {
132 fprintf(stderr, "Can't execute diff %s %s\n", old, new);
133 exit(2);
136 fstat(fileno(oldfp), &statbuf);
137 printf("*** %s crc=%s\t%s", old, sysbuf1, ctime(&statbuf.st_mtime));
138 fstat(fileno(newfp), &statbuf);
139 printf("--- %s crc=%s\t%s", new, sysbuf2, ctime(&statbuf.st_mtime));
141 preoldend = -1000;
143 while (fgets(buff, sizeof buff, inputfp) != Nullch) {
144 if (isdigit(*buff)) {
145 oldmin = atoi(buff);
146 for (s = buff; isdigit(*s); s++);
147 if (*s == ',') {
148 s++;
149 oldmax = atoi(s);
150 for (; isdigit(*s); s++);
151 } else {
152 oldmax = oldmin;
154 if (*s != 'a' && *s != 'd' && *s != 'c') {
155 fprintf(stderr, "Unparseable input: %s\n", s);
156 exit(2);
158 op = *s;
159 s++;
160 newmin = atoi(s);
161 for (; isdigit(*s); s++);
162 if (*s == ',') {
163 s++;
164 newmax = atoi(s);
165 for (; isdigit(*s); s++);
166 } else {
167 newmax = newmin;
169 if (*s != '\n' && *s != ' ') {
170 fprintf(stderr, "Unparseable input: %s\n", s);
171 exit(2);
173 newmark = oldmark = "! ";
174 if (op == 'a') {
175 oldmin++;
176 newmark = "+ ";
178 if (op == 'd') {
179 newmin++;
180 oldmark = "- ";
182 oldbeg = oldmin - context;
183 oldend = oldmax + context;
184 if (oldbeg < 1) oldbeg = 1;
185 newbeg = newmin - context;
186 newend = newmax + context;
187 if (newbeg < 1) newbeg = 1;
189 if (preoldend < oldbeg - 1) {
190 if (preoldend >= 0) {
191 dumphunk();
193 preoldbeg = oldbeg;
194 prenewbeg = newbeg;
195 oldwanted = newwanted = 0;
196 oldsize = newsize = 0;
197 } else { /* we want to append to previous hunk */
198 oldbeg = preoldmax + 1;
199 newbeg = prenewmax + 1;
202 for (i = oldbeg; i <= oldmax; i++) {
203 line = getold(i);
204 if (!line) {
205 oldend = oldmax = i - 1;
206 break;
208 len = strlen(line) + 2;
209 if (oldsize + len + 1 >= oldalloc) {
210 oldalloc *= 2;
211 oldhunk = (char *) xrealloc(oldhunk, oldalloc);
213 if (i >= oldmin) {
214 strcpy(oldhunk + oldsize, oldmark);
215 oldwanted++;
216 } else {
217 strcpy(oldhunk + oldsize, " ");
219 strcpy(oldhunk + oldsize + 2, line);
220 oldsize += len;
222 preoldmax = oldmax;
223 preoldend = oldend;
225 for (i = newbeg; i <= newmax; i++) {
226 line = getnew(i);
227 if (!line) {
228 newend = newmax = i - 1;
229 break;
231 len = strlen(line) + 2;
232 if (newsize + len + 1 >= newalloc) {
233 newalloc *= 2;
234 newhunk = (char *) xrealloc(newhunk, newalloc);
236 if (i >= newmin) {
237 strcpy(newhunk + newsize, newmark);
238 newwanted++;
239 } else {
240 strcpy(newhunk + newsize, " ");
242 strcpy(newhunk + newsize + 2, line);
243 newsize += len;
245 prenewmax = newmax;
246 prenewend = newend;
250 if (preoldend >= 0) {
251 dumphunk();
253 status = pclose(inputfp);
254 if (!WIFEXITED(status)) exit(2);
255 status = WEXITSTATUS(status);
256 return(status == 0 || status == 1 ? status : 2);
259 void dumphunk()
261 int i;
262 char *line;
263 int len;
265 for (i = preoldmax + 1; i <= preoldend; i++) {
266 line = getold(i);
267 if (!line) {
268 preoldend = i - 1;
269 break;
271 len = strlen(line) + 2;
272 if (oldsize + len + 1 >= oldalloc) {
273 oldalloc *= 2;
274 oldhunk = (char *) xrealloc(oldhunk, oldalloc);
276 strcpy(oldhunk + oldsize, " ");
277 strcpy(oldhunk + oldsize + 2, line);
278 oldsize += len;
280 for (i = prenewmax + 1; i <= prenewend; i++) {
281 line = getnew(i);
282 if (!line) {
283 prenewend = i - 1;
284 break;
286 len = strlen(line) + 2;
287 if (newsize + len + 1 >= newalloc) {
288 newalloc *= 2;
289 newhunk = (char *) xrealloc(newhunk, newalloc);
291 strcpy(newhunk + newsize, " ");
292 strcpy(newhunk + newsize + 2, line);
293 newsize += len;
295 printf("***************\n");
296 if (preoldbeg >= preoldend) {
297 printf("*** %d ****\n", preoldend);
298 } else {
299 printf("*** %d,%d ****\n", preoldbeg, preoldend);
301 if (oldwanted) {
302 printf("%s", oldhunk);
304 oldsize = 0;
305 *oldhunk = '\0';
306 if (prenewbeg >= prenewend) {
307 printf("--- %d ----\n", prenewend);
308 } else {
309 printf("--- %d,%d ----\n", prenewbeg, prenewend);
311 if (newwanted) {
312 printf("%s", newhunk);
314 newsize = 0;
315 *newhunk = '\0';
318 char *getold(targ)
319 int targ;
321 static int oldline = 0;
323 while (fgets(buff, sizeof buff, oldfp) != Nullch) {
324 oldline++;
325 if (oldline == targ) return buff;
327 return Nullch;
330 char *getnew(targ)
331 int targ;
333 static int newline = 0;
335 while (fgets(buff, sizeof buff, newfp) != Nullch) {
336 newline++;
337 if (newline == targ) return buff;
339 return Nullch;
342 void *xmalloc(size)
343 size_t size;
345 void *ptr;
347 ptr = malloc(size);
348 if (ptr == NULL) {
349 fprintf(stderr, "%s: out of memory\n", progname);
350 exit(2);
352 return(ptr);
355 void *xrealloc(ptr, size)
356 void *ptr;
357 size_t size;
359 ptr = realloc(ptr, size);
360 if (ptr == NULL) {
361 fprintf(stderr, "%s: out of memory\n", progname);
362 exit(2);
364 return(ptr);