Blame


1 3b0f3d61 2020-01-22 neels /* Commandline diff utility to test diff implementations. */
2 3b0f3d61 2020-01-22 neels /*
3 3b0f3d61 2020-01-22 neels * Copyright (c) 2018 Martin Pieuchot
4 3b0f3d61 2020-01-22 neels * Copyright (c) 2020 Neels Hofmeyr <neels@hofmeyr.de>
5 3b0f3d61 2020-01-22 neels *
6 3b0f3d61 2020-01-22 neels * Permission to use, copy, modify, and distribute this software for any
7 3b0f3d61 2020-01-22 neels * purpose with or without fee is hereby granted, provided that the above
8 3b0f3d61 2020-01-22 neels * copyright notice and this permission notice appear in all copies.
9 3b0f3d61 2020-01-22 neels *
10 3b0f3d61 2020-01-22 neels * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 3b0f3d61 2020-01-22 neels * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 3b0f3d61 2020-01-22 neels * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 3b0f3d61 2020-01-22 neels * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 3b0f3d61 2020-01-22 neels * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 3b0f3d61 2020-01-22 neels * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 3b0f3d61 2020-01-22 neels * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 3b0f3d61 2020-01-22 neels */
18 3b0f3d61 2020-01-22 neels
19 3b0f3d61 2020-01-22 neels #include <sys/mman.h>
20 3b0f3d61 2020-01-22 neels #include <sys/stat.h>
21 18a9c7f8 2020-09-20 stsp #include <sys/types.h>
22 3b0f3d61 2020-01-22 neels
23 3b0f3d61 2020-01-22 neels #include <err.h>
24 3b0f3d61 2020-01-22 neels #include <fcntl.h>
25 3b0f3d61 2020-01-22 neels #include <inttypes.h>
26 3b0f3d61 2020-01-22 neels #include <stdio.h>
27 3b0f3d61 2020-01-22 neels #include <stdlib.h>
28 e10a628a 2020-09-16 stsp #include <stdbool.h>
29 3e6cba3a 2020-08-13 stsp #include <string.h>
30 3b0f3d61 2020-01-22 neels #include <unistd.h>
31 3b0f3d61 2020-01-22 neels
32 1dfba055 2020-10-07 stsp #include <arraylist.h>
33 1dfba055 2020-10-07 stsp #include <diff_main.h>
34 1dfba055 2020-10-07 stsp #include <diff_output.h>
35 8ad022d2 2020-05-05 neels
36 3b0f3d61 2020-01-22 neels __dead void usage(void);
37 b7ba71f0 2020-10-07 stsp int diffreg(char *, char *, bool, bool, int, bool);
38 7a54ad3a 2020-09-20 stsp FILE * openfile(const char *, char **, struct stat *);
39 3b0f3d61 2020-01-22 neels
40 3b0f3d61 2020-01-22 neels __dead void
41 3b0f3d61 2020-01-22 neels usage(void)
42 3b0f3d61 2020-01-22 neels {
43 760fe30e 2020-05-05 neels fprintf(stderr,
44 0c9a7e9d 2020-10-07 stsp "usage: %s [-pwe] [-U n] file1 file2\n"
45 760fe30e 2020-05-05 neels "\n"
46 760fe30e 2020-05-05 neels " -p Use Patience Diff (slower but often nicer)\n"
47 732e8ee0 2020-09-20 stsp " -w Ignore Whitespace\n"
48 0c9a7e9d 2020-10-07 stsp " -U n Number of Context Lines\n"
49 0c9a7e9d 2020-10-07 stsp " -e Produce ed script output\n"
50 760fe30e 2020-05-05 neels , getprogname());
51 3b0f3d61 2020-01-22 neels exit(1);
52 3b0f3d61 2020-01-22 neels }
53 3b0f3d61 2020-01-22 neels
54 3b0f3d61 2020-01-22 neels int
55 3b0f3d61 2020-01-22 neels main(int argc, char *argv[])
56 3b0f3d61 2020-01-22 neels {
57 3e6cba3a 2020-08-13 stsp int ch, rc;
58 732e8ee0 2020-09-20 stsp bool do_patience = false, ignore_whitespace = false;
59 b7ba71f0 2020-10-07 stsp bool edscript = false;
60 527f2c8a 2020-09-20 stsp int context_lines = 3;
61 3b0f3d61 2020-01-22 neels
62 0c9a7e9d 2020-10-07 stsp while ((ch = getopt(argc, argv, "pwU:e")) != -1) {
63 3b0f3d61 2020-01-22 neels switch (ch) {
64 760fe30e 2020-05-05 neels case 'p':
65 760fe30e 2020-05-05 neels do_patience = true;
66 760fe30e 2020-05-05 neels break;
67 732e8ee0 2020-09-20 stsp case 'w':
68 732e8ee0 2020-09-20 stsp ignore_whitespace = true;
69 732e8ee0 2020-09-20 stsp break;
70 0c9a7e9d 2020-10-07 stsp case 'U':
71 527f2c8a 2020-09-20 stsp context_lines = atoi(optarg);
72 527f2c8a 2020-09-20 stsp break;
73 b7ba71f0 2020-10-07 stsp case 'e':
74 b7ba71f0 2020-10-07 stsp edscript = true;
75 b7ba71f0 2020-10-07 stsp break;
76 3b0f3d61 2020-01-22 neels default:
77 3b0f3d61 2020-01-22 neels usage();
78 3b0f3d61 2020-01-22 neels }
79 3b0f3d61 2020-01-22 neels }
80 3b0f3d61 2020-01-22 neels
81 3b0f3d61 2020-01-22 neels argc -= optind;
82 3b0f3d61 2020-01-22 neels argv += optind;
83 3b0f3d61 2020-01-22 neels
84 3b0f3d61 2020-01-22 neels if (argc != 2)
85 3b0f3d61 2020-01-22 neels usage();
86 3b0f3d61 2020-01-22 neels
87 527f2c8a 2020-09-20 stsp rc = diffreg(argv[0], argv[1], do_patience, ignore_whitespace,
88 b7ba71f0 2020-10-07 stsp context_lines, edscript);
89 3e6cba3a 2020-08-13 stsp if (rc != DIFF_RC_OK) {
90 3e6cba3a 2020-08-13 stsp fprintf(stderr, "diff: %s\n", strerror(rc));
91 3e6cba3a 2020-08-13 stsp return 1;
92 3e6cba3a 2020-08-13 stsp }
93 3e6cba3a 2020-08-13 stsp return 0;
94 3b0f3d61 2020-01-22 neels }
95 3b0f3d61 2020-01-22 neels
96 0d27172a 2020-05-06 neels const struct diff_algo_config myers_then_patience;
97 0d27172a 2020-05-06 neels const struct diff_algo_config myers_then_myers_divide;
98 0d27172a 2020-05-06 neels const struct diff_algo_config patience;
99 0d27172a 2020-05-06 neels const struct diff_algo_config myers_divide;
100 3b0f3d61 2020-01-22 neels
101 760fe30e 2020-05-05 neels const struct diff_algo_config myers_then_patience = (struct diff_algo_config){
102 3b0f3d61 2020-01-22 neels .impl = diff_algo_myers,
103 9e668157 2020-01-27 neels .permitted_state_size = 1024 * 1024 * sizeof(int),
104 3b0f3d61 2020-01-22 neels .fallback_algo = &patience,
105 3b0f3d61 2020-01-22 neels };
106 3b0f3d61 2020-01-22 neels
107 0d27172a 2020-05-06 neels const struct diff_algo_config myers_then_myers_divide =
108 0d27172a 2020-05-06 neels (struct diff_algo_config){
109 760fe30e 2020-05-05 neels .impl = diff_algo_myers,
110 760fe30e 2020-05-05 neels .permitted_state_size = 1024 * 1024 * sizeof(int),
111 760fe30e 2020-05-05 neels .fallback_algo = &myers_divide,
112 760fe30e 2020-05-05 neels };
113 760fe30e 2020-05-05 neels
114 3b0f3d61 2020-01-22 neels const struct diff_algo_config patience = (struct diff_algo_config){
115 3b0f3d61 2020-01-22 neels .impl = diff_algo_patience,
116 0d27172a 2020-05-06 neels /* After subdivision, do Patience again: */
117 0d27172a 2020-05-06 neels .inner_algo = &patience,
118 0d27172a 2020-05-06 neels /* If subdivision failed, do Myers Divide et Impera: */
119 0d27172a 2020-05-06 neels .fallback_algo = &myers_then_myers_divide,
120 3b0f3d61 2020-01-22 neels };
121 3b0f3d61 2020-01-22 neels
122 3b0f3d61 2020-01-22 neels const struct diff_algo_config myers_divide = (struct diff_algo_config){
123 3b0f3d61 2020-01-22 neels .impl = diff_algo_myers_divide,
124 0d27172a 2020-05-06 neels /* When division succeeded, start from the top: */
125 0d27172a 2020-05-06 neels .inner_algo = &myers_then_myers_divide,
126 0d27172a 2020-05-06 neels /* (fallback_algo = NULL implies diff_algo_none). */
127 3b0f3d61 2020-01-22 neels };
128 3b0f3d61 2020-01-22 neels
129 3b0f3d61 2020-01-22 neels const struct diff_config diff_config = {
130 3b0f3d61 2020-01-22 neels .atomize_func = diff_atomize_text_by_line,
131 760fe30e 2020-05-05 neels .algo = &myers_then_myers_divide,
132 3b0f3d61 2020-01-22 neels };
133 3b0f3d61 2020-01-22 neels
134 760fe30e 2020-05-05 neels const struct diff_config diff_config_patience = {
135 760fe30e 2020-05-05 neels .atomize_func = diff_atomize_text_by_line,
136 760fe30e 2020-05-05 neels .algo = &myers_then_patience,
137 760fe30e 2020-05-05 neels };
138 760fe30e 2020-05-05 neels
139 3b0f3d61 2020-01-22 neels int
140 527f2c8a 2020-09-20 stsp diffreg(char *file1, char *file2, bool do_patience, bool ignore_whitespace,
141 b7ba71f0 2020-10-07 stsp int context_lines, bool edscript)
142 3b0f3d61 2020-01-22 neels {
143 3b0f3d61 2020-01-22 neels char *str1, *str2;
144 7a54ad3a 2020-09-20 stsp FILE *f1, *f2;
145 3b0f3d61 2020-01-22 neels struct stat st1, st2;
146 3b0f3d61 2020-01-22 neels struct diff_input_info info = {
147 3b0f3d61 2020-01-22 neels .left_path = file1,
148 3b0f3d61 2020-01-22 neels .right_path = file2,
149 3b0f3d61 2020-01-22 neels };
150 f8cbb8fe 2020-05-05 neels struct diff_result *result;
151 3e6cba3a 2020-08-13 stsp int rc;
152 0d27172a 2020-05-06 neels const struct diff_config *cfg;
153 00d5652b 2020-09-22 stsp int diff_flags = 0;
154 0d27172a 2020-05-06 neels
155 0d27172a 2020-05-06 neels cfg = do_patience ? &diff_config_patience : &diff_config;
156 3b0f3d61 2020-01-22 neels
157 7a54ad3a 2020-09-20 stsp f1 = openfile(file1, &str1, &st1);
158 7a54ad3a 2020-09-20 stsp f2 = openfile(file2, &str2, &st2);
159 3b0f3d61 2020-01-22 neels
160 00d5652b 2020-09-22 stsp if (ignore_whitespace)
161 00d5652b 2020-09-22 stsp diff_flags |= DIFF_FLAG_IGNORE_WHITESPACE;
162 00d5652b 2020-09-22 stsp
163 7a54ad3a 2020-09-20 stsp result = diff_main(cfg, f1, str1, st1.st_size, f2, str2, st2.st_size,
164 00d5652b 2020-09-22 stsp diff_flags);
165 f8cbb8fe 2020-05-05 neels #if 0
166 f8cbb8fe 2020-05-05 neels rc = diff_output_plain(stdout, &info, result);
167 f8cbb8fe 2020-05-05 neels #else
168 b7ba71f0 2020-10-07 stsp if (edscript)
169 b7ba71f0 2020-10-07 stsp rc = diff_output_edscript(NULL, stdout, &info, result);
170 b7ba71f0 2020-10-07 stsp else {
171 b7ba71f0 2020-10-07 stsp rc = diff_output_unidiff(NULL, stdout, &info, result,
172 b7ba71f0 2020-10-07 stsp context_lines);
173 b7ba71f0 2020-10-07 stsp }
174 f8cbb8fe 2020-05-05 neels #endif
175 f8cbb8fe 2020-05-05 neels diff_result_free(result);
176 3b0f3d61 2020-01-22 neels
177 c6eecea3 2020-07-26 stsp if (str1)
178 c6eecea3 2020-07-26 stsp munmap(str1, st1.st_size);
179 c6eecea3 2020-07-26 stsp if (str2)
180 c6eecea3 2020-07-26 stsp munmap(str2, st2.st_size);
181 7a54ad3a 2020-09-20 stsp fclose(f1);
182 7a54ad3a 2020-09-20 stsp fclose(f2);
183 3b0f3d61 2020-01-22 neels
184 f8cbb8fe 2020-05-05 neels return rc;
185 3b0f3d61 2020-01-22 neels }
186 3b0f3d61 2020-01-22 neels
187 7a54ad3a 2020-09-20 stsp FILE *
188 c6eecea3 2020-07-26 stsp openfile(const char *path, char **p, struct stat *st)
189 3b0f3d61 2020-01-22 neels {
190 7a54ad3a 2020-09-20 stsp FILE *f = NULL;
191 3b0f3d61 2020-01-22 neels
192 7a54ad3a 2020-09-20 stsp f = fopen(path, "r");
193 7a54ad3a 2020-09-20 stsp if (f == NULL)
194 3b0f3d61 2020-01-22 neels err(2, "%s", path);
195 3b0f3d61 2020-01-22 neels
196 7a54ad3a 2020-09-20 stsp if (fstat(fileno(f), st) == -1)
197 3b0f3d61 2020-01-22 neels err(2, "%s", path);
198 3b0f3d61 2020-01-22 neels
199 c6eecea3 2020-07-26 stsp #ifndef DIFF_NO_MMAP
200 7a54ad3a 2020-09-20 stsp *p = mmap(NULL, st->st_size, PROT_READ, MAP_PRIVATE, fileno(f), 0);
201 c6eecea3 2020-07-26 stsp if (*p == MAP_FAILED)
202 c6eecea3 2020-07-26 stsp #endif
203 c6eecea3 2020-07-26 stsp *p = NULL; /* fall back on file I/O */
204 3b0f3d61 2020-01-22 neels
205 7a54ad3a 2020-09-20 stsp return f;
206 3b0f3d61 2020-01-22 neels }