/** @file Source code style checks. Copyright (C) 2019 by Christian Zuckschwerdt This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. */ // Run with: make CTEST_OUTPUT_ON_FAILURE=1 test #include #include #include #include #define MAX_LEN 1024 /// Source code file style checks. /// Check that there are no long lines. /// Check that there are no CRLF endings. /// Check that there are no mixed tabs/spaces. static int style_check(char *path) { char *strict = strstr(path, "/devices/"); FILE *fp = fopen(path, "r"); assert(fp); if (!fp) exit(EXIT_FAILURE); int read_errors = 0; int long_errors = 0; int crlf_errors = 0; int tabs_errors = 0; int trailing_errors = 0; int memc_errors = 0; int funbrace_errors = 0; int leading_tabs = 0; int leading_spcs = 0; int use_stdout = 0; int use_printf = 0; int need_cond = 0; char str[MAX_LEN]; while (fgets(str, MAX_LEN, fp)) { int len = strlen(str); if (len <= 0) { read_errors++; continue; } if (len >= MAX_LEN - 1) { long_errors++; } if (str[len - 1] == '\r' || (len > 1 && str[len - 2] == '\r')) { crlf_errors++; } if (str[0] == '\t') { leading_tabs++; } if (len >= 4 && str[0] == ' ' && str[1] == ' ' && str[2] == ' ' && str[3] == ' ') { leading_spcs++; } if (len > 1 && (str[len - 2] == ' ' || str[len - 2] == '\t')) { trailing_errors++; } if (strstr(str, "(r_device *decoder") && str[len - 2] == '{') { funbrace_errors++; } if (strstr(str, "stdout")) { use_stdout++; } char *p; if ((p = strstr(str, "printf"))) { if (p == str || p[-1] < '_'|| p[-1] > 'z') { use_printf++; } } if (need_cond && !strstr(str, "if (!")) { // we had an alloc but no check on the following line memc_errors++; } need_cond = 0; if (strstr(str, "alloc(") && !strstr(str, "alloc()")) { need_cond++; } if (strstr(str, "strdup(") && !strstr(str, "strdup()")) { need_cond++; } } fclose(fp); if (leading_tabs && leading_spcs) { tabs_errors = leading_tabs > leading_spcs ? leading_spcs : leading_tabs; } if (read_errors) printf("File \"%s\" has %d READ errors.\n", path, read_errors); if (long_errors) printf("File \"%s\" has %d LONG line errors.\n", path, long_errors); if (crlf_errors) printf("File \"%s\" has %d CRLF errors.\n", path, crlf_errors); if (tabs_errors) printf("File \"%s\" has %d MIXED tab/spaces errors.\n", path, tabs_errors); if (trailing_errors) printf("File \"%s\" has %d TRAILING whitespace errors.\n", path, trailing_errors); if (memc_errors) printf("File \"%s\" has %d ALLOC check errors.\n", path, memc_errors); if (funbrace_errors) printf("File \"%s\" has %d BRACE function on newline error.\n", path, funbrace_errors); if (leading_tabs) printf("File \"%s\" has %d TAB indented lines.\n", path, leading_tabs); if (strict && use_stdout) printf("File \"%s\" has %d STDOUT lines.\n", path, use_stdout); if (strict && use_printf) printf("File \"%s\" has %d PRINTF lines.\n", path, use_printf); return read_errors + long_errors + crlf_errors + tabs_errors + leading_tabs + trailing_errors + funbrace_errors + (strict ? use_stdout + use_printf : 0) + memc_errors; } int main(int argc, char *argv[]) { int failed = 0; for (int i = 1; i < argc; ++i) { failed += style_check(argv[i]); } exit(!!failed); }