-
+ F5B3E5C736BE0C6C4E4FDCC50E2A436C17D3E84FE47E6125DD0FA775C9CFFCC625A98FE7091A036593E21CDAFA1E533FD8A04640649CD6ED89DA499C94333668
vtools/src/context.c
(0 . 0)(1 . 211)
3216
3217 #include <stdlib.h>
3218 #include "diff.h"
3219
3220 /* Print a label for a context diff, with a file name and date or a
3221 label. */
3222
3223 static void
3224 print_context_label(char const *mark,
3225 struct file_data *inf,
3226 char const *name,
3227 char const *label) {
3228 if (label)
3229 fprintf(outfile, "%s %s\n", mark, label);
3230 else {
3231 fprintf(outfile, "%s %s false\n", mark, name);
3232 }
3233 }
3234
3235 /* Print a header for a context diff, with the file names and dates. */
3236
3237 void
3238 print_context_header(struct file_data inf[], char const *const *names) {
3239 print_context_label("---", &inf[0], names[0], file_label[0]);
3240 print_context_label("+++", &inf[1], names[1], file_label[1]);
3241 }
3242
3243 /* Print an edit script in context format. */
3244
3245 void
3246 print_context_script(struct change *script) {
3247 struct change *e;
3248 for (e = script; e; e = e->link)
3249 e->ignore = false;
3250
3251 print_script(script);
3252 }
3253
3254 /* Print a pair of line numbers with a comma, translated for file
3255 |file|. If the second number is smaller, use the first in place of
3256 it. If the numbers are equal, print just one number.
3257
3258 Args |a| and |b| are internal line numbers. We print the
3259 translated (real) line numbers. */
3260
3261 static void
3262 print_unidiff_number_range(struct file_data const *file, lin a, lin b) {
3263 printint trans_a, trans_b;
3264 translate_range(file, a, b, &trans_a, &trans_b);
3265
3266 /* We can have |b < a| in the case of a range of no lines. In
3267 this case, we print the line number before the range, which is
3268 |b|. It would be more logical to print |a|, but `patch'
3269 expects |b| in order to detect diffs against empty files. */
3270 if (trans_b <= trans_a)
3271 fprintf(outfile, trans_b < trans_a ? "%"pI"d,0" : "%"pI"d", trans_b);
3272 else
3273 fprintf(outfile, "%"pI"d,%"pI"d", trans_a, trans_b - trans_a + 1);
3274 }
3275
3276 /* Print a portion of an edit script in unidiff format. |hunk| is the
3277 beginning of the portion to be printed. The end is marked by a
3278 |link| that has been nulled out.
3279
3280 Prints out lines from both files, and precedes each line with the
3281 appropriate flag-character. */
3282
3283 void
3284 pr_unidiff_hunk(struct change *hunk) {
3285 lin first0, last0, first1, last1;
3286 lin i, j, k;
3287 struct change *next;
3288 FILE *out;
3289
3290 /* Determine range of line numbers involved in each file. */
3291
3292 if (!analyze_hunk(hunk, &first0, &last0, &first1, &last1))
3293 return;
3294
3295 /* Include a context's width before and after. */
3296
3297 i = -files[0].prefix_lines;
3298 first0 = MAX (first0 - context, i);
3299 first1 = MAX (first1 - context, i);
3300 if (last0 < files[0].valid_lines - context)
3301 last0 += context;
3302 else
3303 last0 = files[0].valid_lines - 1;
3304 if (last1 < files[1].valid_lines - context)
3305 last1 += context;
3306 else
3307 last1 = files[1].valid_lines - 1;
3308
3309 begin_output();
3310 out = outfile;
3311
3312 fputs("@@ -", out);
3313 print_unidiff_number_range(&files[0], first0, last0);
3314 fputs(" +", out);
3315 print_unidiff_number_range(&files[1], first1, last1);
3316 fputs(" @@", out);
3317
3318 putc('\n', out);
3319
3320 next = hunk;
3321 i = first0;
3322 j = first1;
3323
3324 while (i <= last0 || j <= last1) {
3325
3326 /* If the line isn't a difference, output the context from
3327 file 0. */
3328
3329 if (!next || i < next->line0) {
3330 char const *const *line = &files[0].linbuf[i++];
3331 if (!(suppress_blank_empty && **line == '\n'))
3332 putc(' ', out);
3333 print_1_line(NULL, line);
3334 j++;
3335 } else {
3336 /* For each difference, first output the deleted part. */
3337
3338 k = next->deleted;
3339 while (k--) {
3340 char const *const *line = &files[0].linbuf[i++];
3341 putc('-', out);
3342 print_1_line_nl(NULL, line, true);
3343 if (line[1][-1] == '\n')
3344 putc('\n', out);
3345 }
3346
3347 /* Then output the inserted part. */
3348
3349 k = next->inserted;
3350 while (k--) {
3351 char const *const *line = &files[1].linbuf[j++];
3352 putc('+', out);
3353 print_1_line_nl(NULL, line, true);
3354 if (line[1][-1] == '\n')
3355 putc('\n', out);
3356 }
3357
3358 /* We're done with this hunk, so on to the next! */
3359
3360 next = next->link;
3361 }
3362 }
3363 }
3364
3365 /* Scan a (forward-ordered) edit script for the first place that more
3366 than |2*context| unchanged lines appear, and return a pointer to
3367 the |struct change| for the last change before those lines. */
3368
3369 struct change *
3370 find_hunk(struct change *start) {
3371 struct change *prev;
3372 lin top0, top1;
3373 lin thresh;
3374
3375 /* Threshold distance is |context| if the second change is
3376 ignorable, |2 * context + 1| otherwise. Integer overflow can't
3377 happen, due to |CONTEXT_LIM|. */
3378 lin ignorable_threshold = context;
3379 lin non_ignorable_threshold = 2 * context + 1;
3380
3381 do {
3382 /* Compute number of first line in each file beyond this changed. */
3383 top0 = start->line0 + start->deleted;
3384 top1 = start->line1 + start->inserted;
3385 prev = start;
3386 start = start->link;
3387 thresh = (start && start->ignore
3388 ? ignorable_threshold
3389 : non_ignorable_threshold);
3390 /* It is not supposed to matter which file we check in the
3391 end-test. If it would matter, crash. */
3392 if (start && start->line0 - top0 != start->line1 - top1)
3393 abort();
3394 } while (start
3395 /* Keep going if less than |thresh| lines elapse before
3396 the affected line. */
3397 && start->line0 - top0 < thresh);
3398
3399 return prev;
3400 }
3401
3402 /* Set the |ignore| flag properly in each change in script. It should
3403 be 1 if all the lines inserted or deleted in that change are
3404 ignorable lines. */
3405
3406 static void
3407 mark_ignorable(struct change *script) {
3408 while (script) {
3409 struct change *next = script->link;
3410 lin first0, last0, first1, last1;
3411
3412 /* Turn this change into a hunk: detach it from the others. */
3413 script->link = NULL;
3414
3415 /* Determine whether this change is ignorable. */
3416 script->ignore = !analyze_hunk(script,
3417 &first0, &last0, &first1, &last1);
3418
3419 /* Reconnect the chain as before. */
3420 script->link = next;
3421
3422 /* Advance to the following change. */
3423 script = next;
3424 }
3425 }
3426