static void print_ifdef_hunk (struct change *hunk) { lin first0, last0, first1, last1; /* Determine range of line numbers involved in each file. */ enum changes changes = analyze_hunk (hunk, &first0, &last0, &first1, &last1); if (!changes) return; begin_output (); /* Print lines up to this change. */ if (next_line0 < first0 || next_line1 < first1) format_ifdef (group_format[UNCHANGED], next_line0, first0, next_line1, first1); /* Print this change. */ next_line0 = last0 + 1; next_line1 = last1 + 1; format_ifdef (group_format[changes], first0, next_line0, first1, next_line1); }
static void print_rcs_hunk (struct change *hunk) { lin i, f0, l0, f1, l1; long int tf0, tl0, tf1, tl1; /* Determine range of line numbers involved in each file. */ enum changes changes = analyze_hunk (hunk, &f0, &l0, &f1, &l1); if (!changes) return; begin_output (); translate_range (&files[0], f0, l0, &tf0, &tl0); if (changes & OLD) { /* For deletion, print just the starting line number from file 0 and the number of lines deleted. */ fprintf (outfile, "d%ld %ld\n", tf0, tf0 <= tl0 ? tl0 - tf0 + 1 : 1); } if (changes & NEW) { /* Take last-line-number from file 0 and # lines from file 1. */ translate_range (&files[1], f1, l1, &tf1, &tl1); fprintf (outfile, "a%ld %ld\n", tl0, tf1 <= tl1 ? tl1 - tf1 + 1 : 1); /* Print the inserted lines. */ for (i = f1; i <= l1; i++) print_1_line ("", &files[1].linbuf[i]); } }
static void pr_forward_ed_hunk (struct change *hunk) { lin i, f0, l0, f1, l1; /* Determine range of line numbers involved in each file. */ enum changes changes = analyze_hunk (hunk, &f0, &l0, &f1, &l1); if (!changes) return; begin_output (); fputc (change_letter[changes], outfile); print_number_range (' ', files, f0, l0); fputc ('\n', outfile); /* If deletion only, print just the number range. */ if (changes == OLD) return; /* For insertion (with or without deletion), print the number range and the lines from file 2. */ for (i = f1; i <= l1; i++) print_1_line ("", &files[1].linbuf[i]); fputs (".\n", outfile); }
static void print_normal_hunk (struct change *hunk) { lin first0, last0, first1, last1; register lin i; /* Determine range of line numbers involved in each file. */ enum changes changes = analyze_hunk (hunk, &first0, &last0, &first1, &last1); if (!changes) return; begin_output (); /* Print out the line number header for this hunk */ print_number_range (',', &files[0], first0, last0); fprintf (outfile, "%c", change_letter[changes]); print_number_range (',', &files[1], first1, last1); fprintf (outfile, "\n"); /* Print the lines that the first file has. */ if (changes & OLD) for (i = first0; i <= last0; i++) print_1_line ("<", &files[0].linbuf[i]); if (changes == CHANGED) fprintf (outfile, "---\n"); /* Print the lines that the second file has. */ if (changes & NEW) for (i = first1; i <= last1; i++) print_1_line (">", &files[1].linbuf[i]); }
static void print_ed_hunk (struct change *hunk) { lin f0, l0, f1, l1; enum changes changes; #ifdef DEBUG debug_script (hunk); #endif /* Determine range of line numbers involved in each file. */ changes = analyze_hunk (hunk, &f0, &l0, &f1, &l1); if (!changes) return; begin_output (); /* Print out the line number header for this hunk */ print_number_range (',', &files[0], f0, l0); fputc (change_letter[changes], outfile); fputc ('\n', outfile); /* Print new/changed lines from second file, if needed */ if (changes != OLD) { lin i; bool insert_mode = true; for (i = f1; i <= l1; i++) { if (!insert_mode) { fputs ("a\n", outfile); insert_mode = true; } if (files[1].linbuf[i][0] == '.' && files[1].linbuf[i][1] == '\n') { /* The file's line is just a dot, and it would exit insert mode. Precede the dot with another dot, exit insert mode and remove the extra dot. */ fputs ("..\n.\ns/.//\n", outfile); insert_mode = false; } else print_1_line ("", &files[1].linbuf[i]); } if (insert_mode) fputs (".\n", outfile); } }
static void print_sdiff_hunk (struct change *hunk) { lin first0, last0, first1, last1; register lin i, j; /* Determine range of line numbers involved in each file. */ enum changes changes = analyze_hunk (hunk, &first0, &last0, &first1, &last1); if (!changes) return; /* Print out lines up to this change. */ print_sdiff_common_lines (first0, first1); if (sdiff_merge_assist) { long int len0 = last0 - first0 + 1; long int len1 = last1 - first1 + 1; fprintf (outfile, "c%ld,%ld\n", len0, len1); } /* Print "xxx | xxx " lines. */ if (changes == CHANGED) { for (i = first0, j = first1; i <= last0 && j <= last1; i++, j++) print_1sdiff_line (&files[0].linbuf[i], '|', &files[1].linbuf[j]); changes = (i <= last0 ? OLD : 0) + (j <= last1 ? NEW : 0); next0 = first0 = i; next1 = first1 = j; } /* Print " > xxx " lines. */ if (changes & NEW) { for (j = first1; j <= last1; ++j) print_1sdiff_line (0, '>', &files[1].linbuf[j]); next1 = j; } /* Print "xxx < " lines. */ if (changes & OLD) { for (i = first0; i <= last0; ++i) print_1sdiff_line (&files[0].linbuf[i], '<', 0); next0 = i; } }
static void mark_ignorable (struct change *script) { while (script) { struct change *next = script->link; lin first0, last0, first1, last1; /* Turn this change into a hunk: detach it from the others. */ script->link = NULL; /* Determine whether this change is ignorable. */ script->ignore = ! analyze_hunk (script, &first0, &last0, &first1, &last1); /* Reconnect the chain as before. */ script->link = next; /* Advance to the following change. */ script = next; } }
static void mark_ignorable (struct change *script) { while (script) { struct change *next = script->link; int first0, last0, first1, last1, deletes, inserts; /* Turn this change into a hunk: detach it from the others. */ script->link = 0; /* Determine whether this change is ignorable. */ analyze_hunk (script, &first0, &last0, &first1, &last1, &deletes, &inserts, files); /* Reconnect the chain as before. */ script->link = next; /* If the change is ignorable, mark it. */ script->ignore = (char)(!deletes && !inserts); /* Advance to the following change. */ script = next; } }
static void pr_unidiff_hunk (struct change *hunk) { lin first0, last0, first1, last1; lin i, j, k; struct change *next; char const *function; FILE *out; /* Determine range of line numbers involved in each file. */ if (! analyze_hunk (hunk, &first0, &last0, &first1, &last1)) return; /* Include a context's width before and after. */ i = - files[0].prefix_lines; first0 = MAX (first0 - context, i); first1 = MAX (first1 - context, i); if (last0 < files[0].valid_lines - context) last0 += context; else last0 = files[0].valid_lines - 1; if (last1 < files[1].valid_lines - context) last1 += context; else last1 = files[1].valid_lines - 1; /* If desired, find the preceding function definition line in file 0. */ function = NULL; if (function_regexp.fastmap) function = find_function (files[0].linbuf, first0); begin_output (); out = outfile; set_color_context (LINE_NUMBER_CONTEXT); fputs ("@@ -", out); print_unidiff_number_range (&files[0], first0, last0); fputs (" +", out); print_unidiff_number_range (&files[1], first1, last1); fputs (" @@", out); set_color_context (RESET_CONTEXT); if (function) print_context_function (out, function); putc ('\n', out); next = hunk; i = first0; j = first1; while (i <= last0 || j <= last1) { /* If the line isn't a difference, output the context from file 0. */ if (!next || i < next->line0) { char const *const *line = &files[0].linbuf[i++]; if (! (suppress_blank_empty && **line == '\n')) putc (initial_tab ? '\t' : ' ', out); print_1_line (NULL, line); j++; } else { /* For each difference, first output the deleted part. */ k = next->deleted; if (k) set_color_context (DELETE_CONTEXT); while (k--) { char const * const *line = &files[0].linbuf[i++]; putc ('-', out); if (initial_tab && ! (suppress_blank_empty && **line == '\n')) putc ('\t', out); print_1_line_nl (NULL, line, true); if (!k) set_color_context (RESET_CONTEXT); if (line[1][-1] == '\n') putc ('\n', out); } /* Then output the inserted part. */ k = next->inserted; if (k) set_color_context (ADD_CONTEXT); while (k--) { char const * const *line = &files[1].linbuf[j++]; putc ('+', out); if (initial_tab && ! (suppress_blank_empty && **line == '\n')) putc ('\t', out); print_1_line_nl (NULL, line, true); if (!k) set_color_context (RESET_CONTEXT); if (line[1][-1] == '\n') putc ('\n', out); } /* We're done with this hunk, so on to the next! */ next = next->link; } } }
static void pr_context_hunk (struct change *hunk) { lin first0, last0, first1, last1, i; char const *prefix; char const *function; FILE *out; /* Determine range of line numbers involved in each file. */ enum changes changes = analyze_hunk (hunk, &first0, &last0, &first1, &last1); if (! changes) return; /* Include a context's width before and after. */ i = - files[0].prefix_lines; first0 = MAX (first0 - context, i); first1 = MAX (first1 - context, i); if (last0 < files[0].valid_lines - context) last0 += context; else last0 = files[0].valid_lines - 1; if (last1 < files[1].valid_lines - context) last1 += context; else last1 = files[1].valid_lines - 1; /* If desired, find the preceding function definition line in file 0. */ function = NULL; if (function_regexp.fastmap) function = find_function (files[0].linbuf, first0); begin_output (); out = outfile; fputs ("***************", out); if (function) print_context_function (out, function); putc ('\n', out); set_color_context (LINE_NUMBER_CONTEXT); fputs ("*** ", out); print_context_number_range (&files[0], first0, last0); fputs (" ****", out); set_color_context (RESET_CONTEXT); putc ('\n', out); if (changes & OLD) { struct change *next = hunk; if (first0 <= last0) set_color_context (DELETE_CONTEXT); for (i = first0; i <= last0; i++) { /* Skip past changes that apply (in file 0) only to lines before line I. */ while (next && next->line0 + next->deleted <= i) next = next->link; /* Compute the marking for line I. */ prefix = " "; if (next && next->line0 <= i) { /* The change NEXT covers this line. If lines were inserted here in file 1, this is "changed". Otherwise it is "deleted". */ prefix = (next->inserted > 0 ? "!" : "-"); } print_1_line_nl (prefix, &files[0].linbuf[i], true); if (i == last0) set_color_context (RESET_CONTEXT); if (files[0].linbuf[i + 1][-1] == '\n') putc ('\n', out); } } set_color_context (LINE_NUMBER_CONTEXT); fputs ("--- ", out); print_context_number_range (&files[1], first1, last1); fputs (" ----", out); set_color_context (RESET_CONTEXT); putc ('\n', out); if (changes & NEW) { struct change *next = hunk; if (first1 <= last1) set_color_context (ADD_CONTEXT); for (i = first1; i <= last1; i++) { /* Skip past changes that apply (in file 1) only to lines before line I. */ while (next && next->line1 + next->inserted <= i) next = next->link; /* Compute the marking for line I. */ prefix = " "; if (next && next->line1 <= i) { /* The change NEXT covers this line. If lines were deleted here in file 0, this is "changed". Otherwise it is "inserted". */ prefix = (next->deleted > 0 ? "!" : "+"); } print_1_line_nl (prefix, &files[1].linbuf[i], true); if (i == last1) set_color_context (RESET_CONTEXT); if (files[1].linbuf[i + 1][-1] == '\n') putc ('\n', out); } } }
static void pr_unidiff_hunk (struct change *hunk) { int first0, last0, first1, last1, show_from, show_to, i, j, k0, k1; int trans_a, trans_b; struct change *next; FILE *out; /* Determine range of line numbers involved in each file. */ analyze_hunk (hunk, &first0, &last0, &first1, &last1, &show_from, &show_to, files); if (!show_from && !show_to) return; /* Include a context's width before and after. */ i = - files[0].prefix_lines; first0 = (std::max) (first0 - context, i); first1 = (std::max) (first1 - context, i); last0 = (std::min) (last0 + context, files[0].valid_lines - 1); last1 = (std::min) (last1 + context, files[1].valid_lines - 1); out = outfile; fprintf (out, " <tr class=\"vc_diff_chunk_header\">\n"); fprintf (out, " <td style=\"width:50%%;\">\n"); translate_range (&files[0], first0, last0, &trans_a, &trans_b); fprintf (out, " <strong>Line %d</strong> \n", trans_a); fprintf (out, " <span class=\"vc_diff_chunk_extra\"></span>\n"); fprintf (out, " </td>\n"); fprintf (out, " <td style=\"width:50%%;\">\n"); translate_range (&files[1], first1, last1, &trans_a, &trans_b); fprintf (out, " <strong>Line %d</strong> \n", trans_a); fprintf (out, " <span class=\"vc_diff_chunk_extra\"></span>\n"); fprintf (out, " </td>\n"); fprintf (out, " </tr>\n"); next = hunk; i = first0; j = first1; while (i <= last0 || j <= last1) { /* If the line isn't a difference, output the context from file 0. */ if (!next || i < next->line0) { fprintf (out, " <tr>\n"); fprintf (out, " <td class=\"vc_diff_nochange\"> "); print_1_escapedhtml(&files[0].linbuf[i++]); fprintf (out, "</td>\n"); fprintf (out, " <td class=\"vc_diff_nochange\"> "); print_1_escapedhtml(&files[1].linbuf[j++]); fprintf (out, "</td>\n"); fprintf (out, " </tr>\n"); } else { k0 = next->deleted; k1 = next->inserted; if (next->inserted > 0 && next->deleted > 0) { while (k0 > 0 || k1 > 0) { fprintf (out, " <tr>\n"); if (k0 > 0) { fprintf (out, " <td class=\"vc_diff_change\"> "); print_1_escapedhtml(&files[0].linbuf[i++]); fprintf (out, "</td>\n"); } else { fprintf (out, " <td class=\"vc_diff_empty\"> </td>"); } if (k1 > 0) { fprintf (out, " <td class=\"vc_diff_change\"> "); print_1_escapedhtml(&files[1].linbuf[j++]); fprintf (out, "</td>\n"); } else { fprintf (out, " <td class=\"vc_diff_empty\"> </td>"); } fprintf (out, " </tr>\n"); if (k0 > 0) k0--; if (k1 > 0) k1--; } } else if (next->deleted > 0 ) { while (k0--) { fprintf (out, " <tr>\n"); fprintf (out, " <td class=\"vc_diff_remove\"> "); print_1_escapedhtml(&files[0].linbuf[i++]); fprintf (out, "</td>\n"); fprintf (out, " <td class=\"vc_diff_empty\"> </td>"); fprintf (out, " </tr>\n"); } } else { while (k1--) { fprintf (out, " <tr>\n"); fprintf (out, " <td class=\"vc_diff_empty\"> </td>"); fprintf (out, " <td class=\"vc_diff_add\"> "); print_1_escapedhtml(&files[1].linbuf[j++]); fprintf (out, "</td>\n"); fprintf (out, " </tr>\n"); } } /* We're done with this hunk, so on to the next! */ next = next->link; } } }
static void pr_unidiff_hunk (struct change *hunk) { lin first0, last0, first1, last1; lin i, j, k; struct change *next; char const *function; FILE *out; /* Determine range of line numbers involved in each file. */ if (! analyze_hunk (hunk, &first0, &last0, &first1, &last1)) return; /* Include a context's width before and after. */ i = - files[0].prefix_lines; first0 = MAX (first0 - context, i); first1 = MAX (first1 - context, i); if (last0 < files[0].valid_lines - context) last0 += context; else last0 = files[0].valid_lines - 1; if (last1 < files[1].valid_lines - context) last1 += context; else last1 = files[1].valid_lines - 1; /* If desired, find the preceding function definition line in file 0. */ function = 0; if (function_regexp.fastmap) function = find_function (files[0].linbuf, first0); begin_output (); out = outfile; fprintf (out, "@@ -"); print_unidiff_number_range (&files[0], first0, last0); fprintf (out, " +"); print_unidiff_number_range (&files[1], first1, last1); fprintf (out, " @@"); if (function) print_context_function (out, function); putc ('\n', out); next = hunk; i = first0; j = first1; while (i <= last0 || j <= last1) { /* If the line isn't a difference, output the context from file 0. */ if (!next || i < next->line0) { putc (initial_tab ? '\t' : ' ', out); print_1_line (0, &files[0].linbuf[i++]); j++; } else { /* For each difference, first output the deleted part. */ k = next->deleted; while (k--) { putc ('-', out); if (initial_tab) putc ('\t', out); print_1_line (0, &files[0].linbuf[i++]); } /* Then output the inserted part. */ k = next->inserted; while (k--) { putc ('+', out); if (initial_tab) putc ('\t', out); print_1_line (0, &files[1].linbuf[j++]); } /* We're done with this hunk, so on to the next! */ next = next->link; } } }
/** * @brief Compare two files (as earlier specified). * @return DIFFCODE as a result of compare. */ int DiffUtils::diffutils_compare_files() { int bin_flag = 0; int bin_file = 0; // bitmap for binary files // Do the actual comparison (generating a change script) struct change *script = NULL; bool success = Diff2Files(&script, 0, &bin_flag, false, &bin_file); if (!success) { return DIFFCODE::FILE | DIFFCODE::TEXT | DIFFCODE::CMPERR; } UINT code = DIFFCODE::FILE | DIFFCODE::TEXT | DIFFCODE::SAME; // make sure to start counting diffs at 0 // (usually it is -1 at this point, for unknown) m_ndiffs = 0; m_ntrivialdiffs = 0; if (script) { struct change *next = script; struct change *thisob = 0, *end = 0; String asLwrCaseExt; String LowerCaseExt = CA2T(m_inf[0].name); int PosOfDot = LowerCaseExt.rfind('.'); if (PosOfDot != -1) { LowerCaseExt.erase(0, PosOfDot + 1); CharLower(&*LowerCaseExt.begin()); asLwrCaseExt = LowerCaseExt; } while (next) { /* Find a set of changes that belong together. */ thisob = next; end = find_change(next); /* Disconnect them from the rest of the changes, making them a hunk, and remember the rest for next iteration. */ next = end->link; end->link = 0; #ifdef _DEBUG debug_script(thisob); #endif { /* Determine range of line numbers involved in each file. */ int first0 = 0, last0 = 0, first1 = 0, last1 = 0, deletes = 0, inserts = 0; analyze_hunk(thisob, &first0, &last0, &first1, &last1, &deletes, &inserts); if (deletes || inserts || thisob->trivial) { /* Print the lines that the first file has. */ int trans_a0 = 0, trans_b0 = 0, trans_a1 = 0, trans_b1 = 0; translate_range(&m_inf[0], first0, last0, &trans_a0, &trans_b0); translate_range(&m_inf[1], first1, last1, &trans_a1, &trans_b1); //Determine quantity of lines in this block for both sides int QtyLinesLeft = (trans_b0 - trans_a0); int QtyLinesRight = (trans_b1 - trans_a1); if(m_pOptions->m_filterCommentsLines || m_pOptions->m_bIgnoreBlankLines || m_pOptions->m_bIgnoreCase) { OP_TYPE op = OP_NONE; if (!deletes && !inserts) op = OP_TRIVIAL; else op = OP_DIFF; DIFFOPTIONS options = {0}; options.nIgnoreWhitespace = m_pOptions->m_ignoreWhitespace; options.bIgnoreBlankLines = m_pOptions->m_bIgnoreBlankLines; options.bFilterCommentsLines = m_pOptions->m_filterCommentsLines; options.bIgnoreCase = m_pOptions->m_bIgnoreCase; options.bIgnoreEol = m_pOptions->m_bIgnoreEOLDifference; m_pDiffWrapper->SetOptions(&options); m_pDiffWrapper->PostFilter(thisob->line0, QtyLinesLeft+1, thisob->line1, QtyLinesRight+1, op, *m_FilterCommentsManager, asLwrCaseExt.c_str()); if(op == OP_TRIVIAL) { thisob->trivial = 1; } } // Match lines against regular expression filters // Our strategy is that every line in both sides must // match regexp before we mark difference as ignored. if(m_pFilterList && m_pFilterList->HasRegExps()) { bool match2 = false; bool match1 = RegExpFilter(thisob->line0, thisob->line0 + QtyLinesLeft, 0); if (match1) match2 = RegExpFilter(thisob->line1, thisob->line1 + QtyLinesRight, 1); if (match1 && match2) thisob->trivial = 1; } } /* Reconnect the script so it will all be freed properly. */ end->link = next; } } } // Free change script (which we don't want) if (script != NULL) { struct change *p, *e; for (e = script; e; e = p) { if (!e->trivial) ++m_ndiffs; else ++m_ntrivialdiffs; p = e->link; free(e); } if (m_ndiffs > 0) code = code & ~DIFFCODE::SAME | DIFFCODE::DIFF; } // diff_2_files set bin_flag to -1 if different binary // diff_2_files set bin_flag to +1 if same binary if (bin_flag != 0) { // Clear text-flag, set binary flag // We don't know diff counts for binary files code = code & ~DIFFCODE::TEXT; switch (bin_file) { case BINFILE_SIDE1: code |= DIFFCODE::BINSIDE1; break; case BINFILE_SIDE2: code |= DIFFCODE::BINSIDE2; break; case BINFILE_SIDE1 | BINFILE_SIDE2: code |= DIFFCODE::BIN; break; default: _RPTF1(_CRT_ERROR, "Invalid bin_file value: %d", bin_file); break; } m_ndiffs = CDiffContext::DIFFS_UNKNOWN; } if (bin_flag < 0) { // Clear same-flag, set diff-flag code = code & ~DIFFCODE::SAME | DIFFCODE::DIFF; } return code; }