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