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 3b0f3d61 2020-01-22 neels
22 3b0f3d61 2020-01-22 neels #include <err.h>
23 3b0f3d61 2020-01-22 neels #include <fcntl.h>
24 3b0f3d61 2020-01-22 neels #include <inttypes.h>
25 3b0f3d61 2020-01-22 neels #include <stdio.h>
26 3b0f3d61 2020-01-22 neels #include <stdlib.h>
27 3b0f3d61 2020-01-22 neels #include <unistd.h>
28 3b0f3d61 2020-01-22 neels
29 8ad022d2 2020-05-05 neels #include <diff/diff_main.h>
30 8ad022d2 2020-05-05 neels #include <diff/diff_output.h>
31 8ad022d2 2020-05-05 neels
32 3b0f3d61 2020-01-22 neels #ifdef __linux__
33 3b0f3d61 2020-01-22 neels /* stupid shims to compile and test on linux */
34 3b0f3d61 2020-01-22 neels #define __dead
35 3b0f3d61 2020-01-22 neels
36 3b0f3d61 2020-01-22 neels static const char *getprogname()
37 3b0f3d61 2020-01-22 neels {
38 3b0f3d61 2020-01-22 neels return "diff";
39 3b0f3d61 2020-01-22 neels }
40 3b0f3d61 2020-01-22 neels #endif
41 3b0f3d61 2020-01-22 neels
42 3b0f3d61 2020-01-22 neels __dead void usage(void);
43 3b0f3d61 2020-01-22 neels int diffreg(char *, char *, int);
44 3b0f3d61 2020-01-22 neels char *mmapfile(const char *, struct stat *);
45 3b0f3d61 2020-01-22 neels
46 3b0f3d61 2020-01-22 neels __dead void
47 3b0f3d61 2020-01-22 neels usage(void)
48 3b0f3d61 2020-01-22 neels {
49 760fe30e 2020-05-05 neels fprintf(stderr,
50 760fe30e 2020-05-05 neels "usage: %s [-p] file1 file2\n"
51 760fe30e 2020-05-05 neels "\n"
52 760fe30e 2020-05-05 neels " -p Use Patience Diff (slower but often nicer)\n"
53 760fe30e 2020-05-05 neels , getprogname());
54 3b0f3d61 2020-01-22 neels exit(1);
55 3b0f3d61 2020-01-22 neels }
56 3b0f3d61 2020-01-22 neels
57 760fe30e 2020-05-05 neels static bool do_patience = false;
58 760fe30e 2020-05-05 neels
59 3b0f3d61 2020-01-22 neels int
60 3b0f3d61 2020-01-22 neels main(int argc, char *argv[])
61 3b0f3d61 2020-01-22 neels {
62 3b0f3d61 2020-01-22 neels int ch;
63 3b0f3d61 2020-01-22 neels
64 760fe30e 2020-05-05 neels while ((ch = getopt(argc, argv, "p")) != -1) {
65 3b0f3d61 2020-01-22 neels switch (ch) {
66 760fe30e 2020-05-05 neels case 'p':
67 760fe30e 2020-05-05 neels do_patience = true;
68 760fe30e 2020-05-05 neels break;
69 3b0f3d61 2020-01-22 neels default:
70 3b0f3d61 2020-01-22 neels usage();
71 3b0f3d61 2020-01-22 neels }
72 3b0f3d61 2020-01-22 neels }
73 3b0f3d61 2020-01-22 neels
74 3b0f3d61 2020-01-22 neels argc -= optind;
75 3b0f3d61 2020-01-22 neels argv += optind;
76 3b0f3d61 2020-01-22 neels
77 3b0f3d61 2020-01-22 neels if (argc != 2)
78 3b0f3d61 2020-01-22 neels usage();
79 3b0f3d61 2020-01-22 neels
80 3b0f3d61 2020-01-22 neels return diffreg(argv[0], argv[1], 0);
81 3b0f3d61 2020-01-22 neels }
82 3b0f3d61 2020-01-22 neels
83 0d27172a 2020-05-06 neels const struct diff_algo_config myers_then_patience;
84 0d27172a 2020-05-06 neels const struct diff_algo_config myers_then_myers_divide;
85 0d27172a 2020-05-06 neels const struct diff_algo_config patience;
86 0d27172a 2020-05-06 neels const struct diff_algo_config myers_divide;
87 3b0f3d61 2020-01-22 neels
88 760fe30e 2020-05-05 neels const struct diff_algo_config myers_then_patience = (struct diff_algo_config){
89 3b0f3d61 2020-01-22 neels .impl = diff_algo_myers,
90 9e668157 2020-01-27 neels .permitted_state_size = 1024 * 1024 * sizeof(int),
91 3b0f3d61 2020-01-22 neels .fallback_algo = &patience,
92 3b0f3d61 2020-01-22 neels };
93 3b0f3d61 2020-01-22 neels
94 0d27172a 2020-05-06 neels const struct diff_algo_config myers_then_myers_divide =
95 0d27172a 2020-05-06 neels (struct diff_algo_config){
96 760fe30e 2020-05-05 neels .impl = diff_algo_myers,
97 760fe30e 2020-05-05 neels .permitted_state_size = 1024 * 1024 * sizeof(int),
98 760fe30e 2020-05-05 neels .fallback_algo = &myers_divide,
99 760fe30e 2020-05-05 neels };
100 760fe30e 2020-05-05 neels
101 3b0f3d61 2020-01-22 neels const struct diff_algo_config patience = (struct diff_algo_config){
102 3b0f3d61 2020-01-22 neels .impl = diff_algo_patience,
103 0d27172a 2020-05-06 neels /* After subdivision, do Patience again: */
104 0d27172a 2020-05-06 neels .inner_algo = &patience,
105 0d27172a 2020-05-06 neels /* If subdivision failed, do Myers Divide et Impera: */
106 0d27172a 2020-05-06 neels .fallback_algo = &myers_then_myers_divide,
107 3b0f3d61 2020-01-22 neels };
108 3b0f3d61 2020-01-22 neels
109 3b0f3d61 2020-01-22 neels const struct diff_algo_config myers_divide = (struct diff_algo_config){
110 3b0f3d61 2020-01-22 neels .impl = diff_algo_myers_divide,
111 0d27172a 2020-05-06 neels /* When division succeeded, start from the top: */
112 0d27172a 2020-05-06 neels .inner_algo = &myers_then_myers_divide,
113 0d27172a 2020-05-06 neels /* (fallback_algo = NULL implies diff_algo_none). */
114 3b0f3d61 2020-01-22 neels };
115 3b0f3d61 2020-01-22 neels
116 3b0f3d61 2020-01-22 neels const struct diff_config diff_config = {
117 3b0f3d61 2020-01-22 neels .atomize_func = diff_atomize_text_by_line,
118 760fe30e 2020-05-05 neels .algo = &myers_then_myers_divide,
119 3b0f3d61 2020-01-22 neels };
120 3b0f3d61 2020-01-22 neels
121 760fe30e 2020-05-05 neels const struct diff_config diff_config_patience = {
122 760fe30e 2020-05-05 neels .atomize_func = diff_atomize_text_by_line,
123 760fe30e 2020-05-05 neels .algo = &myers_then_patience,
124 760fe30e 2020-05-05 neels };
125 760fe30e 2020-05-05 neels
126 3b0f3d61 2020-01-22 neels int
127 3b0f3d61 2020-01-22 neels diffreg(char *file1, char *file2, int flags)
128 3b0f3d61 2020-01-22 neels {
129 3b0f3d61 2020-01-22 neels char *str1, *str2;
130 3b0f3d61 2020-01-22 neels struct stat st1, st2;
131 3b0f3d61 2020-01-22 neels struct diff_input_info info = {
132 3b0f3d61 2020-01-22 neels .left_path = file1,
133 3b0f3d61 2020-01-22 neels .right_path = file2,
134 3b0f3d61 2020-01-22 neels };
135 f8cbb8fe 2020-05-05 neels struct diff_result *result;
136 f8cbb8fe 2020-05-05 neels enum diff_rc rc;
137 0d27172a 2020-05-06 neels const struct diff_config *cfg;
138 0d27172a 2020-05-06 neels
139 0d27172a 2020-05-06 neels cfg = do_patience ? &diff_config_patience : &diff_config;
140 3b0f3d61 2020-01-22 neels
141 3b0f3d61 2020-01-22 neels str1 = mmapfile(file1, &st1);
142 3b0f3d61 2020-01-22 neels str2 = mmapfile(file2, &st2);
143 3b0f3d61 2020-01-22 neels
144 760fe30e 2020-05-05 neels result = diff_main(cfg, str1, st1.st_size, str2, st2.st_size);
145 f8cbb8fe 2020-05-05 neels #if 0
146 f8cbb8fe 2020-05-05 neels rc = diff_output_plain(stdout, &info, result);
147 f8cbb8fe 2020-05-05 neels #else
148 f8cbb8fe 2020-05-05 neels rc = diff_output_unidiff(stdout, &info, result, 3);
149 f8cbb8fe 2020-05-05 neels #endif
150 f8cbb8fe 2020-05-05 neels diff_result_free(result);
151 3b0f3d61 2020-01-22 neels
152 3b0f3d61 2020-01-22 neels munmap(str1, st1.st_size);
153 3b0f3d61 2020-01-22 neels munmap(str2, st2.st_size);
154 3b0f3d61 2020-01-22 neels
155 f8cbb8fe 2020-05-05 neels return rc;
156 3b0f3d61 2020-01-22 neels }
157 3b0f3d61 2020-01-22 neels
158 3b0f3d61 2020-01-22 neels char *
159 3b0f3d61 2020-01-22 neels mmapfile(const char *path, struct stat *st)
160 3b0f3d61 2020-01-22 neels {
161 3b0f3d61 2020-01-22 neels int fd;
162 3b0f3d61 2020-01-22 neels char *p;
163 3b0f3d61 2020-01-22 neels
164 3b0f3d61 2020-01-22 neels fd = open(path, O_RDONLY);
165 3b0f3d61 2020-01-22 neels if (fd == -1)
166 3b0f3d61 2020-01-22 neels err(2, "%s", path);
167 3b0f3d61 2020-01-22 neels
168 3b0f3d61 2020-01-22 neels if (fstat(fd, st) == -1)
169 3b0f3d61 2020-01-22 neels err(2, "%s", path);
170 3b0f3d61 2020-01-22 neels
171 3b0f3d61 2020-01-22 neels if ((uintmax_t)st->st_size > SIZE_MAX)
172 3b0f3d61 2020-01-22 neels errx(2, "%s: file too big to fit memory", path);
173 3b0f3d61 2020-01-22 neels
174 3b0f3d61 2020-01-22 neels p = mmap(NULL, st->st_size, PROT_READ, MAP_PRIVATE, fd, 0);
175 3b0f3d61 2020-01-22 neels if (p == MAP_FAILED)
176 3b0f3d61 2020-01-22 neels err(2, "mmap");
177 3b0f3d61 2020-01-22 neels
178 3b0f3d61 2020-01-22 neels close(fd);
179 3b0f3d61 2020-01-22 neels
180 3b0f3d61 2020-01-22 neels return p;
181 3b0f3d61 2020-01-22 neels }