Blame


1 5993a8f2 2003-11-23 devnull #include <u.h>
2 5993a8f2 2003-11-23 devnull #include <libc.h>
3 5993a8f2 2003-11-23 devnull #include <bio.h>
4 5993a8f2 2003-11-23 devnull #include "diff.h"
5 5993a8f2 2003-11-23 devnull
6 5993a8f2 2003-11-23 devnull /* diff - differential file comparison
7 5993a8f2 2003-11-23 devnull *
8 5993a8f2 2003-11-23 devnull * Uses an algorithm due to Harold Stone, which finds
9 5993a8f2 2003-11-23 devnull * a pair of longest identical subsequences in the two
10 5993a8f2 2003-11-23 devnull * files.
11 5993a8f2 2003-11-23 devnull *
12 5993a8f2 2003-11-23 devnull * The major goal is to generate the match vector J.
13 5993a8f2 2003-11-23 devnull * J[i] is the index of the line in file1 corresponding
14 5993a8f2 2003-11-23 devnull * to line i file0. J[i] = 0 if there is no
15 5993a8f2 2003-11-23 devnull * such line in file1.
16 5993a8f2 2003-11-23 devnull *
17 5993a8f2 2003-11-23 devnull * Lines are hashed so as to work in core. All potential
18 5993a8f2 2003-11-23 devnull * matches are located by sorting the lines of each file
19 5993a8f2 2003-11-23 devnull * on the hash (called value). In particular, this
20 5993a8f2 2003-11-23 devnull * collects the equivalence classes in file1 together.
21 5993a8f2 2003-11-23 devnull * Subroutine equiv replaces the value of each line in
22 5993a8f2 2003-11-23 devnull * file0 by the index of the first element of its
23 5993a8f2 2003-11-23 devnull * matching equivalence in (the reordered) file1.
24 5993a8f2 2003-11-23 devnull * To save space equiv squeezes file1 into a single
25 5993a8f2 2003-11-23 devnull * array member in which the equivalence classes
26 5993a8f2 2003-11-23 devnull * are simply concatenated, except that their first
27 5993a8f2 2003-11-23 devnull * members are flagged by changing sign.
28 5993a8f2 2003-11-23 devnull *
29 5993a8f2 2003-11-23 devnull * Next the indices that point into member are unsorted into
30 5993a8f2 2003-11-23 devnull * array class according to the original order of file0.
31 5993a8f2 2003-11-23 devnull *
32 5993a8f2 2003-11-23 devnull * The cleverness lies in routine stone. This marches
33 5993a8f2 2003-11-23 devnull * through the lines of file0, developing a vector klist
34 5993a8f2 2003-11-23 devnull * of "k-candidates". At step i a k-candidate is a matched
35 5993a8f2 2003-11-23 devnull * pair of lines x,y (x in file0 y in file1) such that
36 5993a8f2 2003-11-23 devnull * there is a common subsequence of lenght k
37 5993a8f2 2003-11-23 devnull * between the first i lines of file0 and the first y
38 5993a8f2 2003-11-23 devnull * lines of file1, but there is no such subsequence for
39 5993a8f2 2003-11-23 devnull * any smaller y. x is the earliest possible mate to y
40 5993a8f2 2003-11-23 devnull * that occurs in such a subsequence.
41 5993a8f2 2003-11-23 devnull *
42 5993a8f2 2003-11-23 devnull * Whenever any of the members of the equivalence class of
43 5993a8f2 2003-11-23 devnull * lines in file1 matable to a line in file0 has serial number
44 5993a8f2 2003-11-23 devnull * less than the y of some k-candidate, that k-candidate
45 5993a8f2 2003-11-23 devnull * with the smallest such y is replaced. The new
46 5993a8f2 2003-11-23 devnull * k-candidate is chained (via pred) to the current
47 5993a8f2 2003-11-23 devnull * k-1 candidate so that the actual subsequence can
48 5993a8f2 2003-11-23 devnull * be recovered. When a member has serial number greater
49 5993a8f2 2003-11-23 devnull * that the y of all k-candidates, the klist is extended.
50 5993a8f2 2003-11-23 devnull * At the end, the longest subsequence is pulled out
51 5993a8f2 2003-11-23 devnull * and placed in the array J by unravel.
52 5993a8f2 2003-11-23 devnull *
53 5993a8f2 2003-11-23 devnull * With J in hand, the matches there recorded are
54 5993a8f2 2003-11-23 devnull * check'ed against reality to assure that no spurious
55 5993a8f2 2003-11-23 devnull * matches have crept in due to hashing. If they have,
56 5993a8f2 2003-11-23 devnull * they are broken, and "jackpot " is recorded--a harmless
57 5993a8f2 2003-11-23 devnull * matter except that a true match for a spuriously
58 5993a8f2 2003-11-23 devnull * mated line may now be unnecessarily reported as a change.
59 5993a8f2 2003-11-23 devnull *
60 5993a8f2 2003-11-23 devnull * Much of the complexity of the program comes simply
61 5993a8f2 2003-11-23 devnull * from trying to minimize core utilization and
62 5993a8f2 2003-11-23 devnull * maximize the range of doable problems by dynamically
63 5993a8f2 2003-11-23 devnull * allocating what is needed and reusing what is not.
64 5993a8f2 2003-11-23 devnull * The core requirements for problems larger than somewhat
65 5993a8f2 2003-11-23 devnull * are (in words) 2*length(file0) + length(file1) +
66 5993a8f2 2003-11-23 devnull * 3*(number of k-candidates installed), typically about
67 5993a8f2 2003-11-23 devnull * 6n words for files of length n.
68 5993a8f2 2003-11-23 devnull */
69 5993a8f2 2003-11-23 devnull /* TIDY THIS UP */
70 5993a8f2 2003-11-23 devnull struct cand {
71 5993a8f2 2003-11-23 devnull int x;
72 5993a8f2 2003-11-23 devnull int y;
73 5993a8f2 2003-11-23 devnull int pred;
74 5993a8f2 2003-11-23 devnull } cand;
75 5993a8f2 2003-11-23 devnull struct line {
76 5993a8f2 2003-11-23 devnull int serial;
77 5993a8f2 2003-11-23 devnull int value;
78 5993a8f2 2003-11-23 devnull } *file[2], line;
79 5993a8f2 2003-11-23 devnull int len[2];
80 5993a8f2 2003-11-23 devnull int binary;
81 5993a8f2 2003-11-23 devnull struct line *sfile[2]; /*shortened by pruning common prefix and suffix*/
82 5993a8f2 2003-11-23 devnull int slen[2];
83 5993a8f2 2003-11-23 devnull int pref, suff; /*length of prefix and suffix*/
84 5993a8f2 2003-11-23 devnull int *class; /*will be overlaid on file[0]*/
85 5993a8f2 2003-11-23 devnull int *member; /*will be overlaid on file[1]*/
86 5993a8f2 2003-11-23 devnull int *klist; /*will be overlaid on file[0] after class*/
87 5993a8f2 2003-11-23 devnull struct cand *clist; /* merely a free storage pot for candidates */
88 5993a8f2 2003-11-23 devnull int clen;
89 5993a8f2 2003-11-23 devnull int *J; /*will be overlaid on class*/
90 5993a8f2 2003-11-23 devnull long *ixold; /*will be overlaid on klist*/
91 5993a8f2 2003-11-23 devnull long *ixnew; /*will be overlaid on file[1]*/
92 5993a8f2 2003-11-23 devnull /* END OF SOME TIDYING */
93 5993a8f2 2003-11-23 devnull
94 5993a8f2 2003-11-23 devnull static void
95 5993a8f2 2003-11-23 devnull sort(struct line *a, int n) /*shellsort CACM #201*/
96 5993a8f2 2003-11-23 devnull {
97 5993a8f2 2003-11-23 devnull int m;
98 5993a8f2 2003-11-23 devnull struct line *ai, *aim, *j, *k;
99 5993a8f2 2003-11-23 devnull struct line w;
100 5993a8f2 2003-11-23 devnull int i;
101 5993a8f2 2003-11-23 devnull
102 5993a8f2 2003-11-23 devnull m = 0;
103 5993a8f2 2003-11-23 devnull for (i = 1; i <= n; i *= 2)
104 5993a8f2 2003-11-23 devnull m = 2*i - 1;
105 5993a8f2 2003-11-23 devnull for (m /= 2; m != 0; m /= 2) {
106 5993a8f2 2003-11-23 devnull k = a+(n-m);
107 5993a8f2 2003-11-23 devnull for (j = a+1; j <= k; j++) {
108 5993a8f2 2003-11-23 devnull ai = j;
109 5993a8f2 2003-11-23 devnull aim = ai+m;
110 5993a8f2 2003-11-23 devnull do {
111 5993a8f2 2003-11-23 devnull if (aim->value > ai->value ||
112 5993a8f2 2003-11-23 devnull aim->value == ai->value &&
113 5993a8f2 2003-11-23 devnull aim->serial > ai->serial)
114 5993a8f2 2003-11-23 devnull break;
115 5993a8f2 2003-11-23 devnull w = *ai;
116 5993a8f2 2003-11-23 devnull *ai = *aim;
117 5993a8f2 2003-11-23 devnull *aim = w;
118 5993a8f2 2003-11-23 devnull
119 5993a8f2 2003-11-23 devnull aim = ai;
120 5993a8f2 2003-11-23 devnull ai -= m;
121 5993a8f2 2003-11-23 devnull } while (ai > a && aim >= ai);
122 5993a8f2 2003-11-23 devnull }
123 5993a8f2 2003-11-23 devnull }
124 5993a8f2 2003-11-23 devnull }
125 5993a8f2 2003-11-23 devnull
126 5993a8f2 2003-11-23 devnull static void
127 5993a8f2 2003-11-23 devnull unsort(struct line *f, int l, int *b)
128 5993a8f2 2003-11-23 devnull {
129 5993a8f2 2003-11-23 devnull int *a;
130 5993a8f2 2003-11-23 devnull int i;
131 5993a8f2 2003-11-23 devnull
132 5993a8f2 2003-11-23 devnull a = MALLOC(int, (l+1));
133 5993a8f2 2003-11-23 devnull for(i=1;i<=l;i++)
134 5993a8f2 2003-11-23 devnull a[f[i].serial] = f[i].value;
135 5993a8f2 2003-11-23 devnull for(i=1;i<=l;i++)
136 5993a8f2 2003-11-23 devnull b[i] = a[i];
137 5993a8f2 2003-11-23 devnull FREE(a);
138 5993a8f2 2003-11-23 devnull }
139 5993a8f2 2003-11-23 devnull
140 5993a8f2 2003-11-23 devnull static void
141 5993a8f2 2003-11-23 devnull prune(void)
142 5993a8f2 2003-11-23 devnull {
143 5993a8f2 2003-11-23 devnull int i,j;
144 5993a8f2 2003-11-23 devnull
145 5993a8f2 2003-11-23 devnull for(pref=0;pref<len[0]&&pref<len[1]&&
146 5993a8f2 2003-11-23 devnull file[0][pref+1].value==file[1][pref+1].value;
147 5993a8f2 2003-11-23 devnull pref++ ) ;
148 5993a8f2 2003-11-23 devnull for(suff=0;suff<len[0]-pref&&suff<len[1]-pref&&
149 5993a8f2 2003-11-23 devnull file[0][len[0]-suff].value==file[1][len[1]-suff].value;
150 5993a8f2 2003-11-23 devnull suff++) ;
151 5993a8f2 2003-11-23 devnull for(j=0;j<2;j++) {
152 5993a8f2 2003-11-23 devnull sfile[j] = file[j]+pref;
153 5993a8f2 2003-11-23 devnull slen[j] = len[j]-pref-suff;
154 5993a8f2 2003-11-23 devnull for(i=0;i<=slen[j];i++)
155 5993a8f2 2003-11-23 devnull sfile[j][i].serial = i;
156 5993a8f2 2003-11-23 devnull }
157 5993a8f2 2003-11-23 devnull }
158 5993a8f2 2003-11-23 devnull
159 5993a8f2 2003-11-23 devnull static void
160 5993a8f2 2003-11-23 devnull equiv(struct line *a, int n, struct line *b, int m, int *c)
161 5993a8f2 2003-11-23 devnull {
162 5993a8f2 2003-11-23 devnull int i, j;
163 5993a8f2 2003-11-23 devnull
164 5993a8f2 2003-11-23 devnull i = j = 1;
165 5993a8f2 2003-11-23 devnull while(i<=n && j<=m) {
166 5993a8f2 2003-11-23 devnull if(a[i].value < b[j].value)
167 5993a8f2 2003-11-23 devnull a[i++].value = 0;
168 5993a8f2 2003-11-23 devnull else if(a[i].value == b[j].value)
169 5993a8f2 2003-11-23 devnull a[i++].value = j;
170 5993a8f2 2003-11-23 devnull else
171 5993a8f2 2003-11-23 devnull j++;
172 5993a8f2 2003-11-23 devnull }
173 5993a8f2 2003-11-23 devnull while(i <= n)
174 5993a8f2 2003-11-23 devnull a[i++].value = 0;
175 5993a8f2 2003-11-23 devnull b[m+1].value = 0;
176 5993a8f2 2003-11-23 devnull j = 0;
177 5993a8f2 2003-11-23 devnull while(++j <= m) {
178 5993a8f2 2003-11-23 devnull c[j] = -b[j].serial;
179 5993a8f2 2003-11-23 devnull while(b[j+1].value == b[j].value) {
180 5993a8f2 2003-11-23 devnull j++;
181 5993a8f2 2003-11-23 devnull c[j] = b[j].serial;
182 5993a8f2 2003-11-23 devnull }
183 5993a8f2 2003-11-23 devnull }
184 5993a8f2 2003-11-23 devnull c[j] = -1;
185 5993a8f2 2003-11-23 devnull }
186 5993a8f2 2003-11-23 devnull
187 5993a8f2 2003-11-23 devnull static int
188 5993a8f2 2003-11-23 devnull newcand(int x, int y, int pred)
189 5993a8f2 2003-11-23 devnull {
190 5993a8f2 2003-11-23 devnull struct cand *q;
191 5993a8f2 2003-11-23 devnull
192 5993a8f2 2003-11-23 devnull clist = REALLOC(clist, struct cand, (clen+1));
193 5993a8f2 2003-11-23 devnull q = clist + clen;
194 5993a8f2 2003-11-23 devnull q->x = x;
195 5993a8f2 2003-11-23 devnull q->y = y;
196 5993a8f2 2003-11-23 devnull q->pred = pred;
197 5993a8f2 2003-11-23 devnull return clen++;
198 5993a8f2 2003-11-23 devnull }
199 5993a8f2 2003-11-23 devnull
200 5993a8f2 2003-11-23 devnull static int
201 5993a8f2 2003-11-23 devnull search(int *c, int k, int y)
202 5993a8f2 2003-11-23 devnull {
203 5993a8f2 2003-11-23 devnull int i, j, l;
204 5993a8f2 2003-11-23 devnull int t;
205 5993a8f2 2003-11-23 devnull
206 5993a8f2 2003-11-23 devnull if(clist[c[k]].y < y) /*quick look for typical case*/
207 5993a8f2 2003-11-23 devnull return k+1;
208 5993a8f2 2003-11-23 devnull i = 0;
209 5993a8f2 2003-11-23 devnull j = k+1;
210 5993a8f2 2003-11-23 devnull while((l=(i+j)/2) > i) {
211 5993a8f2 2003-11-23 devnull t = clist[c[l]].y;
212 5993a8f2 2003-11-23 devnull if(t > y)
213 5993a8f2 2003-11-23 devnull j = l;
214 5993a8f2 2003-11-23 devnull else if(t < y)
215 5993a8f2 2003-11-23 devnull i = l;
216 5993a8f2 2003-11-23 devnull else
217 5993a8f2 2003-11-23 devnull return l;
218 5993a8f2 2003-11-23 devnull }
219 5993a8f2 2003-11-23 devnull return l+1;
220 5993a8f2 2003-11-23 devnull }
221 5993a8f2 2003-11-23 devnull
222 5993a8f2 2003-11-23 devnull static int
223 5993a8f2 2003-11-23 devnull stone(int *a, int n, int *b, int *c)
224 5993a8f2 2003-11-23 devnull {
225 5993a8f2 2003-11-23 devnull int i, k,y;
226 5993a8f2 2003-11-23 devnull int j, l;
227 5993a8f2 2003-11-23 devnull int oldc, tc;
228 5993a8f2 2003-11-23 devnull int oldl;
229 5993a8f2 2003-11-23 devnull
230 5993a8f2 2003-11-23 devnull k = 0;
231 5993a8f2 2003-11-23 devnull c[0] = newcand(0,0,0);
232 5993a8f2 2003-11-23 devnull for(i=1; i<=n; i++) {
233 5993a8f2 2003-11-23 devnull j = a[i];
234 5993a8f2 2003-11-23 devnull if(j==0)
235 5993a8f2 2003-11-23 devnull continue;
236 5993a8f2 2003-11-23 devnull y = -b[j];
237 5993a8f2 2003-11-23 devnull oldl = 0;
238 5993a8f2 2003-11-23 devnull oldc = c[0];
239 5993a8f2 2003-11-23 devnull do {
240 5993a8f2 2003-11-23 devnull if(y <= clist[oldc].y)
241 5993a8f2 2003-11-23 devnull continue;
242 5993a8f2 2003-11-23 devnull l = search(c, k, y);
243 5993a8f2 2003-11-23 devnull if(l!=oldl+1)
244 5993a8f2 2003-11-23 devnull oldc = c[l-1];
245 5993a8f2 2003-11-23 devnull if(l<=k) {
246 5993a8f2 2003-11-23 devnull if(clist[c[l]].y <= y)
247 5993a8f2 2003-11-23 devnull continue;
248 5993a8f2 2003-11-23 devnull tc = c[l];
249 5993a8f2 2003-11-23 devnull c[l] = newcand(i,y,oldc);
250 5993a8f2 2003-11-23 devnull oldc = tc;
251 5993a8f2 2003-11-23 devnull oldl = l;
252 5993a8f2 2003-11-23 devnull } else {
253 5993a8f2 2003-11-23 devnull c[l] = newcand(i,y,oldc);
254 5993a8f2 2003-11-23 devnull k++;
255 5993a8f2 2003-11-23 devnull break;
256 5993a8f2 2003-11-23 devnull }
257 5993a8f2 2003-11-23 devnull } while((y=b[++j]) > 0);
258 5993a8f2 2003-11-23 devnull }
259 5993a8f2 2003-11-23 devnull return k;
260 5993a8f2 2003-11-23 devnull }
261 5993a8f2 2003-11-23 devnull
262 5993a8f2 2003-11-23 devnull static void
263 5993a8f2 2003-11-23 devnull unravel(int p)
264 5993a8f2 2003-11-23 devnull {
265 5993a8f2 2003-11-23 devnull int i;
266 5993a8f2 2003-11-23 devnull struct cand *q;
267 5993a8f2 2003-11-23 devnull
268 5993a8f2 2003-11-23 devnull for(i=0; i<=len[0]; i++) {
269 5993a8f2 2003-11-23 devnull if (i <= pref)
270 5993a8f2 2003-11-23 devnull J[i] = i;
271 5993a8f2 2003-11-23 devnull else if (i > len[0]-suff)
272 5993a8f2 2003-11-23 devnull J[i] = i+len[1]-len[0];
273 5993a8f2 2003-11-23 devnull else
274 5993a8f2 2003-11-23 devnull J[i] = 0;
275 5993a8f2 2003-11-23 devnull }
276 5993a8f2 2003-11-23 devnull for(q=clist+p;q->y!=0;q=clist+q->pred)
277 5993a8f2 2003-11-23 devnull J[q->x+pref] = q->y+pref;
278 5993a8f2 2003-11-23 devnull }
279 5993a8f2 2003-11-23 devnull
280 5993a8f2 2003-11-23 devnull static void
281 5993a8f2 2003-11-23 devnull output(void)
282 5993a8f2 2003-11-23 devnull {
283 5993a8f2 2003-11-23 devnull int m, i0, i1, j0, j1;
284 5993a8f2 2003-11-23 devnull
285 5993a8f2 2003-11-23 devnull m = len[0];
286 5993a8f2 2003-11-23 devnull J[0] = 0;
287 5993a8f2 2003-11-23 devnull J[m+1] = len[1]+1;
288 5993a8f2 2003-11-23 devnull if (mode != 'e') {
289 5993a8f2 2003-11-23 devnull for (i0 = 1; i0 <= m; i0 = i1+1) {
290 5993a8f2 2003-11-23 devnull while (i0 <= m && J[i0] == J[i0-1]+1)
291 5993a8f2 2003-11-23 devnull i0++;
292 5993a8f2 2003-11-23 devnull j0 = J[i0-1]+1;
293 5993a8f2 2003-11-23 devnull i1 = i0-1;
294 5993a8f2 2003-11-23 devnull while (i1 < m && J[i1+1] == 0)
295 5993a8f2 2003-11-23 devnull i1++;
296 5993a8f2 2003-11-23 devnull j1 = J[i1+1]-1;
297 5993a8f2 2003-11-23 devnull J[i1] = j1;
298 5993a8f2 2003-11-23 devnull change(i0, i1, j0, j1);
299 5993a8f2 2003-11-23 devnull }
300 5993a8f2 2003-11-23 devnull }
301 5993a8f2 2003-11-23 devnull else {
302 5993a8f2 2003-11-23 devnull for (i0 = m; i0 >= 1; i0 = i1-1) {
303 5993a8f2 2003-11-23 devnull while (i0 >= 1 && J[i0] == J[i0+1]-1 && J[i0])
304 5993a8f2 2003-11-23 devnull i0--;
305 5993a8f2 2003-11-23 devnull j0 = J[i0+1]-1;
306 5993a8f2 2003-11-23 devnull i1 = i0+1;
307 5993a8f2 2003-11-23 devnull while (i1 > 1 && J[i1-1] == 0)
308 5993a8f2 2003-11-23 devnull i1--;
309 5993a8f2 2003-11-23 devnull j1 = J[i1-1]+1;
310 5993a8f2 2003-11-23 devnull J[i1] = j1;
311 5993a8f2 2003-11-23 devnull change(i1 , i0, j1, j0);
312 5993a8f2 2003-11-23 devnull }
313 5993a8f2 2003-11-23 devnull }
314 5993a8f2 2003-11-23 devnull if (m == 0)
315 5993a8f2 2003-11-23 devnull change(1, 0, 1, len[1]);
316 4ac5f249 2005-01-26 devnull flushchanges();
317 5993a8f2 2003-11-23 devnull }
318 5993a8f2 2003-11-23 devnull
319 5993a8f2 2003-11-23 devnull #define BUF 4096
320 5993a8f2 2003-11-23 devnull static int
321 5993a8f2 2003-11-23 devnull cmp(Biobuf* b1, Biobuf* b2)
322 5993a8f2 2003-11-23 devnull {
323 5993a8f2 2003-11-23 devnull int n;
324 5993a8f2 2003-11-23 devnull uchar buf1[BUF], buf2[BUF];
325 5993a8f2 2003-11-23 devnull int f1, f2;
326 5993a8f2 2003-11-23 devnull vlong nc = 1;
327 5993a8f2 2003-11-23 devnull uchar *b1s, *b1e, *b2s, *b2e;
328 5993a8f2 2003-11-23 devnull
329 5993a8f2 2003-11-23 devnull f1 = Bfildes(b1);
330 5993a8f2 2003-11-23 devnull f2 = Bfildes(b2);
331 5993a8f2 2003-11-23 devnull seek(f1, 0, 0);
332 5993a8f2 2003-11-23 devnull seek(f2, 0, 0);
333 5993a8f2 2003-11-23 devnull b1s = b1e = buf1;
334 5993a8f2 2003-11-23 devnull b2s = b2e = buf2;
335 5993a8f2 2003-11-23 devnull for(;;){
336 5993a8f2 2003-11-23 devnull if(b1s >= b1e){
337 5993a8f2 2003-11-23 devnull if(b1s >= &buf1[BUF])
338 5993a8f2 2003-11-23 devnull b1s = buf1;
339 5993a8f2 2003-11-23 devnull n = read(f1, b1s, &buf1[BUF] - b1s);
340 5993a8f2 2003-11-23 devnull b1e = b1s + n;
341 5993a8f2 2003-11-23 devnull }
342 5993a8f2 2003-11-23 devnull if(b2s >= b2e){
343 5993a8f2 2003-11-23 devnull if(b2s >= &buf2[BUF])
344 5993a8f2 2003-11-23 devnull b2s = buf2;
345 5993a8f2 2003-11-23 devnull n = read(f2, b2s, &buf2[BUF] - b2s);
346 5993a8f2 2003-11-23 devnull b2e = b2s + n;
347 5993a8f2 2003-11-23 devnull }
348 5993a8f2 2003-11-23 devnull n = b2e - b2s;
349 5993a8f2 2003-11-23 devnull if(n > b1e - b1s)
350 5993a8f2 2003-11-23 devnull n = b1e - b1s;
351 5993a8f2 2003-11-23 devnull if(n <= 0)
352 5993a8f2 2003-11-23 devnull break;
353 5993a8f2 2003-11-23 devnull if(memcmp((void *)b1s, (void *)b2s, n) != 0){
354 5993a8f2 2003-11-23 devnull return 1;
355 5993a8f2 2003-11-23 devnull }
356 5993a8f2 2003-11-23 devnull nc += n;
357 5993a8f2 2003-11-23 devnull b1s += n;
358 5993a8f2 2003-11-23 devnull b2s += n;
359 5993a8f2 2003-11-23 devnull }
360 5993a8f2 2003-11-23 devnull if(b1e - b1s == b2e - b2s)
361 5993a8f2 2003-11-23 devnull return 0;
362 5993a8f2 2003-11-23 devnull return 1;
363 5993a8f2 2003-11-23 devnull }
364 5993a8f2 2003-11-23 devnull
365 5993a8f2 2003-11-23 devnull void
366 5993a8f2 2003-11-23 devnull diffreg(char *f, char *t)
367 5993a8f2 2003-11-23 devnull {
368 5993a8f2 2003-11-23 devnull Biobuf *b0, *b1;
369 5993a8f2 2003-11-23 devnull int k;
370 5993a8f2 2003-11-23 devnull
371 5993a8f2 2003-11-23 devnull binary = 0;
372 5993a8f2 2003-11-23 devnull b0 = prepare(0, f);
373 5993a8f2 2003-11-23 devnull if (!b0)
374 5993a8f2 2003-11-23 devnull return;
375 5993a8f2 2003-11-23 devnull b1 = prepare(1, t);
376 5993a8f2 2003-11-23 devnull if (!b1) {
377 5993a8f2 2003-11-23 devnull FREE(file[0]);
378 5993a8f2 2003-11-23 devnull Bterm(b0);
379 5993a8f2 2003-11-23 devnull return;
380 5993a8f2 2003-11-23 devnull }
381 5993a8f2 2003-11-23 devnull if (binary){
382 5993a8f2 2003-11-23 devnull // could use b0 and b1 but this is simpler.
383 5993a8f2 2003-11-23 devnull if (cmp(b0, b1))
384 5993a8f2 2003-11-23 devnull print("binary files %s %s differ\n", f, t);
385 5993a8f2 2003-11-23 devnull Bterm(b0);
386 5993a8f2 2003-11-23 devnull Bterm(b1);
387 5993a8f2 2003-11-23 devnull return;
388 5993a8f2 2003-11-23 devnull }
389 5993a8f2 2003-11-23 devnull clen = 0;
390 5993a8f2 2003-11-23 devnull prune();
391 5993a8f2 2003-11-23 devnull sort(sfile[0], slen[0]);
392 5993a8f2 2003-11-23 devnull sort(sfile[1], slen[1]);
393 5993a8f2 2003-11-23 devnull
394 5993a8f2 2003-11-23 devnull member = (int *)file[1];
395 5993a8f2 2003-11-23 devnull equiv(sfile[0], slen[0], sfile[1], slen[1], member);
396 5993a8f2 2003-11-23 devnull member = REALLOC(member, int, slen[1]+2);
397 5993a8f2 2003-11-23 devnull
398 5993a8f2 2003-11-23 devnull class = (int *)file[0];
399 5993a8f2 2003-11-23 devnull unsort(sfile[0], slen[0], class);
400 5993a8f2 2003-11-23 devnull class = REALLOC(class, int, slen[0]+2);
401 5993a8f2 2003-11-23 devnull
402 5993a8f2 2003-11-23 devnull klist = MALLOC(int, slen[0]+2);
403 5993a8f2 2003-11-23 devnull clist = MALLOC(struct cand, 1);
404 5993a8f2 2003-11-23 devnull k = stone(class, slen[0], member, klist);
405 5993a8f2 2003-11-23 devnull FREE(member);
406 5993a8f2 2003-11-23 devnull FREE(class);
407 5993a8f2 2003-11-23 devnull
408 5993a8f2 2003-11-23 devnull J = MALLOC(int, len[0]+2);
409 5993a8f2 2003-11-23 devnull unravel(klist[k]);
410 5993a8f2 2003-11-23 devnull FREE(clist);
411 5993a8f2 2003-11-23 devnull FREE(klist);
412 5993a8f2 2003-11-23 devnull
413 5993a8f2 2003-11-23 devnull ixold = MALLOC(long, len[0]+2);
414 5993a8f2 2003-11-23 devnull ixnew = MALLOC(long, len[1]+2);
415 5993a8f2 2003-11-23 devnull Bseek(b0, 0, 0); Bseek(b1, 0, 0);
416 5993a8f2 2003-11-23 devnull check(b0, b1);
417 5993a8f2 2003-11-23 devnull output();
418 5993a8f2 2003-11-23 devnull FREE(J); FREE(ixold); FREE(ixnew);
419 5993a8f2 2003-11-23 devnull Bterm(b0); Bterm(b1); /* ++++ */
420 5993a8f2 2003-11-23 devnull }