1 /** @file
2 Source code style checks.
3
4 Copyright (C) 2019 by Christian Zuckschwerdt <zany@triq.net>
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10 */
11
12 // Run with: make CTEST_OUTPUT_ON_FAILURE=1 test
13
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #include <assert.h>
18
19 #define MAX_LEN 1024
20
21 /// Source code file style checks.
22 /// Check that there are no long lines.
23 /// Check that there are no CRLF endings.
24 /// Check that there are no mixed tabs/spaces.
style_check(char * path)25 static int style_check(char *path)
26 {
27 char *strict = strstr(path, "/devices/");
28
29 FILE *fp = fopen(path, "r");
30 assert(fp);
31 if (!fp)
32 exit(EXIT_FAILURE);
33
34 int read_errors = 0;
35 int long_errors = 0;
36 int crlf_errors = 0;
37 int tabs_errors = 0;
38 int trailing_errors = 0;
39 int memc_errors = 0;
40 int funbrace_errors = 0;
41
42 int leading_tabs = 0;
43 int leading_spcs = 0;
44
45 int use_stdout = 0;
46 int use_printf = 0;
47
48 int need_cond = 0;
49
50 char str[MAX_LEN];
51 while (fgets(str, MAX_LEN, fp)) {
52 int len = strlen(str);
53 if (len <= 0) {
54 read_errors++;
55 continue;
56 }
57 if (len >= MAX_LEN - 1) {
58 long_errors++;
59 }
60 if (str[len - 1] == '\r' || (len > 1 && str[len - 2] == '\r')) {
61 crlf_errors++;
62 }
63
64 if (str[0] == '\t') {
65 leading_tabs++;
66 }
67 if (len >= 4 && str[0] == ' ' && str[1] == ' ' && str[2] == ' ' && str[3] == ' ') {
68 leading_spcs++;
69 }
70 if (len > 1 && (str[len - 2] == ' ' || str[len - 2] == '\t')) {
71 trailing_errors++;
72 }
73 if (strstr(str, "(r_device *decoder") && str[len - 2] == '{') {
74 funbrace_errors++;
75 }
76
77 if (strstr(str, "stdout")) {
78 use_stdout++;
79 }
80 char *p;
81 if ((p = strstr(str, "printf"))) {
82 if (p == str || p[-1] < '_'|| p[-1] > 'z') {
83 use_printf++;
84 }
85 }
86 if (need_cond && !strstr(str, "if (!")) {
87 // we had an alloc but no check on the following line
88 memc_errors++;
89 }
90 need_cond = 0;
91 if (strstr(str, "alloc(") && !strstr(str, "alloc()")) {
92 need_cond++;
93 }
94 if (strstr(str, "strdup(") && !strstr(str, "strdup()")) {
95 need_cond++;
96 }
97 }
98 fclose(fp);
99 if (leading_tabs && leading_spcs) {
100 tabs_errors = leading_tabs > leading_spcs ? leading_spcs : leading_tabs;
101 }
102
103 if (read_errors)
104 printf("File \"%s\" has %d READ errors.\n", path, read_errors);
105 if (long_errors)
106 printf("File \"%s\" has %d LONG line errors.\n", path, long_errors);
107 if (crlf_errors)
108 printf("File \"%s\" has %d CRLF errors.\n", path, crlf_errors);
109 if (tabs_errors)
110 printf("File \"%s\" has %d MIXED tab/spaces errors.\n", path, tabs_errors);
111 if (trailing_errors)
112 printf("File \"%s\" has %d TRAILING whitespace errors.\n", path, trailing_errors);
113 if (memc_errors)
114 printf("File \"%s\" has %d ALLOC check errors.\n", path, memc_errors);
115 if (funbrace_errors)
116 printf("File \"%s\" has %d BRACE function on newline error.\n", path, funbrace_errors);
117 if (leading_tabs)
118 printf("File \"%s\" has %d TAB indented lines.\n", path, leading_tabs);
119 if (strict && use_stdout)
120 printf("File \"%s\" has %d STDOUT lines.\n", path, use_stdout);
121 if (strict && use_printf)
122 printf("File \"%s\" has %d PRINTF lines.\n", path, use_printf);
123
124 return read_errors + long_errors + crlf_errors + tabs_errors + leading_tabs + trailing_errors
125 + funbrace_errors + (strict ? use_stdout + use_printf : 0) + memc_errors;
126 }
127
main(int argc,char * argv[])128 int main(int argc, char *argv[])
129 {
130 int failed = 0;
131 for (int i = 1; i < argc; ++i) {
132 failed += style_check(argv[i]);
133 }
134 exit(!!failed);
135 }
136