|
|
1.1 root 1: /* idiff: interactive diff */
2:
3: #include <stdio.h>
4: #include <stdlib.h>
5: #include <ctype.h>
6: #include <string.h>
7: #include <signal.h>
8: #include <sys/types.h>
9: #include <sys/stat.h>
10:
11: #define HUGE 10000 /* large number of lines */
12:
13: char *progname;
14: char diffout[100];
15: char tempfile[100];
16: char *outfile = "idiff.out";
17:
18: FILE *efopen(char *, char *);
19: char *basename(char *);
20: void idiff(FILE *f1, FILE *f2, FILE *fin, FILE *fout);
21: void parse(char *s, int *pfrom1, int *pto1, int *pcmd, int *pfrom2, int *pto2);
22: void nskip(FILE *fin, int n);
23: void ncopy(FILE *fin, int n, FILE *fout);
24: void cleanup(int);
25:
26: /* these have to be undone in a non-posix world: */
27:
28: /* int fileno(FILE *); */
29: #define S_ISDIR(n) ((n) & S_IFDIR) /* vaxes */
30: #define remove unlink
31:
32: main(int argc, char *argv[])
33: {
34: FILE *fin, *fout, *f1, *f2;
35: char buf[BUFSIZ], diffopts[100], *p;
36: struct stat stbuf;
37:
38: progname = argv[0];
39: buf[0] = 0;
40: while (argc > 3 && argv[1][0] == '-') { /* assume all flags go to diff for now */
41: strcat(diffopts, argv[1]);
42: strcat(diffopts, " ");
43: argv++;
44: argc--;
45: }
46: if (argc != 3) {
47: fprintf(stderr, "Usage: idiff [-opts] file1 file2\n");
48: exit(1);
49: }
50: f1 = efopen(argv[1], "r");
51: f2 = efopen(argv[2], "r");
52: fstat(fileno(f2), &stbuf);
53: if (S_ISDIR(stbuf.st_mode)) {
54: fclose(f2);
55: sprintf(buf, "%s/%s", argv[2], basename(argv[1]));
56: f2 = efopen(buf, "r");
57: }
58: if (signal(SIGINT, SIG_IGN) != SIG_IGN)
59: signal(SIGINT, cleanup);
60: fout = efopen(outfile, "w");
61: tmpnam(diffout);
62: sprintf(buf,"diff %s %s %s >%s", diffopts, argv[1], argv[2], diffout);
63: system(buf);
64: fin = efopen(diffout, "r");
65: tmpnam(tempfile);
66: idiff(f1, f2, fin, fout);
67: remove(diffout);
68: printf("%s output in file %s\n", progname, outfile);
69: exit(0);
70: }
71:
72: void cleanup(int i)
73: {
74: remove(diffout);
75: remove(tempfile);
76: remove(outfile);
77: exit(1);
78: }
79:
80: char *basename(char *s) /* find last component of filename */
81: {
82: static char *p;
83:
84: for (p = s+strlen(s)-1; p >= s; p--)
85: if (*p == '/')
86: return p+1;
87: return s;
88: }
89:
90: void idiff(FILE *f1, FILE *f2, FILE *fin, FILE *fout) /* process diffs */
91: {
92: char buf[BUFSIZ], buf2[BUFSIZ];
93: FILE *ft;
94: int cmd, n, from1, to1, from2, to2, nf1, nf2, done;
95:
96: nf1 = nf2 = 0;
97: done = 0;
98: while (!done && fgets(buf, sizeof buf, fin) != NULL) {
99: parse(buf, &from1, &to1, &cmd, &from2, &to2);
100: n = to1-from1 + to2-from2 + 1; /* #lines from diff */
101: if (cmd == 'c')
102: n += 2;
103: else if (cmd == 'a')
104: from1++;
105: else if (cmd == 'd')
106: from2++;
107: printf("%s", buf);
108: while (n-- > 0) {
109: fgets(buf, sizeof buf, fin);
110: printf("%s", buf);
111: }
112: for(;;) {
113: printf("? ");
114: fflush(stdout);
115: fgets(buf, sizeof buf, stdin);
116: switch (buf[0]) {
117: case '2':
118: to1 = to2 = HUGE;
119: done = 1;
120: case '>':
121: nskip(f1, to1-nf1);
122: ncopy(f2, to2-nf2, fout);
123: break;
124: case '1':
125: to1 = to2 = HUGE;
126: done = 1;
127: case '<':
128: nskip(f2, to2-nf2);
129: ncopy(f1, to1-nf1, fout);
130: break;
131: case 'e':
132: ncopy(f1, from1-1-nf1, fout);
133: nskip(f2, from2-1-nf2);
134: ft = efopen(tempfile, "w");
135: ncopy(f1, to1+1-from1, ft);
136: fprintf(ft, "---\n");
137: ncopy(f2, to2+1-from2, ft);
138: fclose(ft);
139: sprintf(buf2, "ed %s", tempfile);
140: system(buf2);
141: ft = efopen(tempfile, "r");
142: ncopy(ft, HUGE, fout);
143: fclose(ft);
144: break;
145: case '!':
146: system(buf+1);
147: printf("!\n");
148: break;
149: case 'd':
150: nskip(f1, to1-nf1);
151: nskip(f2, to2-nf2);
152: break;
153: default:
154: printf("< > d e 1 2 !\n");
155: continue;
156: }
157: break;
158: }
159: nf1 = to1;
160: nf2 = to2;
161: }
162: ncopy(f1, HUGE, fout); /* can fail on very long files */
163: remove(tempfile);
164: }
165:
166: void parse(char *s, int *pfrom1, int *pto1, int *pcmd, int *pfrom2, int *pto2)
167: {
168: #define a2i(p) while (isdigit(*s)) p = 10*(p) + *s++ - '0'
169:
170: *pfrom1 = *pto1 = *pfrom2 = *pto2 = 0;
171: a2i(*pfrom1);
172: if (*s == ',') {
173: s++;
174: a2i(*pto1);
175: } else
176: *pto1 = *pfrom1;
177: *pcmd = *s++;
178: a2i(*pfrom2);
179: if (*s == ',') {
180: s++;
181: a2i(*pto2);
182: } else
183: *pto2 = *pfrom2;
184: }
185:
186: void nskip(FILE *fin, int n) /* skip n lines of file fin */
187: {
188: char buf[BUFSIZ];
189:
190: while (n-- > 0)
191: fgets(buf, sizeof buf, fin);
192: }
193:
194: void ncopy(FILE *fin, int n, FILE *fout) /* copy n lines from fin to fout */
195: {
196: char buf[BUFSIZ];
197:
198: while (n-- > 0) {
199: if (fgets(buf, sizeof buf, fin) == NULL)
200: return;
201: fputs(buf, fout);
202: }
203: }
204:
205: FILE *efopen(char *file, char *mode) /* fopen file, die if can't */
206: {
207: FILE *fp;
208: extern char *progname;
209:
210: if ((fp = fopen(file, mode)) != NULL)
211: return fp;
212: fprintf(stderr, "%s: can't open file %s mode %s\n",
213: progname, file, mode);
214: exit(1);
215: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.