3 * The bulk of this software is derived from Plan 9 and is thus distributed
4 * under the Lucent Public License, Version 1.02, reproduced below.
6 * ===================================================================
8 * Lucent Public License Version 1.02
10 * THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS PUBLIC
11 * LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE
12 * PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
16 * "Contribution" means:
18 * a. in the case of Lucent Technologies Inc. ("LUCENT"), the Original
20 * b. in the case of each Contributor,
22 * i. changes to the Program, and
23 * ii. additions to the Program;
25 * where such changes and/or additions to the Program were added to the
26 * Program by such Contributor itself or anyone acting on such
27 * Contributor's behalf, and the Contributor explicitly consents, in
28 * accordance with Section 3C, to characterization of the changes and/or
29 * additions as Contributions.
31 * "Contributor" means LUCENT and any other entity that has Contributed a
32 * Contribution to the Program.
34 * "Distributor" means a Recipient that distributes the Program,
35 * modifications to the Program, or any part thereof.
37 * "Licensed Patents" mean patent claims licensable by a Contributor
38 * which are necessarily infringed by the use or sale of its Contribution
39 * alone or when combined with the Program.
41 * "Original Program" means the original version of the software
42 * accompanying this Agreement as released by LUCENT, including source
43 * code, object code and documentation, if any.
45 * "Program" means the Original Program and Contributions or any part
48 * "Recipient" means anyone who receives the Program under this
49 * Agreement, including all Contributors.
53 * a. Subject to the terms of this Agreement, each Contributor hereby
54 * grants Recipient a non-exclusive, worldwide, royalty-free copyright
55 * license to reproduce, prepare derivative works of, publicly display,
56 * publicly perform, distribute and sublicense the Contribution of such
57 * Contributor, if any, and such derivative works, in source code and
60 * b. Subject to the terms of this Agreement, each Contributor hereby
61 * grants Recipient a non-exclusive, worldwide, royalty-free patent
62 * license under Licensed Patents to make, use, sell, offer to sell,
63 * import and otherwise transfer the Contribution of such Contributor, if
64 * any, in source code and object code form. The patent license granted
65 * by a Contributor shall also apply to the combination of the
66 * Contribution of that Contributor and the Program if, at the time the
67 * Contribution is added by the Contributor, such addition of the
68 * Contribution causes such combination to be covered by the Licensed
69 * Patents. The patent license granted by a Contributor shall not apply
70 * to (i) any other combinations which include the Contribution, nor to
71 * (ii) Contributions of other Contributors. No hardware per se is
74 * c. Recipient understands that although each Contributor grants the
75 * licenses to its Contributions set forth herein, no assurances are
76 * provided by any Contributor that the Program does not infringe the
77 * patent or other intellectual property rights of any other entity. Each
78 * Contributor disclaims any liability to Recipient for claims brought by
79 * any other entity based on infringement of intellectual property rights
80 * or otherwise. As a condition to exercising the rights and licenses
81 * granted hereunder, each Recipient hereby assumes sole responsibility
82 * to secure any other intellectual property rights needed, if any. For
83 * example, if a third party patent license is required to allow
84 * Recipient to distribute the Program, it is Recipient's responsibility
85 * to acquire that license before distributing the Program.
87 * d. Each Contributor represents that to its knowledge it has sufficient
88 * copyright rights in its Contribution, if any, to grant the copyright
89 * license set forth in this Agreement.
93 * A. Distributor may choose to distribute the Program in any form under
94 * this Agreement or under its own license agreement, provided that:
96 * a. it complies with the terms and conditions of this Agreement;
98 * b. if the Program is distributed in source code or other tangible
99 * form, a copy of this Agreement or Distributor's own license agreement
100 * is included with each copy of the Program; and
102 * c. if distributed under Distributor's own license agreement, such
105 * i. effectively disclaims on behalf of all Contributors all warranties
106 * and conditions, express and implied, including warranties or
107 * conditions of title and non-infringement, and implied warranties or
108 * conditions of merchantability and fitness for a particular purpose;
109 * ii. effectively excludes on behalf of all Contributors all liability
110 * for damages, including direct, indirect, special, incidental and
111 * consequential damages, such as lost profits; and
112 * iii. states that any provisions which differ from this Agreement are
113 * offered by that Contributor alone and not by any other party.
115 * B. Each Distributor must include the following in a conspicuous
116 * location in the Program:
118 * Copyright (C) 2003, Lucent Technologies Inc. and others. All Rights
121 * C. In addition, each Contributor must identify itself as the
122 * originator of its Contribution in a manner that reasonably allows
123 * subsequent Recipients to identify the originator of the Contribution.
124 * Also, each Contributor must agree that the additions and/or changes
125 * are intended to be a Contribution. Once a Contribution is contributed,
126 * it may not thereafter be revoked.
128 * 4. COMMERCIAL DISTRIBUTION
130 * Commercial distributors of software may accept certain
131 * responsibilities with respect to end users, business partners and the
132 * like. While this license is intended to facilitate the commercial use
133 * of the Program, the Distributor who includes the Program in a
134 * commercial product offering should do so in a manner which does not
135 * create potential liability for Contributors. Therefore, if a
136 * Distributor includes the Program in a commercial product offering,
137 * such Distributor ("Commercial Distributor") hereby agrees to defend
138 * and indemnify every Contributor ("Indemnified Contributor") against
139 * any losses, damages and costs (collectively"Losses") arising from
140 * claims, lawsuits and other legal actions brought by a third party
141 * against the Indemnified Contributor to the extent caused by the acts
142 * or omissions of such Commercial Distributor in connection with its
143 * distribution of the Program in a commercial product offering. The
144 * obligations in this section do not apply to any claims or Losses
145 * relating to any actual or alleged intellectual property infringement.
146 * In order to qualify, an Indemnified Contributor must: a) promptly
147 * notify the Commercial Distributor in writing of such claim, and b)
148 * allow the Commercial Distributor to control, and cooperate with the
149 * Commercial Distributor in, the defense and any related settlement
150 * negotiations. The Indemnified Contributor may participate in any such
151 * claim at its own expense.
153 * For example, a Distributor might include the Program in a commercial
154 * product offering, Product X. That Distributor is then a Commercial
155 * Distributor. If that Commercial Distributor then makes performance
156 * claims, or offers warranties related to Product X, those performance
157 * claims and warranties are such Commercial Distributor's responsibility
158 * alone. Under this section, the Commercial Distributor would have to
159 * defend claims against the Contributors related to those performance
160 * claims and warranties, and if a court requires any Contributor to pay
161 * any damages as a result, the Commercial Distributor must pay those
166 * EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS
167 * PROVIDED ON AN"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
168 * KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY
169 * WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY
170 * OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely
171 * responsible for determining the appropriateness of using and
172 * distributing the Program and assumes all risks associated with its
173 * exercise of rights under this Agreement, including but not limited to
174 * the risks and costs of program errors, compliance with applicable
175 * laws, damage to or loss of data, programs or equipment, and
176 * unavailability or interruption of operations.
178 * 6. DISCLAIMER OF LIABILITY
180 * EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR
181 * ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT,
182 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING
183 * WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF
184 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
185 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR
186 * DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
187 * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
191 * Recipient agrees that Recipient alone is responsible for compliance
192 * with the United States export administration regulations (and the
193 * export control laws and regulation of any other countries).
197 * If any provision of this Agreement is invalid or unenforceable under
198 * applicable law, it shall not affect the validity or enforceability of
199 * the remainder of the terms of this Agreement, and without further
200 * action by the parties hereto, such provision shall be reformed to the
201 * minimum extent necessary to make such provision valid and enforceable.
203 * If Recipient institutes patent litigation against a Contributor with
204 * respect to a patent applicable to software (including a cross-claim or
205 * counterclaim in a lawsuit), then any patent licenses granted by that
206 * Contributor to such Recipient under this Agreement shall terminate as
207 * of the date such litigation is filed. In addition, if Recipient
208 * institutes patent litigation against any entity (including a
209 * cross-claim or counterclaim in a lawsuit) alleging that the Program
210 * itself (excluding combinations of the Program with other software or
211 * hardware) infringes such Recipient's patent(s), then such Recipient's
212 * rights granted under Section 2(b) shall terminate as of the date such
213 * litigation is filed.
215 * All Recipient's rights under this Agreement shall terminate if it
216 * fails to comply with any of the material terms or conditions of this
217 * Agreement and does not cure such failure in a reasonable period of
218 * time after becoming aware of such noncompliance. If all Recipient's
219 * rights under this Agreement terminate, Recipient agrees to cease use
220 * and distribution of the Program as soon as reasonably practicable.
221 * However, Recipient's obligations under this Agreement and any licenses
222 * granted by Recipient relating to the Program shall continue and
225 * LUCENT may publish new versions (including revisions) of this
226 * Agreement from time to time. Each new version of the Agreement will be
227 * given a distinguishing version number. The Program (including
228 * Contributions) may always be distributed subject to the version of the
229 * Agreement under which it was received. In addition, after a new
230 * version of the Agreement is published, Contributor may elect to
231 * distribute the Program (including its Contributions) under the new
232 * version. No one other than LUCENT has the right to modify this
233 * Agreement. Except as expressly stated in Sections 2(a) and 2(b) above,
234 * Recipient receives no rights or licenses to the intellectual property
235 * of any Contributor under this Agreement, whether expressly, by
236 * implication, estoppel or otherwise. All rights in the Program not
237 * expressly granted under this Agreement are reserved.
239 * This Agreement is governed by the laws of the State of New York and
240 * the intellectual property laws of the United States of America. No
241 * party to this Agreement will bring a legal action under this Agreement
242 * more than one year after the cause of action arose. Each party waives
243 * its rights to a jury trial in any resulting litigation.
263 struct line *sfile[2]; // shortened by pruning common prefix and suffix
265 int pref, suff; // length of prefix and suffix
266 int *class; // will be overlaid on file[0]
267 int *member; // will be overlaid on file[1]
268 int *klist; // will be overlaid on file[0] after class
269 struct cand *clist; // merely a free storage pot for candidates
271 int *J; // will be overlaid on class
274 #define low(x) (x&((1L<<HALFLONG)-1))
275 #define high(x) (x>>HALFLONG)
278 * Returns a computed hash for a given string.
279 * Hashing has the effect of arranging line in 7-bit bytes and then summing 1-s
280 * complement in 16-bit hunks.
281 * @param line The line of a buffer to hash.
283 static int hash(char *line) {
294 sum += (long)*p++ << (shift &= (HALFLONG-1));
297 sum = low(sum) + high(sum);
298 return ((short)low(sum) + (short)high(sum));
302 * Hashes each line in the given string buffer and stores it internally.
303 * @param i 0 for diff 'from', 1 for diff 'to'.
304 * @param buf The string buffer to prepare from.
306 void prepare(int i, const char *buf) {
309 char bufcpy[strlen(buf)];
312 p = malloc(3*sizeof(struct line));
314 strncpy(bufcpy, buf, strlen(buf));
315 bufcpy[strlen(buf)] = 0;
316 l = strtok(bufcpy, "\n");
318 p = realloc(p, (++j+3)*sizeof(struct line));
319 p[j].value = hash(l);
320 l = strtok(NULL, "\n");
327 * Adds to the count of lines added and removed for this diff.
328 * Diff 'from' chunks are counted as lines removed and diff 'to' chunks are
329 * counted as lines added.
330 * @param a The diff 'from' chunk's beginning line number.
331 * @param b The diff 'from' chunk's ending line number.
332 * @param c The diff 'to' chunk's beginning line number.
333 * @param d The diff 'to' chunk's ending line number.
334 * @param added Int pointer to the running number of lines added for this diff.
335 * @param removed Int pointer to the running number of lines removed for this
338 void change(int a, int b, int c, int d, int *added, int *removed) {
347 *removed += b - a + 1;
358 * diff - differential file comparison
360 * Uses an algorithm due to Harold Stone, which finds
361 * a pair of longest identical subsequences in the two
364 * The major goal is to generate the match vector J.
365 * J[i] is the index of the line in file1 corresponding
366 * to line i file0. J[i] = 0 if there is no
367 * such line in file1.
369 * Lines are hashed so as to work in core. All potential
370 * matches are located by sorting the lines of each file
371 * on the hash (called value). In particular, this
372 * collects the equivalence classes in file1 together.
373 * Subroutine equiv replaces the value of each line in
374 * file0 by the index of the first element of its
375 * matching equivalence in (the reordered) file1.
376 * To save space equiv squeezes file1 into a single
377 * array member in which the equivalence classes
378 * are simply concatenated, except that their first
379 * members are flagged by changing sign.
381 * Next the indices that point into member are unsorted into
382 * array class according to the original order of file0.
384 * The cleverness lies in routine stone. This marches
385 * through the lines of file0, developing a vector klist
386 * of "k-candidates". At step i a k-candidate is a matched
387 * pair of lines x,y (x in file0 y in file1) such that
388 * there is a common subsequence of lenght k
389 * between the first i lines of file0 and the first y
390 * lines of file1, but there is no such subsequence for
391 * any smaller y. x is the earliest possible mate to y
392 * that occurs in such a subsequence.
394 * Whenever any of the members of the equivalence class of
395 * lines in file1 matable to a line in file0 has serial number
396 * less than the y of some k-candidate, that k-candidate
397 * with the smallest such y is replaced. The new
398 * k-candidate is chained (via pred) to the current
399 * k-1 candidate so that the actual subsequence can
400 * be recovered. When a member has serial number greater
401 * that the y of all k-candidates, the klist is extended.
402 * At the end, the longest subsequence is pulled out
403 * and placed in the array J by unravel.
405 * With J in hand, the matches there recorded are
406 * check'ed against reality to assure that no spurious
407 * matches have crept in due to hashing. If they have,
408 * they are broken, and "jackpot " is recorded--a harmless
409 * matter except that a true match for a spuriously
410 * mated line may now be unnecessarily reported as a change.
412 * Much of the complexity of the program comes simply
413 * from trying to minimize core utilization and
414 * maximize the range of doable problems by dynamically
415 * allocating what is needed and reusing what is not.
416 * The core requirements for problems larger than somewhat
417 * are (in words) 2*length(file0) + length(file1) +
418 * 3*(number of k-candidates installed), typically about
419 * 6n words for files of length n.
422 static void sort(struct line *a, int n) { /*shellsort CACM #201*/
424 struct line *ai, *aim, *j, *k;
429 for (i = 1; i <= n; i *= 2)
431 for (m /= 2; m != 0; m /= 2) {
433 for (j = a+1; j <= k; j++) {
437 if (aim->value > ai->value ||
438 aim->value == ai->value &&
439 aim->serial > ai->serial)
447 } while (ai > a && aim >= ai);
452 static void unsort(struct line *f, int l, int *b) {
456 a = malloc((l+1)*sizeof(int));
458 a[f[i].serial] = f[i].value;
464 static void prune(void) {
467 for(pref=0;pref<len[0]&&pref<len[1]&&
468 file[0][pref+1].value==file[1][pref+1].value;
470 for(suff=0;suff<len[0]-pref&&suff<len[1]-pref&&
471 file[0][len[0]-suff].value==file[1][len[1]-suff].value;
474 sfile[j] = file[j]+pref;
475 slen[j] = len[j]-pref-suff;
476 for(i=0;i<=slen[j];i++)
477 sfile[j][i].serial = i;
481 static void equiv(struct line *a, int n, struct line *b, int m, int *c) {
485 while(i<=n && j<=m) {
486 if(a[i].value < b[j].value)
488 else if(a[i].value == b[j].value)
499 while(b[j+1].value == b[j].value) {
507 static int newcand(int x, int y, int pred) {
510 clist = realloc(clist, (clen+1)*sizeof(struct cand));
518 static int search(int *c, int k, int y) {
522 if(clist[c[k]].y < y) /*quick look for typical case*/
526 while((l=(i+j)/2) > i) {
538 static int stone(int *a, int n, int *b, int *c) {
545 c[0] = newcand(0,0,0);
546 for(i=1; i<=n; i++) {
554 if(y <= clist[oldc].y)
560 if(clist[c[l]].y <= y)
563 c[l] = newcand(i,y,oldc);
567 c[l] = newcand(i,y,oldc);
571 } while((y=b[++j]) > 0);
576 static void unravel(int p) {
580 for(i=0; i<=len[0]; i++) {
583 else if (i > len[0]-suff)
584 J[i] = i+len[1]-len[0];
588 for(q=clist+p;q->y!=0;q=clist+q->pred)
589 J[q->x+pref] = q->y+pref;
592 static void output(int *added, int *removed) {
593 int m, i0, i1, j0, j1;
598 for (i0 = 1; i0 <= m; i0 = i1+1) {
599 while (i0 <= m && J[i0] == J[i0-1]+1)
603 while (i1 < m && J[i1+1] == 0)
607 change(i0, i1, j0, j1, added, removed);
610 change(1, 0, 1, len[1], added, removed);
613 void ohcount_calc_diff(const char *from, const char *to, int *added,
621 sort(sfile[0], slen[0]);
622 sort(sfile[1], slen[1]);
624 member = (int *)file[1];
625 equiv(sfile[0], slen[0], sfile[1], slen[1], member);
626 member = realloc(member, (slen[1]+2)*sizeof(int));
628 class = (int *)file[0];
629 unsort(sfile[0], slen[0], class);
630 class = realloc(class, (slen[0]+2)*sizeof(int));
632 klist = malloc((slen[0]+2)*sizeof(int));
633 clist = malloc(sizeof(struct cand));
634 k = stone(class, slen[0], member, klist);
638 J = malloc((len[0]+2)*sizeof(int));
643 *added = *removed = 0;
644 output(added, removed);