commit - 93965884a1452f6e1f50fb33a0395448fbd8b3bd
commit + 65a56b169e5746c2fe2ee46008238505c64e4908
blob - 33779b232e5c0a49cb587d8763bf9deb96411d0d
blob + 0bcda3a003c8741c8ea2e2801503387eb993bd12
--- diff/diff.c
+++ diff/diff.c
#include <diff_main.h>
#include <diff_output.h>
+enum diffreg_algo {
+ DIFFREG_ALGO_MYERS_THEN_MYERS_DIVIDE = 0,
+ DIFFREG_ALGO_MYERS_THEN_PATIENCE = 1,
+ DIFFREG_ALGO_PATIENCE = 2,
+ DIFFREG_ALGO_NONE = 3,
+};
+
__dead void usage(void);
-int diffreg(char *, char *, bool, bool, int, bool);
+int diffreg(char *, char *, enum diffreg_algo, bool, int, bool);
FILE * openfile(const char *, char **, struct stat *);
__dead void
usage(void)
{
fprintf(stderr,
- "usage: %s [-pwe] [-U n] file1 file2\n"
+ "usage: %s [-PQTwe] [-U n] file1 file2\n"
"\n"
- " -p Use Patience Diff (slower but often nicer)\n"
+ " -P Use Patience Diff (slower but often nicer)\n"
+ " -Q Use forward-Myers for small files, otherwise Patience\n"
+ " -T Trivial algo: detect similar start and end only\n"
" -w Ignore Whitespace\n"
" -U n Number of Context Lines\n"
" -e Produce ed script output\n"
main(int argc, char *argv[])
{
int ch, rc;
- bool do_patience = false, ignore_whitespace = false;
+ bool ignore_whitespace = false;
bool edscript = false;
int context_lines = 3;
+ enum diffreg_algo algo = DIFFREG_ALGO_MYERS_THEN_MYERS_DIVIDE;
- while ((ch = getopt(argc, argv, "pwU:e")) != -1) {
+ while ((ch = getopt(argc, argv, "PQTwU:e")) != -1) {
switch (ch) {
- case 'p':
- do_patience = true;
+ case 'P':
+ algo = DIFFREG_ALGO_PATIENCE;
break;
+ case 'Q':
+ algo = DIFFREG_ALGO_MYERS_THEN_PATIENCE;
+ break;
+ case 'T':
+ algo = DIFFREG_ALGO_NONE;
+ break;
case 'w':
ignore_whitespace = true;
break;
if (argc != 2)
usage();
- rc = diffreg(argv[0], argv[1], do_patience, ignore_whitespace,
+ rc = diffreg(argv[0], argv[1], algo, ignore_whitespace,
context_lines, edscript);
if (rc != DIFF_RC_OK) {
fprintf(stderr, "diff: %s\n", strerror(rc));
/* (fallback_algo = NULL implies diff_algo_none). */
};
-const struct diff_config diff_config = {
+const struct diff_algo_config no_algo = (struct diff_algo_config){
+ .impl = diff_algo_none,
+};
+
+/* If the state for a forward-Myers is small enough, use Myers, otherwise first
+ * do a Myers-divide. */
+const struct diff_config diff_config_myers_then_myers_divide = {
.atomize_func = diff_atomize_text_by_line,
.algo = &myers_then_myers_divide,
};
-const struct diff_config diff_config_patience = {
+/* If the state for a forward-Myers is small enough, use Myers, otherwise first
+ * do a Patience. */
+const struct diff_config diff_config_myers_then_patience = {
.atomize_func = diff_atomize_text_by_line,
.algo = &myers_then_patience,
};
+/* Directly force Patience as a first divider of the source file. */
+const struct diff_config diff_config_patience = {
+ .atomize_func = diff_atomize_text_by_line,
+ .algo = &patience,
+};
+
+/* Directly force Patience as a first divider of the source file. */
+const struct diff_config diff_config_no_algo = {
+ .atomize_func = diff_atomize_text_by_line,
+};
+
int
-diffreg(char *file1, char *file2, bool do_patience, bool ignore_whitespace,
+diffreg(char *file1, char *file2, enum diffreg_algo algo, bool ignore_whitespace,
int context_lines, bool edscript)
{
char *str1, *str2;
const struct diff_config *cfg;
int diff_flags = 0;
- cfg = do_patience ? &diff_config_patience : &diff_config;
+ switch (algo) {
+ default:
+ case DIFFREG_ALGO_MYERS_THEN_MYERS_DIVIDE:
+ cfg = &diff_config_myers_then_myers_divide;
+ break;
+ case DIFFREG_ALGO_MYERS_THEN_PATIENCE:
+ cfg = &diff_config_myers_then_patience;
+ break;
+ case DIFFREG_ALGO_PATIENCE:
+ cfg = &diff_config_patience;
+ break;
+ case DIFFREG_ALGO_NONE:
+ cfg = &diff_config_no_algo;
+ break;
+ }
f1 = openfile(file1, &str1, &st1);
f2 = openfile(file2, &str2, &st2);