1 #include <string.h>
2 #include "iobuf.h"
3 #include "msg.h"
4 #include "wrap.h"
5 #include "path.h"
6 #include "str.h"
7 
8 const char program[] = "selftest-cmp";
9 
str_diff_fnmatch(const str * a,const str * b)10 static int str_diff_fnmatch(const str* a, const str* b)
11 {
12   return !fnmatch(a->s, b->s, 0);
13 }
14 
getline(ibuf * in,str * line,const char * src)15 static int getline(ibuf* in, str* line, const char* src)
16 {
17   int i = ibuf_getstr(in, line, LF);
18   if (!i && ibuf_error(in))
19     die2sys(111, "Error reading from ", src);
20   return i;
21 }
22 
escape(const str * in,str * out)23 static void escape(const str* in, str* out)
24 {
25   unsigned int i;
26   unsigned int j;
27   int ch;
28   char buf[7*in->len];
29 
30   for (i = j = 0; i < in->len; i++) {
31     ch = (unsigned char)in->s[i];
32     if (ch < 32 && ch != '\t' && ch != '\n') {
33       buf[j++] = '^';
34       buf[j++] = ch + 64;
35     }
36     else if (ch == 127) {
37       buf[j++] = '^';
38       buf[j++] = '?';
39     }
40     else if (ch >= 128) {
41       buf[j++] = 'M';
42       buf[j++] = '-';
43       buf[j++] = (ch >= 192) ? 'C' : 'B';
44       buf[j++] = 'M';
45       buf[j++] = '-';
46       ch &= 0x3f;
47       if (ch < 32) {
48 	buf[j++] = '^';
49 	ch += 64;
50       }
51       buf[j++] = ch;
52     }
53     else
54       buf[j++] = ch;
55   }
56   wrap_str(str_copyb(out, buf, j));
57 }
58 
main(int argc,char * argv[])59 int main(int argc, char* argv[])
60 {
61   ibuf srcbuf;
62   ibuf tstbuf;
63   str sline = {0};
64   str tline = {0};
65   str xline = {0};
66   int lineno = 0;
67   int (*cmp)(const str*, const str*) = str_diff;
68 
69   if (argc != 3)
70     die1(111, "Usage: selftest-cmp SOURCE TEST-RESULT");
71   if (!ibuf_open(&srcbuf, argv[1], 0))
72     diefsys(111, "{Could not open }s", argv[1]);
73   if (!ibuf_open(&tstbuf, argv[2], 0))
74     diefsys(111, "{Could not open }s", argv[2]);
75 
76   while (ibuf_getstr(&srcbuf, &sline, LF)) {
77     if (str_starts(&sline, "#ifdef SELFTEST_EXP")) {
78       if (str_starts(&sline, "#ifdef SELFTEST_EXP_FNMATCH"))
79 	cmp = str_diff_fnmatch;
80       break;
81     }
82   }
83   if (ibuf_error(&srcbuf))
84     die1sys(111, "Error reading from source");
85   while (getline(&srcbuf, &sline, "source")) {
86     if (str_starts(&sline, "#endif"))
87       break;
88     if (!getline(&tstbuf, &tline, "test result"))
89       die1(1, "EOF on test result");
90     escape(&tline, &xline);
91     ++lineno;
92     if (cmp(&xline, &sline)) {
93       obuf_putf(&outbuf, "d{: }S", xline.len, &xline);
94       obuf_putf(&outbuf, "d{: }S", sline.len, &sline);
95       obuf_flush(&outbuf);
96       dief(1, "{Line #}d{ mismatch}", lineno);
97     }
98   }
99   if (getline(&tstbuf, &tline, "test result"))
100     die1(1, "EOF on source");
101   return 0;
102 }
103