Commit Diff


commit - a45330b1527e02e1627af02b55831f4cdf8794b4
commit + 760fe30eb1f6351170157beaae12a0ca0c2698a9
blob - 46bb7f527a44e83d238f01ff2980caf8ce2cd5e2
blob + 9946f9378ce360c8824bc29c354cf4d1f921648e
--- diff/diff.c
+++ diff/diff.c
@@ -46,17 +46,26 @@ char		*mmapfile(const char *, struct stat *);
 __dead void
 usage(void)
 {
-	fprintf(stderr, "usage: %s file1 file2\n", getprogname());
+	fprintf(stderr,
+		"usage: %s [-p] file1 file2\n"
+		"\n"
+		"  -p   Use Patience Diff (slower but often nicer)\n"
+		, getprogname());
 	exit(1);
 }
 
+static bool do_patience = false;
+
 int
 main(int argc, char *argv[])
 {
 	int ch;
 
-	while ((ch = getopt(argc, argv, "")) != -1) {
+	while ((ch = getopt(argc, argv, "p")) != -1) {
 		switch (ch) {
+		case 'p':
+			do_patience = true;
+			break;
 		default:
 			usage();
 		}
@@ -71,31 +80,42 @@ main(int argc, char *argv[])
 	return diffreg(argv[0], argv[1], 0);
 }
 
-const struct diff_algo_config myers, patience, myers_divide;
+const struct diff_algo_config myers_then_patience, myers_then_myers_divide, patience, myers_divide;
 
-const struct diff_algo_config myers = (struct diff_algo_config){
+const struct diff_algo_config myers_then_patience = (struct diff_algo_config){
 	.impl = diff_algo_myers,
 	.permitted_state_size = 1024 * 1024 * sizeof(int),
 	.fallback_algo = &patience,
 };
 
+const struct diff_algo_config myers_then_myers_divide = (struct diff_algo_config){
+	.impl = diff_algo_myers,
+	.permitted_state_size = 1024 * 1024 * sizeof(int),
+	.fallback_algo = &myers_divide,
+};
+
 const struct diff_algo_config patience = (struct diff_algo_config){
 	.impl = diff_algo_patience,
 	.inner_algo = &patience,	// After subdivision, do Patience again.
-	.fallback_algo = &myers_divide, // If subdivision failed, do Myers Divide et Impera.
+	.fallback_algo = &myers_then_myers_divide, // If subdivision failed, do Myers Divide et Impera.
 };
 
 const struct diff_algo_config myers_divide = (struct diff_algo_config){
 	.impl = diff_algo_myers_divide,
-	.inner_algo = &myers,		// When division succeeded, start from the top.
-					// (fallback_algo = NULL implies diff_algo_none).
+	.inner_algo = &myers_then_myers_divide,	// When division succeeded, start from the top.
+	// (fallback_algo = NULL implies diff_algo_none).
 };
 
 const struct diff_config diff_config = {
 	.atomize_func = diff_atomize_text_by_line,
-	.algo = &myers,
+	.algo = &myers_then_myers_divide,
 };
 
+const struct diff_config diff_config_patience = {
+	.atomize_func = diff_atomize_text_by_line,
+	.algo = &myers_then_patience,
+};
+
 int
 diffreg(char *file1, char *file2, int flags)
 {
@@ -107,11 +127,12 @@ diffreg(char *file1, char *file2, int flags)
 	};
 	struct diff_result *result;
 	enum diff_rc rc;
+	const struct diff_config *cfg = do_patience ? &diff_config_patience : &diff_config;
 
 	str1 = mmapfile(file1, &st1);
 	str2 = mmapfile(file2, &st2);
 
-	result = diff_main(&diff_config, str1, st1.st_size, str2, st2.st_size);
+	result = diff_main(cfg, str1, st1.st_size, str2, st2.st_size);
 #if 0
 	rc = diff_output_plain(stdout, &info, result);
 #else