utf8: don't allow NUL in decoded strings.
[ccan] / tools / ccanlint / tests / hash_if.c
1 #include <tools/ccanlint/ccanlint.h>
2 #include <tools/tools.h>
3 #include <ccan/str/str.h>
4 #include <ccan/foreach/foreach.h>
5 #include <sys/types.h>
6 #include <sys/stat.h>
7 #include <fcntl.h>
8 #include <unistd.h>
9 #include <limits.h>
10 #include <errno.h>
11 #include <stdlib.h>
12 #include <stdio.h>
13 #include <err.h>
14 #include <string.h>
15 #include <ctype.h>
16
17 static void check_hash_if(struct manifest *m,
18                           unsigned int *timeleft UNNEEDED,
19                           struct score *score)
20 {
21         struct list_head *list;
22         const char *explanation =
23         "\n\t(#if works like #ifdef, but with gcc's -Wundef, we can detect\n"
24         "\tmistyped or unknown configuration options)";
25
26         /* We don't fail ccanlint for this. */ 
27         score->pass = true;
28
29         foreach_ptr(list, &m->c_files, &m->h_files,
30                     &m->run_tests, &m->api_tests,
31                     &m->compile_ok_tests, &m->compile_fail_tests,
32                     &m->other_test_c_files) {
33                 struct ccan_file *f;
34
35                 list_for_each(list, f, list) {
36                         unsigned int i;
37                         char **lines = get_ccan_file_lines(f);
38
39                         for (i = 0; lines[i]; i++) {
40                                 const char *line = lines[i];
41                                 char *sym;
42
43                                 if (!get_token(&line, "#"))
44                                         continue;
45                                 if (!(get_token(&line, "if")
46                                       && get_token(&line, "defined")
47                                       && get_token(&line, "("))
48                                     && !get_token(&line, "ifdef"))
49                                         continue;
50
51                                 sym = get_symbol_token(lines, &line);
52                                 if (!sym || !strstarts(sym, "HAVE_"))
53                                         continue;
54                                 score_file_error(score, f, i+1,
55                                                  "%s should be tested with #if"
56                                                  "%s",
57                                                  sym, explanation);
58                                 explanation = "";
59                         }
60                 }
61         }
62
63         if (!score->error) {
64                 score->score = score->total;
65         }
66 }
67
68 struct ccanlint hash_if = {
69         .key = "hash_if",
70         .name = "Features are checked with #if not #ifdef",
71         .check = check_hash_if,
72         .needs = "info_exists"
73 };
74
75 REGISTER_TEST(hash_if);