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