forked from pool/patch
111 lines
3.3 KiB
Diff
111 lines
3.3 KiB
Diff
---
|
|
patch.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
|
|
1 file changed, 72 insertions(+), 6 deletions(-)
|
|
|
|
Index: b/patch.c
|
|
===================================================================
|
|
--- a/patch.c
|
|
+++ b/patch.c
|
|
@@ -62,6 +62,8 @@ static FILE *create_output_file (char co
|
|
static LINENUM locate_hunk (LINENUM);
|
|
static bool apply_hunk (struct outstate *, LINENUM);
|
|
static bool common_context(LINENUM, LINENUM, LINENUM);
|
|
+static LINENUM min_mismatches(LINENUM, LINENUM);
|
|
+static LINENUM locate_merge (void);
|
|
static bool merge_hunk (struct outstate *, LINENUM, LINENUM);
|
|
static void merge_ends_here(struct outstate *outstate);
|
|
static bool copy_till (struct outstate *, LINENUM);
|
|
@@ -304,15 +306,11 @@ main (int argc, char **argv)
|
|
goto skip_hunk;
|
|
} else if (!where) {
|
|
if (mergetype & MERGE_REJECTS) {
|
|
- LINENUM guess = pch_first () + last_offset;
|
|
-
|
|
- if (merge_hunk(&outstate, guess, -1)) {
|
|
+ if (merge_hunk(&outstate, locate_merge(), -1)) {
|
|
merged++;
|
|
mismatch = 1;
|
|
- } else {
|
|
- /* FIXME: guess harder! */
|
|
+ } else
|
|
goto skip_hunk;
|
|
- }
|
|
} else
|
|
goto skip_hunk;
|
|
} else {
|
|
@@ -1356,6 +1354,74 @@ static bool common_context(LINENUM where
|
|
memcmp(line, pfetch(new), size) == 0));
|
|
}
|
|
|
|
+static LINENUM min_mismatches(LINENUM where, LINENUM lowest)
|
|
+{
|
|
+ register LINENUM ptrn_lines = pch_ptrn_lines();
|
|
+ register LINENUM old, mismatched = 0;
|
|
+
|
|
+ for (old = 1; old <= ptrn_lines; old++, where++) {
|
|
+ size_t size;
|
|
+ const char *line;
|
|
+
|
|
+ line = ifetch (where, false, &size);
|
|
+ if (!size ||
|
|
+ !(canonicalize ?
|
|
+ similar(pfetch(old), pch_line_len(old), line, size) :
|
|
+ (size == pch_line_len(old) &&
|
|
+ memcmp(line, pfetch(old), size) == 0))) {
|
|
+ mismatched++;
|
|
+ if (mismatched >= lowest)
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ return mismatched;
|
|
+}
|
|
+
|
|
+static LINENUM locate_merge ()
|
|
+{
|
|
+ register LINENUM first_guess = pch_first () + last_offset;
|
|
+ register LINENUM lowest = input_lines, where = first_guess;
|
|
+ register LINENUM offset;
|
|
+ LINENUM pat_lines = pch_ptrn_lines();
|
|
+ LINENUM suffix_context = pch_suffix_context ();
|
|
+ LINENUM max_where = input_lines - (pat_lines - suffix_context) + 1;
|
|
+ LINENUM min_where = last_frozen_line + 1;
|
|
+ LINENUM max_pos_offset = max_where - first_guess;
|
|
+ LINENUM max_neg_offset = first_guess - min_where;
|
|
+ LINENUM max_offset = (max_pos_offset < max_neg_offset
|
|
+ ? max_neg_offset : max_pos_offset);
|
|
+
|
|
+ /* Do not try lines <= 0. */
|
|
+ if (first_guess <= max_neg_offset)
|
|
+ max_neg_offset = first_guess - 1;
|
|
+
|
|
+ for (offset = 0; offset <= max_offset; offset++) {
|
|
+ if (offset <= max_pos_offset) {
|
|
+ register LINENUM mismatched;
|
|
+
|
|
+ mismatched = min_mismatches(first_guess - offset, lowest);
|
|
+ if (mismatched < lowest) {
|
|
+ lowest = mismatched;
|
|
+ where = first_guess - offset;
|
|
+ if (lowest == 1)
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ if (0 < offset && offset <= max_neg_offset) {
|
|
+ register LINENUM mismatched;
|
|
+
|
|
+ mismatched = min_mismatches(first_guess + offset, lowest);
|
|
+ if (mismatched < lowest) {
|
|
+ lowest = mismatched;
|
|
+ where = first_guess + offset;
|
|
+ if (lowest == 1)
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ return where;
|
|
+}
|
|
+
|
|
/* A FUZZ value of -1 indicates that the hunk could not be applied. */
|
|
|
|
static bool merge_hunk (struct outstate *outstate, LINENUM where, LINENUM fuzz)
|