Commit Diff


commit - 93965884a1452f6e1f50fb33a0395448fbd8b3bd
commit + 65a56b169e5746c2fe2ee46008238505c64e4908
blob - 33779b232e5c0a49cb587d8763bf9deb96411d0d
blob + 0bcda3a003c8741c8ea2e2801503387eb993bd12
--- diff/diff.c
+++ diff/diff.c
@@ -33,17 +33,26 @@
 #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"
@@ -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);