raw
vtools_genesis          1 
vtools_genesis 2 #include <stdlib.h>
vtools_genesis 3 #include "diff.h"
vtools_genesis 4
vtools_genesis 5 /* Print a label for a context diff, with a file name and date or a
vtools_genesis 6 label. */
vtools_genesis 7
vdiff_keccak 8 const char bb_hexdigits_upcase[] = "0123456789ABCDEF";
vdiff_keccak 9 char *bin2hex(char *p, const char *cp, int count) {
vdiff_keccak 10 while (count) {
vdiff_keccak 11 unsigned char c = *cp++;
vdiff_keccak 12 /* put lowercase hex digits */
vdiff_keccak 13 *p++ = 0x20 | bb_hexdigits_upcase[c >> 4];
vdiff_keccak 14 *p++ = 0x20 | bb_hexdigits_upcase[c & 0xf];
vdiff_keccak 15 count--;
vdiff_keccak 16 }
vdiff_keccak 17 return p;
vdiff_keccak 18 }
vdiff_keccak 19
vtools_genesis 20 static void
vtools_genesis 21 print_context_label(char const *mark,
vtools_genesis 22 struct file_data *inf,
vtools_genesis 23 char const *name,
vtools_genesis 24 char const *label) {
vtools_genesis 25 if (label)
vtools_genesis 26 fprintf(outfile, "%s %s\n", mark, label);
vtools_genesis 27 else {
vdiff_keccak 28 if (inf->desc >= 0) {
vdiff_keccak 29 char buf[(64 * 2) + 1] = {0};
vdiff_keccak 30 bin2hex(buf, (char*) inf->hash, 64);
vdiff_keccak 31 fprintf(outfile, "%s %s %s\n", mark, name, buf);
vdiff_keccak 32 } else {
vdiff_keccak 33 fprintf(outfile, "%s %s false\n", mark, name);
vdiff_keccak 34 }
vtools_genesis 35 }
vtools_genesis 36 }
vtools_genesis 37
vtools_genesis 38 /* Print a header for a context diff, with the file names and dates. */
vtools_genesis 39
vtools_genesis 40 void
vtools_genesis 41 print_context_header(struct file_data inf[], char const *const *names) {
vtools_genesis 42 print_context_label("---", &inf[0], names[0], file_label[0]);
vtools_genesis 43 print_context_label("+++", &inf[1], names[1], file_label[1]);
vtools_genesis 44 }
vtools_genesis 45
vtools_genesis 46 /* Print an edit script in context format. */
vtools_genesis 47
vtools_genesis 48 void
vtools_genesis 49 print_context_script(struct change *script) {
vtools_genesis 50 struct change *e;
vtools_genesis 51 for (e = script; e; e = e->link)
vtools_genesis 52 e->ignore = false;
vtools_genesis 53
vtools_genesis 54 print_script(script);
vtools_genesis 55 }
vtools_genesis 56
vtools_genesis 57 /* Print a pair of line numbers with a comma, translated for file
vtools_genesis 58 |file|. If the second number is smaller, use the first in place of
vtools_genesis 59 it. If the numbers are equal, print just one number.
vtools_genesis 60
vtools_genesis 61 Args |a| and |b| are internal line numbers. We print the
vtools_genesis 62 translated (real) line numbers. */
vtools_genesis 63
vtools_genesis 64 static void
vtools_genesis 65 print_unidiff_number_range(struct file_data const *file, lin a, lin b) {
vtools_genesis 66 printint trans_a, trans_b;
vtools_genesis 67 translate_range(file, a, b, &trans_a, &trans_b);
vtools_genesis 68
vtools_genesis 69 /* We can have |b < a| in the case of a range of no lines. In
vtools_genesis 70 this case, we print the line number before the range, which is
vtools_genesis 71 |b|. It would be more logical to print |a|, but `patch'
vtools_genesis 72 expects |b| in order to detect diffs against empty files. */
vtools_genesis 73 if (trans_b <= trans_a)
vtools_genesis 74 fprintf(outfile, trans_b < trans_a ? "%"pI"d,0" : "%"pI"d", trans_b);
vtools_genesis 75 else
vtools_genesis 76 fprintf(outfile, "%"pI"d,%"pI"d", trans_a, trans_b - trans_a + 1);
vtools_genesis 77 }
vtools_genesis 78
vtools_genesis 79 /* Print a portion of an edit script in unidiff format. |hunk| is the
vtools_genesis 80 beginning of the portion to be printed. The end is marked by a
vtools_genesis 81 |link| that has been nulled out.
vtools_genesis 82
vtools_genesis 83 Prints out lines from both files, and precedes each line with the
vtools_genesis 84 appropriate flag-character. */
vtools_genesis 85
vtools_genesis 86 void
vtools_genesis 87 pr_unidiff_hunk(struct change *hunk) {
vtools_genesis 88 lin first0, last0, first1, last1;
vtools_genesis 89 lin i, j, k;
vtools_genesis 90 struct change *next;
vtools_genesis 91 FILE *out;
vtools_genesis 92
vtools_genesis 93 /* Determine range of line numbers involved in each file. */
vtools_genesis 94
vtools_genesis 95 if (!analyze_hunk(hunk, &first0, &last0, &first1, &last1))
vtools_genesis 96 return;
vtools_genesis 97
vtools_genesis 98 /* Include a context's width before and after. */
vtools_genesis 99
vtools_genesis 100 i = -files[0].prefix_lines;
vtools_genesis 101 first0 = MAX (first0 - context, i);
vtools_genesis 102 first1 = MAX (first1 - context, i);
vtools_genesis 103 if (last0 < files[0].valid_lines - context)
vtools_genesis 104 last0 += context;
vtools_genesis 105 else
vtools_genesis 106 last0 = files[0].valid_lines - 1;
vtools_genesis 107 if (last1 < files[1].valid_lines - context)
vtools_genesis 108 last1 += context;
vtools_genesis 109 else
vtools_genesis 110 last1 = files[1].valid_lines - 1;
vtools_genesis 111
vtools_genesis 112 begin_output();
vtools_genesis 113 out = outfile;
vtools_genesis 114
vtools_genesis 115 fputs("@@ -", out);
vtools_genesis 116 print_unidiff_number_range(&files[0], first0, last0);
vtools_genesis 117 fputs(" +", out);
vtools_genesis 118 print_unidiff_number_range(&files[1], first1, last1);
vtools_genesis 119 fputs(" @@", out);
vtools_genesis 120
vtools_genesis 121 putc('\n', out);
vtools_genesis 122
vtools_genesis 123 next = hunk;
vtools_genesis 124 i = first0;
vtools_genesis 125 j = first1;
vtools_genesis 126
vtools_genesis 127 while (i <= last0 || j <= last1) {
vtools_genesis 128
vtools_genesis 129 /* If the line isn't a difference, output the context from
vtools_genesis 130 file 0. */
vtools_genesis 131
vtools_genesis 132 if (!next || i < next->line0) {
vtools_genesis 133 char const *const *line = &files[0].linbuf[i++];
vtools_genesis 134 if (!(suppress_blank_empty && **line == '\n'))
vtools_genesis 135 putc(' ', out);
vtools_genesis 136 print_1_line(NULL, line);
vtools_genesis 137 j++;
vtools_genesis 138 } else {
vtools_genesis 139 /* For each difference, first output the deleted part. */
vtools_genesis 140
vtools_genesis 141 k = next->deleted;
vtools_genesis 142 while (k--) {
vtools_genesis 143 char const *const *line = &files[0].linbuf[i++];
vtools_genesis 144 putc('-', out);
vtools_genesis 145 print_1_line_nl(NULL, line, true);
vtools_genesis 146 if (line[1][-1] == '\n')
vtools_genesis 147 putc('\n', out);
vtools_genesis 148 }
vtools_genesis 149
vtools_genesis 150 /* Then output the inserted part. */
vtools_genesis 151
vtools_genesis 152 k = next->inserted;
vtools_genesis 153 while (k--) {
vtools_genesis 154 char const *const *line = &files[1].linbuf[j++];
vtools_genesis 155 putc('+', out);
vtools_genesis 156 print_1_line_nl(NULL, line, true);
vtools_genesis 157 if (line[1][-1] == '\n')
vtools_genesis 158 putc('\n', out);
vtools_genesis 159 }
vtools_genesis 160
vtools_genesis 161 /* We're done with this hunk, so on to the next! */
vtools_genesis 162
vtools_genesis 163 next = next->link;
vtools_genesis 164 }
vtools_genesis 165 }
vtools_genesis 166 }
vtools_genesis 167
vtools_genesis 168 /* Scan a (forward-ordered) edit script for the first place that more
vtools_genesis 169 than |2*context| unchanged lines appear, and return a pointer to
vtools_genesis 170 the |struct change| for the last change before those lines. */
vtools_genesis 171
vtools_genesis 172 struct change *
vtools_genesis 173 find_hunk(struct change *start) {
vtools_genesis 174 struct change *prev;
vtools_genesis 175 lin top0, top1;
vtools_genesis 176 lin thresh;
vtools_genesis 177
vtools_genesis 178 /* Threshold distance is |context| if the second change is
vtools_genesis 179 ignorable, |2 * context + 1| otherwise. Integer overflow can't
vtools_genesis 180 happen, due to |CONTEXT_LIM|. */
vtools_genesis 181 lin ignorable_threshold = context;
vtools_genesis 182 lin non_ignorable_threshold = 2 * context + 1;
vtools_genesis 183
vtools_genesis 184 do {
vtools_genesis 185 /* Compute number of first line in each file beyond this changed. */
vtools_genesis 186 top0 = start->line0 + start->deleted;
vtools_genesis 187 top1 = start->line1 + start->inserted;
vtools_genesis 188 prev = start;
vtools_genesis 189 start = start->link;
vtools_genesis 190 thresh = (start && start->ignore
vtools_genesis 191 ? ignorable_threshold
vtools_genesis 192 : non_ignorable_threshold);
vtools_genesis 193 /* It is not supposed to matter which file we check in the
vtools_genesis 194 end-test. If it would matter, crash. */
vtools_genesis 195 if (start && start->line0 - top0 != start->line1 - top1)
vtools_genesis 196 abort();
vtools_genesis 197 } while (start
vtools_genesis 198 /* Keep going if less than |thresh| lines elapse before
vtools_genesis 199 the affected line. */
vtools_genesis 200 && start->line0 - top0 < thresh);
vtools_genesis 201
vtools_genesis 202 return prev;
vtools_genesis 203 }
vtools_genesis 204
vtools_genesis 205 /* Set the |ignore| flag properly in each change in script. It should
vtools_genesis 206 be 1 if all the lines inserted or deleted in that change are
vtools_genesis 207 ignorable lines. */
vtools_genesis 208
vtools_genesis 209 static void
vtools_genesis 210 mark_ignorable(struct change *script) {
vtools_genesis 211 while (script) {
vtools_genesis 212 struct change *next = script->link;
vtools_genesis 213 lin first0, last0, first1, last1;
vtools_genesis 214
vtools_genesis 215 /* Turn this change into a hunk: detach it from the others. */
vtools_genesis 216 script->link = NULL;
vtools_genesis 217
vtools_genesis 218 /* Determine whether this change is ignorable. */
vtools_genesis 219 script->ignore = !analyze_hunk(script,
vtools_genesis 220 &first0, &last0, &first1, &last1);
vtools_genesis 221
vtools_genesis 222 /* Reconnect the chain as before. */
vtools_genesis 223 script->link = next;
vtools_genesis 224
vtools_genesis 225 /* Advance to the following change. */
vtools_genesis 226 script = next;
vtools_genesis 227 }
vtools_genesis 228 }
vtools_genesis 229