Mercurial > vim
comparison src/xdiff/xdiffi.c @ 25709:d5142d87f898 v8.2.3390
patch 8.2.3390: included xdiff code is outdated
Commit: https://github.com/vim/vim/commit/ba02e4720f863fdb456e7023520f0a354eec0dcf
Author: Christian Brabandt <cb@256bit.org>
Date: Tue Aug 31 20:46:39 2021 +0200
patch 8.2.3390: included xdiff code is outdated
Problem: Included xdiff code is outdated.
Solution: Sync with xdiff in git 2.33. (Christian Brabandt, closes https://github.com/vim/vim/issues/8431)
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Tue, 31 Aug 2021 21:00:05 +0200 |
parents | 3be01cf0a632 |
children | f84e5db372ea |
comparison
equal
deleted
inserted
replaced
25708:a1f90f486bf7 | 25709:d5142d87f898 |
---|---|
36 /* | 36 /* |
37 * See "An O(ND) Difference Algorithm and its Variations", by Eugene Myers. | 37 * See "An O(ND) Difference Algorithm and its Variations", by Eugene Myers. |
38 * Basically considers a "box" (off1, off2, lim1, lim2) and scan from both | 38 * Basically considers a "box" (off1, off2, lim1, lim2) and scan from both |
39 * the forward diagonal starting from (off1, off2) and the backward diagonal | 39 * the forward diagonal starting from (off1, off2) and the backward diagonal |
40 * starting from (lim1, lim2). If the K values on the same diagonal crosses | 40 * starting from (lim1, lim2). If the K values on the same diagonal crosses |
41 * returns the furthest point of reach. We might end up having to expensive | 41 * returns the furthest point of reach. We might encounter expensive edge cases |
42 * cases using this algorithm is full, so a little bit of heuristic is needed | 42 * using this algorithm, so a little bit of heuristic is needed to cut the |
43 * to cut the search and to return a suboptimal point. | 43 * search and to return a suboptimal point. |
44 */ | 44 */ |
45 static long xdl_split(unsigned long const *ha1, long off1, long lim1, | 45 static long xdl_split(unsigned long const *ha1, long off1, long lim1, |
46 unsigned long const *ha2, long off2, long lim2, | 46 unsigned long const *ha2, long off2, long lim2, |
47 long *kvdf, long *kvdb, int need_min, xdpsplit_t *spl, | 47 long *kvdf, long *kvdb, int need_min, xdpsplit_t *spl, |
48 xdalgoenv_t *xenv) { | 48 xdalgoenv_t *xenv) { |
61 | 61 |
62 for (ec = 1;; ec++) { | 62 for (ec = 1;; ec++) { |
63 int got_snake = 0; | 63 int got_snake = 0; |
64 | 64 |
65 /* | 65 /* |
66 * We need to extent the diagonal "domain" by one. If the next | 66 * We need to extend the diagonal "domain" by one. If the next |
67 * values exits the box boundaries we need to change it in the | 67 * values exits the box boundaries we need to change it in the |
68 * opposite direction because (max - min) must be a power of two. | 68 * opposite direction because (max - min) must be a power of |
69 * two. | |
70 * | |
69 * Also we initialize the external K value to -1 so that we can | 71 * Also we initialize the external K value to -1 so that we can |
70 * avoid extra conditions check inside the core loop. | 72 * avoid extra conditions in the check inside the core loop. |
71 */ | 73 */ |
72 if (fmin > dmin) | 74 if (fmin > dmin) |
73 kvdf[--fmin - 1] = -1; | 75 kvdf[--fmin - 1] = -1; |
74 else | 76 else |
75 ++fmin; | 77 ++fmin; |
96 return ec; | 98 return ec; |
97 } | 99 } |
98 } | 100 } |
99 | 101 |
100 /* | 102 /* |
101 * We need to extent the diagonal "domain" by one. If the next | 103 * We need to extend the diagonal "domain" by one. If the next |
102 * values exits the box boundaries we need to change it in the | 104 * values exits the box boundaries we need to change it in the |
103 * opposite direction because (max - min) must be a power of two. | 105 * opposite direction because (max - min) must be a power of |
106 * two. | |
107 * | |
104 * Also we initialize the external K value to -1 so that we can | 108 * Also we initialize the external K value to -1 so that we can |
105 * avoid extra conditions check inside the core loop. | 109 * avoid extra conditions in the check inside the core loop. |
106 */ | 110 */ |
107 if (bmin > dmin) | 111 if (bmin > dmin) |
108 kvdb[--bmin - 1] = XDL_LINE_MAX; | 112 kvdb[--bmin - 1] = XDL_LINE_MAX; |
109 else | 113 else |
110 ++bmin; | 114 ++bmin; |
136 continue; | 140 continue; |
137 | 141 |
138 /* | 142 /* |
139 * If the edit cost is above the heuristic trigger and if | 143 * If the edit cost is above the heuristic trigger and if |
140 * we got a good snake, we sample current diagonals to see | 144 * we got a good snake, we sample current diagonals to see |
141 * if some of the, have reached an "interesting" path. Our | 145 * if some of them have reached an "interesting" path. Our |
142 * measure is a function of the distance from the diagonal | 146 * measure is a function of the distance from the diagonal |
143 * corner (i1 + i2) penalized with the distance from the | 147 * corner (i1 + i2) penalized with the distance from the |
144 * mid diagonal itself. If this value is above the current | 148 * mid diagonal itself. If this value is above the current |
145 * edit cost times a magic factor (XDL_K_HEUR) we consider | 149 * edit cost times a magic factor (XDL_K_HEUR) we consider |
146 * it interesting. | 150 * it interesting. |
194 return ec; | 198 return ec; |
195 } | 199 } |
196 } | 200 } |
197 | 201 |
198 /* | 202 /* |
199 * Enough is enough. We spent too much time here and now we collect | 203 * Enough is enough. We spent too much time here and now we |
200 * the furthest reaching path using the (i1 + i2) measure. | 204 * collect the furthest reaching path using the (i1 + i2) |
205 * measure. | |
201 */ | 206 */ |
202 if (ec >= xenv->mxcost) { | 207 if (ec >= xenv->mxcost) { |
203 long fbest, fbest1, bbest, bbest1; | 208 long fbest, fbest1, bbest, bbest1; |
204 | 209 |
205 fbest = fbest1 = -1; | 210 fbest = fbest1 = -1; |
242 } | 247 } |
243 } | 248 } |
244 | 249 |
245 | 250 |
246 /* | 251 /* |
247 * Rule: "Divide et Impera". Recursively split the box in sub-boxes by calling | 252 * Rule: "Divide et Impera" (divide & conquer). Recursively split the box in |
248 * the box splitting function. Note that the real job (marking changed lines) | 253 * sub-boxes by calling the box splitting function. Note that the real job |
249 * is done in the two boundary reaching checks. | 254 * (marking changed lines) is done in the two boundary reaching checks. |
250 */ | 255 */ |
251 int xdl_recs_cmp(diffdata_t *dd1, long off1, long lim1, | 256 int xdl_recs_cmp(diffdata_t *dd1, long off1, long lim1, |
252 diffdata_t *dd2, long off2, long lim2, | 257 diffdata_t *dd2, long off2, long lim2, |
253 long *kvdf, long *kvdb, int need_min, xdalgoenv_t *xenv) { | 258 long *kvdf, long *kvdb, int need_min, xdalgoenv_t *xenv) { |
254 unsigned long const *ha1 = dd1->ha, *ha2 = dd2->ha; | 259 unsigned long const *ha1 = dd1->ha, *ha2 = dd2->ha; |
321 | 326 |
322 return -1; | 327 return -1; |
323 } | 328 } |
324 | 329 |
325 /* | 330 /* |
326 * Allocate and setup K vectors to be used by the differential algorithm. | 331 * Allocate and setup K vectors to be used by the differential |
332 * algorithm. | |
333 * | |
327 * One is to store the forward path and one to store the backward path. | 334 * One is to store the forward path and one to store the backward path. |
328 */ | 335 */ |
329 ndiags = xe->xdf1.nreff + xe->xdf2.nreff + 3; | 336 ndiags = xe->xdf1.nreff + xe->xdf2.nreff + 3; |
330 if (!(kvd = (long *) xdl_malloc((2 * ndiags + 2) * sizeof(long)))) { | 337 if (!(kvd = (long *) xdl_malloc((2 * ndiags + 2) * sizeof(long)))) { |
331 | 338 |
416 return ret; | 423 return ret; |
417 else if (c == ' ') | 424 else if (c == ' ') |
418 ret += 1; | 425 ret += 1; |
419 else if (c == '\t') | 426 else if (c == '\t') |
420 ret += 8 - ret % 8; | 427 ret += 8 - ret % 8; |
421 // ignore other whitespace characters | 428 /* ignore other whitespace characters */ |
422 | 429 |
423 if (ret >= MAX_INDENT) | 430 if (ret >= MAX_INDENT) |
424 return MAX_INDENT; | 431 return MAX_INDENT; |
425 } | 432 } |
426 | 433 |
427 // The line contains only whitespace. | 434 /* The line contains only whitespace. */ |
428 return -1; | 435 return -1; |
429 } | 436 } |
430 | 437 |
431 /* | 438 /* |
432 * If more than this number of consecutive blank rows are found, just return | 439 * If more than this number of consecutive blank rows are found, just return |
433 * this value. This avoids requiring O(N^2) work for pathological cases, and | 440 * this value. This avoids requiring O(N^2) work for pathological cases, and |
434 * also ensures that the output of score_split fits in an int. | 441 * also ensures that the output of score_split fits in an int. |
435 */ | 442 */ |
436 #define MAX_BLANKS 20 | 443 #define MAX_BLANKS 20 |
437 | 444 |
438 // Characteristics measured about a hypothetical split position. | 445 /* Characteristics measured about a hypothetical split position. */ |
439 struct split_measurement { | 446 struct split_measurement { |
440 /* | 447 /* |
441 * Is the split at the end of the file (aside from any blank lines)? | 448 * Is the split at the end of the file (aside from any blank lines)? |
442 */ | 449 */ |
443 int end_of_file; | 450 int end_of_file; |
444 | 451 |
445 /* | 452 /* |
446 * How much is the line immediately following the split indented (or -1 if | 453 * How much is the line immediately following the split indented (or -1 |
447 * the line is blank): | 454 * if the line is blank): |
448 */ | 455 */ |
449 int indent; | 456 int indent; |
450 | 457 |
451 /* | 458 /* |
452 * How many consecutive lines above the split are blank? | 459 * How many consecutive lines above the split are blank? |
453 */ | 460 */ |
454 int pre_blank; | 461 int pre_blank; |
455 | 462 |
456 /* | 463 /* |
457 * How much is the nearest non-blank line above the split indented (or -1 | 464 * How much is the nearest non-blank line above the split indented (or |
458 * if there is no such line)? | 465 * -1 if there is no such line)? |
459 */ | 466 */ |
460 int pre_indent; | 467 int pre_indent; |
461 | 468 |
462 /* | 469 /* |
463 * How many lines after the line following the split are blank? | 470 * How many lines after the line following the split are blank? |
470 */ | 477 */ |
471 int post_indent; | 478 int post_indent; |
472 }; | 479 }; |
473 | 480 |
474 struct split_score { | 481 struct split_score { |
475 // The effective indent of this split (smaller is preferred). | 482 /* The effective indent of this split (smaller is preferred). */ |
476 int effective_indent; | 483 int effective_indent; |
477 | 484 |
478 // Penalty for this split (smaller is preferred). | 485 /* Penalty for this split (smaller is preferred). */ |
479 int penalty; | 486 int penalty; |
480 }; | 487 }; |
481 | 488 |
482 /* | 489 /* |
483 * Fill m with information about a hypothetical split of xdf above line split. | 490 * Fill m with information about a hypothetical split of xdf above line split. |
532 * In practice, these numbers are chosen to be large enough that they can be | 539 * In practice, these numbers are chosen to be large enough that they can be |
533 * adjusted relative to each other with sufficient precision despite using | 540 * adjusted relative to each other with sufficient precision despite using |
534 * integer math. | 541 * integer math. |
535 */ | 542 */ |
536 | 543 |
537 // Penalty if there are no non-blank lines before the split | 544 /* Penalty if there are no non-blank lines before the split */ |
538 #define START_OF_FILE_PENALTY 1 | 545 #define START_OF_FILE_PENALTY 1 |
539 | 546 |
540 // Penalty if there are no non-blank lines after the split | 547 /* Penalty if there are no non-blank lines after the split */ |
541 #define END_OF_FILE_PENALTY 21 | 548 #define END_OF_FILE_PENALTY 21 |
542 | 549 |
543 // Multiplier for the number of blank lines around the split | 550 /* Multiplier for the number of blank lines around the split */ |
544 #define TOTAL_BLANK_WEIGHT (-30) | 551 #define TOTAL_BLANK_WEIGHT (-30) |
545 | 552 |
546 // Multiplier for the number of blank lines after the split | 553 /* Multiplier for the number of blank lines after the split */ |
547 #define POST_BLANK_WEIGHT 6 | 554 #define POST_BLANK_WEIGHT 6 |
548 | 555 |
549 /* | 556 /* |
550 * Penalties applied if the line is indented more than its predecessor | 557 * Penalties applied if the line is indented more than its predecessor |
551 */ | 558 */ |
579 */ | 586 */ |
580 #define INDENT_HEURISTIC_MAX_SLIDING 100 | 587 #define INDENT_HEURISTIC_MAX_SLIDING 100 |
581 | 588 |
582 /* | 589 /* |
583 * Compute a badness score for the hypothetical split whose measurements are | 590 * Compute a badness score for the hypothetical split whose measurements are |
584 * stored in m. The weight factors were determined empirically using the tools and | 591 * stored in m. The weight factors were determined empirically using the tools |
585 * corpus described in | 592 * and corpus described in |
586 * | 593 * |
587 * https://github.com/mhagger/diff-slider-tools | 594 * https://github.com/mhagger/diff-slider-tools |
588 * | 595 * |
589 * Also see that project if you want to improve the weights based on, for example, | 596 * Also see that project if you want to improve the weights based on, for |
590 * a larger or more diverse corpus. | 597 * example, a larger or more diverse corpus. |
591 */ | 598 */ |
592 static void score_add_split(const struct split_measurement *m, struct split_score *s) | 599 static void score_add_split(const struct split_measurement *m, struct split_score *s) |
593 { | 600 { |
594 /* | 601 /* |
595 * A place to accumulate penalty factors (positive makes this index more | 602 * A place to accumulate penalty factors (positive makes this index more |
608 * including the line immediately after the split: | 615 * including the line immediately after the split: |
609 */ | 616 */ |
610 post_blank = (m->indent == -1) ? 1 + m->post_blank : 0; | 617 post_blank = (m->indent == -1) ? 1 + m->post_blank : 0; |
611 total_blank = m->pre_blank + post_blank; | 618 total_blank = m->pre_blank + post_blank; |
612 | 619 |
613 // Penalties based on nearby blank lines: | 620 /* Penalties based on nearby blank lines: */ |
614 s->penalty += TOTAL_BLANK_WEIGHT * total_blank; | 621 s->penalty += TOTAL_BLANK_WEIGHT * total_blank; |
615 s->penalty += POST_BLANK_WEIGHT * post_blank; | 622 s->penalty += POST_BLANK_WEIGHT * post_blank; |
616 | 623 |
617 if (m->indent != -1) | 624 if (m->indent != -1) |
618 indent = m->indent; | 625 indent = m->indent; |
619 else | 626 else |
620 indent = m->post_indent; | 627 indent = m->post_indent; |
621 | 628 |
622 any_blanks = (total_blank != 0); | 629 any_blanks = (total_blank != 0); |
623 | 630 |
624 // Note that the effective indent is -1 at the end of the file: | 631 /* Note that the effective indent is -1 at the end of the file: */ |
625 s->effective_indent += indent; | 632 s->effective_indent += indent; |
626 | 633 |
627 if (indent == -1) { | 634 if (indent == -1) { |
628 // No additional adjustments needed. | 635 /* No additional adjustments needed. */ |
629 } else if (m->pre_indent == -1) { | 636 } else if (m->pre_indent == -1) { |
630 // No additional adjustments needed. | 637 /* No additional adjustments needed. */ |
631 } else if (indent > m->pre_indent) { | 638 } else if (indent > m->pre_indent) { |
632 /* | 639 /* |
633 * The line is indented more than its predecessor. | 640 * The line is indented more than its predecessor. |
634 */ | 641 */ |
635 s->penalty += any_blanks ? | 642 s->penalty += any_blanks ? |
667 } | 674 } |
668 } | 675 } |
669 | 676 |
670 static int score_cmp(struct split_score *s1, struct split_score *s2) | 677 static int score_cmp(struct split_score *s1, struct split_score *s2) |
671 { | 678 { |
672 // -1 if s1.effective_indent < s2->effective_indent, etc. | 679 /* -1 if s1.effective_indent < s2->effective_indent, etc. */ |
673 int cmp_indents = ((s1->effective_indent > s2->effective_indent) - | 680 int cmp_indents = ((s1->effective_indent > s2->effective_indent) - |
674 (s1->effective_indent < s2->effective_indent)); | 681 (s1->effective_indent < s2->effective_indent)); |
675 | 682 |
676 return INDENT_WEIGHT * cmp_indents + (s1->penalty - s2->penalty); | 683 return INDENT_WEIGHT * cmp_indents + (s1->penalty - s2->penalty); |
677 } | 684 } |
807 | 814 |
808 group_init(xdf, &g); | 815 group_init(xdf, &g); |
809 group_init(xdfo, &go); | 816 group_init(xdfo, &go); |
810 | 817 |
811 while (1) { | 818 while (1) { |
812 // If the group is empty in the to-be-compacted file, skip it: | 819 /* |
820 * If the group is empty in the to-be-compacted file, skip it: | |
821 */ | |
813 if (g.end == g.start) | 822 if (g.end == g.start) |
814 goto next; | 823 goto next; |
815 | 824 |
816 /* | 825 /* |
817 * Now shift the change up and then down as far as possible in | 826 * Now shift the change up and then down as far as possible in |
818 * each direction. If it bumps into any other changes, merge them. | 827 * each direction. If it bumps into any other changes, merge |
828 * them. | |
819 */ | 829 */ |
820 do { | 830 do { |
821 groupsize = g.end - g.start; | 831 groupsize = g.end - g.start; |
822 | 832 |
823 /* | 833 /* |
826 * other file. -1 indicates that we haven't found such | 836 * other file. -1 indicates that we haven't found such |
827 * a match yet: | 837 * a match yet: |
828 */ | 838 */ |
829 end_matching_other = -1; | 839 end_matching_other = -1; |
830 | 840 |
831 // Shift the group backward as much as possible: | 841 /* Shift the group backward as much as possible: */ |
832 while (!group_slide_up(xdf, &g, flags)) | 842 while (!group_slide_up(xdf, &g, flags)) |
833 if (group_previous(xdfo, &go)) | 843 if (group_previous(xdfo, &go)) |
834 xdl_bug("group sync broken sliding up"); | 844 xdl_bug("group sync broken sliding up"); |
835 | 845 |
836 /* | 846 /* |
840 earliest_end = g.end; | 850 earliest_end = g.end; |
841 | 851 |
842 if (go.end > go.start) | 852 if (go.end > go.start) |
843 end_matching_other = g.end; | 853 end_matching_other = g.end; |
844 | 854 |
845 // Now shift the group forward as far as possible: | 855 /* Now shift the group forward as far as possible: */ |
846 while (1) { | 856 while (1) { |
847 if (group_slide_down(xdf, &g, flags)) | 857 if (group_slide_down(xdf, &g, flags)) |
848 break; | 858 break; |
849 if (group_next(xdfo, &go)) | 859 if (group_next(xdfo, &go)) |
850 xdl_bug("group sync broken sliding down"); | 860 xdl_bug("group sync broken sliding down"); |
856 | 866 |
857 /* | 867 /* |
858 * If the group can be shifted, then we can possibly use this | 868 * If the group can be shifted, then we can possibly use this |
859 * freedom to produce a more intuitive diff. | 869 * freedom to produce a more intuitive diff. |
860 * | 870 * |
861 * The group is currently shifted as far down as possible, so the | 871 * The group is currently shifted as far down as possible, so |
862 * heuristics below only have to handle upwards shifts. | 872 * the heuristics below only have to handle upwards shifts. |
863 */ | 873 */ |
864 | 874 |
865 if (g.end == earliest_end) { | 875 if (g.end == earliest_end) { |
866 // no shifting was possible | 876 /* no shifting was possible */ |
867 } else if (end_matching_other != -1) { | 877 } else if (end_matching_other != -1) { |
868 /* | 878 /* |
869 * Move the possibly merged group of changes back to line | 879 * Move the possibly merged group of changes back to |
870 * up with the last group of changes from the other file | 880 * line up with the last group of changes from the |
871 * that it can align with. | 881 * other file that it can align with. |
872 */ | 882 */ |
873 while (go.end == go.start) { | 883 while (go.end == go.start) { |
874 if (group_slide_up(xdf, &g, flags)) | 884 if (group_slide_up(xdf, &g, flags)) |
875 xdl_bug("match disappeared"); | 885 xdl_bug("match disappeared"); |
876 if (group_previous(xdfo, &go)) | 886 if (group_previous(xdfo, &go)) |
877 xdl_bug("group sync broken sliding to match"); | 887 xdl_bug("group sync broken sliding to match"); |
878 } | 888 } |
879 } else if (flags & XDF_INDENT_HEURISTIC) { | 889 } else if (flags & XDF_INDENT_HEURISTIC) { |
880 /* | 890 /* |
881 * Indent heuristic: a group of pure add/delete lines | 891 * Indent heuristic: a group of pure add/delete lines |
882 * implies two splits, one between the end of the "before" | 892 * implies two splits, one between the end of the |
883 * context and the start of the group, and another between | 893 * "before" context and the start of the group, and |
884 * the end of the group and the beginning of the "after" | 894 * another between the end of the group and the |
885 * context. Some splits are aesthetically better and some | 895 * beginning of the "after" context. Some splits are |
886 * are worse. We compute a badness "score" for each split, | 896 * aesthetically better and some are worse. We compute |
887 * and add the scores for the two splits to define a | 897 * a badness "score" for each split, and add the scores |
888 * "score" for each position that the group can be shifted | 898 * for the two splits to define a "score" for each |
889 * to. Then we pick the shift with the lowest score. | 899 * position that the group can be shifted to. Then we |
900 * pick the shift with the lowest score. | |
890 */ | 901 */ |
891 long shift, best_shift = -1; | 902 long shift, best_shift = -1; |
892 struct split_score best_score; | 903 struct split_score best_score; |
893 | 904 |
894 shift = earliest_end; | 905 shift = earliest_end; |
919 xdl_bug("group sync broken sliding to blank line"); | 930 xdl_bug("group sync broken sliding to blank line"); |
920 } | 931 } |
921 } | 932 } |
922 | 933 |
923 next: | 934 next: |
924 // Move past the just-processed group: | 935 /* Move past the just-processed group: */ |
925 if (group_next(xdf, &g)) | 936 if (group_next(xdf, &g)) |
926 break; | 937 break; |
927 if (group_next(xdfo, &go)) | 938 if (group_next(xdfo, &go)) |
928 xdl_bug("group sync broken moving to next group"); | 939 xdl_bug("group sync broken moving to next group"); |
929 } | 940 } |
985 return -1; | 996 return -1; |
986 } | 997 } |
987 return 0; | 998 return 0; |
988 } | 999 } |
989 | 1000 |
990 static void xdl_mark_ignorable(xdchange_t *xscr, xdfenv_t *xe, long flags) | 1001 static void xdl_mark_ignorable_lines(xdchange_t *xscr, xdfenv_t *xe, long flags) |
991 { | 1002 { |
992 xdchange_t *xch; | 1003 xdchange_t *xch; |
993 | 1004 |
994 for (xch = xscr; xch; xch = xch->next) { | 1005 for (xch = xscr; xch; xch = xch->next) { |
995 int ignore = 1; | 1006 int ignore = 1; |
1005 ignore = xdl_blankline(rec[i]->ptr, rec[i]->size, flags); | 1016 ignore = xdl_blankline(rec[i]->ptr, rec[i]->size, flags); |
1006 | 1017 |
1007 xch->ignore = ignore; | 1018 xch->ignore = ignore; |
1008 } | 1019 } |
1009 } | 1020 } |
1021 | |
1022 #if 0 // unused by Vim | |
1023 static int record_matches_regex(xrecord_t *rec, xpparam_t const *xpp) { | |
1024 regmatch_t regmatch; | |
1025 int i; | |
1026 | |
1027 for (i = 0; i < xpp->ignore_regex_nr; i++) | |
1028 if (!regexec_buf(xpp->ignore_regex[i], rec->ptr, rec->size, 1, | |
1029 ®match, 0)) | |
1030 return 1; | |
1031 | |
1032 return 0; | |
1033 } | |
1034 | |
1035 static void xdl_mark_ignorable_regex(xdchange_t *xscr, const xdfenv_t *xe, | |
1036 xpparam_t const *xpp) | |
1037 { | |
1038 xdchange_t *xch; | |
1039 | |
1040 for (xch = xscr; xch; xch = xch->next) { | |
1041 xrecord_t **rec; | |
1042 int ignore = 1; | |
1043 long i; | |
1044 | |
1045 /* | |
1046 * Do not override --ignore-blank-lines. | |
1047 */ | |
1048 if (xch->ignore) | |
1049 continue; | |
1050 | |
1051 rec = &xe->xdf1.recs[xch->i1]; | |
1052 for (i = 0; i < xch->chg1 && ignore; i++) | |
1053 ignore = record_matches_regex(rec[i], xpp); | |
1054 | |
1055 rec = &xe->xdf2.recs[xch->i2]; | |
1056 for (i = 0; i < xch->chg2 && ignore; i++) | |
1057 ignore = record_matches_regex(rec[i], xpp); | |
1058 | |
1059 xch->ignore = ignore; | |
1060 } | |
1061 } | |
1062 #endif | |
1010 | 1063 |
1011 int xdl_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp, | 1064 int xdl_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp, |
1012 xdemitconf_t const *xecfg, xdemitcb_t *ecb) { | 1065 xdemitconf_t const *xecfg, xdemitcb_t *ecb) { |
1013 xdchange_t *xscr; | 1066 xdchange_t *xscr; |
1014 xdfenv_t xe; | 1067 xdfenv_t xe; |
1025 xdl_free_env(&xe); | 1078 xdl_free_env(&xe); |
1026 return -1; | 1079 return -1; |
1027 } | 1080 } |
1028 if (xscr) { | 1081 if (xscr) { |
1029 if (xpp->flags & XDF_IGNORE_BLANK_LINES) | 1082 if (xpp->flags & XDF_IGNORE_BLANK_LINES) |
1030 xdl_mark_ignorable(xscr, &xe, xpp->flags); | 1083 xdl_mark_ignorable_lines(xscr, &xe, xpp->flags); |
1084 | |
1085 #if 0 | |
1086 if (xpp->ignore_regex) | |
1087 xdl_mark_ignorable_regex(xscr, &xe, xpp); | |
1088 #endif | |
1031 | 1089 |
1032 if (ef(&xe, xscr, ecb, xecfg) < 0) { | 1090 if (ef(&xe, xscr, ecb, xecfg) < 0) { |
1033 | 1091 |
1034 xdl_free_script(xscr); | 1092 xdl_free_script(xscr); |
1035 xdl_free_env(&xe); | 1093 xdl_free_env(&xe); |