#include #include char line[100000]; int lineno; /* 0 = other, 1 = if, 2 = else, 3 = endif */ int iftype; /* 0, 1, 2, ... - preprocessor indentation -1 other line -2 blank line */ int linetype() { int i = 0; int hashpos; if (line[0] == '\0') return -2; while (line[i] == ' ' || line[i] == '\t') i++; if (line[i] != '#') return -1; i++; hashpos = i; iftype = 0; while (line[i] == ' ' || line[i] == '\t') i++; if (strncmp (line + i, "if", 2) == 0 && (line[i+2] == ' ' || line[i+2] == '\t')) iftype = 1; else if (strncmp (line + i, "ifdef", 5) == 0 && (line[i+5] == ' ' || line[i+5] == '\t')) iftype = 1; else if (strncmp (line + i, "ifndef", 6) == 0 && (line[i+6] == ' ' || line[i+6] == '\t')) iftype = 1; else if (strncmp (line + i, "else", 4) == 0 && (line[i+4] == ' ' || line[i+4] == '\t' || line[i+4] == '\0')) iftype = 2; else if (strncmp (line + i, "elif", 4) == 0 && (line[i+4] == ' ' || line[i+4] == '\t')) iftype = 2; else if (strncmp (line + i, "endif", 5) == 0 && (line[i+5] == ' ' || line[i+5] == '\t' || line[i+5] == '\0')) iftype = 3; return i - hashpos; } int main (int argc, char *argv[]) { const char *filename = argv[1]; int expected_indentation = -1000; int block_lineno = 1; int block_start_indentation = 0; int block_end_expected_indentation = 0; int block_directive_count = 0; int block_if_directive_count = 0; int block_endif_directive_count = 0; int block_not_cppi_like_indented = 0; int exitcode = 0; if (freopen (filename, "r", stdin) == NULL) { fprintf (stderr, "file not found: %s\n", filename); return 1; } while (!feof (stdin)) { lineno++; if (gets (line) == NULL) break; int type = linetype(); if (type == -2) { /* end of block */ if (block_directive_count > 1 && (block_if_directive_count > 0 && block_endif_directive_count > 0) && block_not_cppi_like_indented && (block_end_expected_indentation != block_start_indentation || expected_indentation != block_start_indentation)) { fprintf (stderr, "misindented block at %s:%d\n", filename, block_lineno); exitcode = 1; } expected_indentation = -1000; block_lineno = lineno + 1; block_start_indentation = 0; block_end_expected_indentation = 0; block_directive_count = 0; block_if_directive_count = 0; block_endif_directive_count = 0; block_not_cppi_like_indented = 0; } else if (type >= 0) { if (block_directive_count == 0) { block_start_indentation = type; block_end_expected_indentation = type; expected_indentation = type; } else { if (iftype == 2 || iftype == 3) expected_indentation--; if (type != expected_indentation) block_not_cppi_like_indented = 1; expected_indentation = type; } if (iftype == 2 || iftype == 3) block_end_expected_indentation--; if (iftype == 1 || iftype == 2) { expected_indentation++; block_end_expected_indentation++; } if (iftype > 0) block_directive_count++; if (iftype == 1) block_if_directive_count++; if (iftype == 3) block_endif_directive_count++; } } /* end of file */ if (block_directive_count > 1 && (block_if_directive_count > 0 && block_endif_directive_count > 0) && block_not_cppi_like_indented && (block_end_expected_indentation != block_start_indentation || expected_indentation != block_start_indentation)) { fprintf (stderr, "misindented block at %s:%d\n", filename, block_lineno); exitcode = 1; } return exitcode; }