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