Blob


1 /*
2 * Copyright (c) 2020 Neels Hofmeyr <neels@hofmeyr.de>
3 *
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
17 #define DEBUG 0
19 #if DEBUG
20 #include <stdio.h>
21 #include <unistd.h>
22 #define print(args...) fprintf(stderr, ##args)
23 #define debug print
24 #define debug_dump dump
25 #define debug_dump_atom dump_atom
26 #define debug_dump_atoms dump_atoms
28 static inline void
29 print_atom_byte(unsigned char c) {
30 if (c == '\r')
31 print("\\r");
32 else if (c == '\n')
33 print("\\n");
34 else if ((c < 32 || c >= 127) && (c != '\t'))
35 print("\\x%02x", c);
36 else
37 print("%c", c);
38 }
40 static inline void
41 dump_atom(const struct diff_data *left, const struct diff_data *right,
42 const struct diff_atom *atom)
43 {
44 if (!atom) {
45 print("NULL atom\n");
46 return;
47 }
48 if (left)
49 print(" %3u", diff_atom_root_idx(left, atom));
50 if (right && atom->patience.pos_in_other)
51 print(" %3u",
52 diff_atom_root_idx(right, atom->patience.pos_in_other));
54 print(" %s%s '",
55 atom->patience.unique_here ? "u" : " ",
56 atom->patience.unique_in_both ? "c" : " ");
57 if (atom->at == NULL) {
58 off_t remain = atom->len;
59 if (fseek(atom->d->root->f, atom->pos, SEEK_SET) == -1)
60 abort(); /* cannot return error */
61 while (remain > 0) {
62 char buf[16];
63 size_t r;
64 int i;
65 r = fread(buf, 1, MIN(remain, sizeof(buf)),
66 atom->d->root->f);
67 if (r == -1)
68 abort(); /* cannot return error */
69 if (r == 0)
70 break;
71 remain -= r;
72 for (i = 0; i < r; i++)
73 print_atom_byte(buf[i]);
74 }
75 } else {
76 const char *s;
77 for (s = atom->at; s < (const char*)(atom->at + atom->len); s++)
78 print_atom_byte(*s);
79 }
80 print("'\n");
81 }
83 static inline void
84 dump_atoms(const struct diff_data *d, struct diff_atom *atom,
85 unsigned int count)
86 {
87 if (count > 42) {
88 dump_atoms(d, atom, 20);
89 print("[%u lines skipped]\n", count - 20 - 20);
90 dump_atoms(d, atom + count - 20, 20);
91 return;
92 } else {
93 struct diff_atom *i;
94 foreach_diff_atom(i, atom, count) {
95 dump_atom(d, NULL, i);
96 }
97 }
98 }
100 static inline void
101 dump(struct diff_data *d)
103 dump_atoms(d, d->atoms.head, d->atoms.len);
106 /* kd is a quadratic space myers matrix from the original Myers algorithm.
107 * kd_forward and kd_backward are linear slices of a myers matrix from the Myers
108 * Divide algorithm.
109 */
110 static inline void
111 dump_myers_graph(const struct diff_data *l, const struct diff_data *r,
112 int *kd, int *kd_forward, int kd_forward_d,
113 int *kd_backward, int kd_backward_d)
115 #define COLOR_YELLOW "\033[1;33m"
116 #define COLOR_GREEN "\033[1;32m"
117 #define COLOR_BLUE "\033[1;34m"
118 #define COLOR_RED "\033[1;31m"
119 #define COLOR_END "\033[0;m"
120 int x;
121 int y;
122 print(" ");
123 for (x = 0; x <= l->atoms.len; x++)
124 print("%2d", x % 100);
125 print("\n");
127 for (y = 0; y <= r->atoms.len; y++) {
128 print("%3d ", y);
129 for (x = 0; x <= l->atoms.len; x++) {
131 /* print d advancements from kd, if any. */
132 char label = 'o';
133 char *color = NULL;
134 if (kd) {
135 int max = l->atoms.len + r->atoms.len;
136 size_t kd_len = max + 1 + max;
137 int *kd_pos = kd;
138 int di;
139 #define xk_to_y(X, K) ((X) - (K))
140 for (di = 0; di < max; di++) {
141 int ki;
142 for (ki = di; ki >= -di; ki -= 2) {
143 if (x != kd_pos[ki]
144 || y != xk_to_y(x, ki))
145 continue;
146 label = '0' + (di % 10);
147 color = COLOR_YELLOW;
148 break;
150 if (label != 'o')
151 break;
152 kd_pos += kd_len;
155 if (kd_forward && kd_forward_d >= 0) {
156 #define xc_to_y(X, C, DELTA) ((X) - (C) + (DELTA))
157 int ki;
158 for (ki = kd_forward_d;
159 ki >= -kd_forward_d;
160 ki -= 2) {
161 if (x != kd_forward[ki])
162 continue;
163 if (y != xk_to_y(x, ki))
164 continue;
165 label = 'F';
166 color = COLOR_GREEN;
167 break;
170 if (kd_backward && kd_backward_d >= 0) {
171 int delta = (int)r->atoms.len
172 - (int)l->atoms.len;
173 int ki;
174 for (ki = kd_backward_d;
175 ki >= -kd_backward_d;
176 ki -= 2) {
177 if (x != kd_backward[ki])
178 continue;
179 if (y != xc_to_y(x, ki, delta))
180 continue;
181 if (label == 'o') {
182 label = 'B';
183 color = COLOR_BLUE;
184 } else {
185 label = 'X';
186 color = COLOR_RED;
188 break;
191 if (color)
192 print("%s", color);
193 print("%c", label);
194 if (color)
195 print("%s", COLOR_END);
196 if (x < l->atoms.len)
197 print("-");
199 print("\n");
200 if (y == r->atoms.len)
201 break;
203 print(" ");
204 for (x = 0; x < l->atoms.len; x++) {
205 bool same;
206 diff_atom_same(&same, &l->atoms.head[x],
207 &r->atoms.head[y]);
208 if (same)
209 print("|\\");
210 else
211 print("| ");
213 print("|\n");
217 static inline void
218 debug_dump_myers_graph(const struct diff_data *l, const struct diff_data *r,
219 int *kd, int *kd_forward, int kd_forward_d,
220 int *kd_backward, int kd_backward_d)
222 if (l->atoms.len > 99 || r->atoms.len > 99)
223 return;
224 dump_myers_graph(l, r, kd, kd_forward, kd_forward_d,
225 kd_backward, kd_backward_d);
228 #else
229 #define debug(args...)
230 #define debug_dump(args...)
231 #define debug_dump_atom(args...)
232 #define debug_dump_atoms(args...)
233 #define debug_dump_myers_graph(args...)
234 #endif