1 /* This is a _really_simple_ program, to extract the difference between two
2 * ChangeLog files. Assumptions are that the new stuff is _always_ added at the
3 * front of the new file.
4 *
5 * Assumes mmap() will work on both files, at once.
6 *
7 * Assumes first 20 bytes of old ChangeLog don't change, and that any changes
8 * total less than 10 bytes.
9 *
10 */
11 #define EX_UTILS_NO_USE_GET 1
12 #define EX_UTILS_NO_USE_LIMIT 1
13 #define EX_UTILS_NO_USE_OPEN 1
14
15 #include "ex_utils.h"
16
17 #define LINE_DIFF_LEN 10
18
add(Vstr_base * s1,const char * fname)19 static size_t add(Vstr_base *s1, const char *fname)
20 {
21 size_t old = s1->len;
22 unsigned int ern = 0;
23
24 if (!vstr_sc_mmap_file(s1, s1->len, fname, 0, 0, &ern))
25 err(EXIT_FAILURE, "mmap(%s)", fname);
26 if (old == s1->len)
27 errx(EXIT_FAILURE, "mmap(%s) is an empty file", fname);
28
29 return (vstr_sc_posdiff(++old, s1->len));
30 }
31
main(int argc,char * argv[])32 int main(int argc, char *argv[])
33 {
34 Vstr_base *s1 = ex_init(NULL); /* init the library etc. */
35 size_t old_f_pos = 0;
36 size_t old_f_len = 0;
37 size_t new_f_pos = 0;
38 size_t new_f_len = 0;
39 size_t srch_pos = 0;
40 size_t srch_len = 0;
41 size_t old_first_line_len = 0;
42 size_t found = 0;
43
44 /* if no arguments are given just do stdin to stdout */
45 if (argc != 3)
46 errx(EXIT_FAILURE, "Format: %s <old ChangeLog> <new ChangeLog>", argv[0]);
47
48 old_f_len = add(s1, argv[1]);
49 new_f_len = add(s1, argv[2]);
50
51 old_f_pos = 1;
52 new_f_pos = old_f_len + 1;
53
54 if (old_f_len > new_f_len)
55 errx(EXIT_FAILURE, "old ChangeLog is larger than new ChangeLog");
56
57 srch_pos = old_f_pos + old_first_line_len;
58 srch_len = old_f_len - old_first_line_len;
59 old_first_line_len += vstr_spn_cstr_chrs_fwd(s1, srch_pos, srch_len, "\n");
60 srch_pos = old_f_pos + old_first_line_len;
61 srch_len = old_f_len - old_first_line_len;
62 old_first_line_len += vstr_cspn_cstr_chrs_fwd(s1, srch_pos, srch_len, "\n");
63 srch_pos = old_f_pos + old_first_line_len;
64 srch_len = old_f_len - old_first_line_len;
65 old_first_line_len += vstr_spn_cstr_chrs_fwd(s1, srch_pos, srch_len, "\n");
66
67 srch_pos = new_f_pos;
68 srch_len = new_f_len;
69 while ((found = vstr_srch_vstr_fwd(s1, srch_pos, srch_len,
70 s1, old_f_pos, old_first_line_len)))
71 {
72 size_t oln_len = vstr_sc_posdiff(found, s1->len);
73
74 if (oln_len > old_f_len)
75 { if ((oln_len - old_f_len) <= LINE_DIFF_LEN) break; }
76 else
77 { if ((old_f_len - oln_len) <= LINE_DIFF_LEN) break; }
78
79 srch_pos = found + 1;
80 srch_len = vstr_sc_posdiff(srch_pos, s1->len);
81 }
82
83 if (!found)
84 errx(EXIT_FAILURE, "old ChangeLog doesn't have a line of data");
85
86 vstr_del(s1, found, vstr_sc_posdiff(found, s1->len));
87 vstr_del(s1, old_f_pos, old_f_len);
88
89 /* get rid of blanks from beg. and end */
90 vstr_del(s1, 1, vstr_spn_cstr_chrs_fwd(s1, 1, s1->len, "\n"));
91 srch_len = vstr_spn_cstr_chrs_rev(s1, 1, s1->len, "\n");
92 if (srch_len)
93 vstr_sc_reduce(s1, 1, s1->len, srch_len - 1);
94
95 /* output all remaining data */
96 io_put_all(s1, STDOUT_FILENO);
97
98 exit (ex_exit(s1, NULL));
99 }
100