commit 65a56b169e5746c2fe2ee46008238505c64e4908 from: Neels Hofmeyr date: Mon Oct 12 04:01:33 2020 UTC diff: drop -p, add -P -Q -T; diffreg(): use algo enum -p is traditionally used for "show which C function each change is in", so don't use it for choosing Patience. Instead add two options for using Patience, -P for only Patience and -Q to attempt forward-Myers first. Also add -T for a trivial diff (diff_algo_none). commit - 93965884a1452f6e1f50fb33a0395448fbd8b3bd commit + 65a56b169e5746c2fe2ee46008238505c64e4908 blob - 33779b232e5c0a49cb587d8763bf9deb96411d0d blob + 0bcda3a003c8741c8ea2e2801503387eb993bd12 --- diff/diff.c +++ diff/diff.c @@ -33,17 +33,26 @@ #include #include +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" @@ -55,15 +64,22 @@ int 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; @@ -84,7 +100,7 @@ main(int argc, char *argv[]) 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)); @@ -126,18 +142,37 @@ const struct diff_algo_config myers_divide = (struct d /* (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; @@ -152,7 +187,21 @@ diffreg(char *file1, char *file2, bool do_patience, bo 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);