/* nobraces.ci: Python-style indentation for C By Ben Hoyt, 22 Sep 2007, http://benhoyt.com/ Basically you just write C code, indenting it like you would anyway, but use colons after control flow statements like in Python. Oh, and leave off all those nasty end-of-line semicolons. Okay, so it's a joke. Mostly. :-) Inspired by the Python parallel, Tim Hatch's "pybraces" (C-style braces in Python): http://timhatch.com/projects/pybraces/ This filter ain't very clever. It doesn't handle continuation lines or comments after code on a line. In short, I didn't feel like writing a C parser. If someone fleshed it out, this might even be useful ... To use it, type something like: nobraces < nobraces.ci > nobraces.c cc nobraces.c OH WAIT! It's written in itself, so you won't be able to compile it without a compiled version of nobraces ... hey, what on earth! :-) */ #include #include #include #include #define MAX_LINE 1000 #define MAX_LEVELS 20 #define TAB_SIZE 4 /* indentation levels stack, see: http://docs.python.org/ref/indentation.html */ int levels[MAX_LEVELS+1] = {0} int level_idx = 0 /* return top item on levels stack (don't pop) */ int levels_top(void): return levels[level_idx] /* push item onto levels stack */ void levels_push(int level): if (level_idx >= MAX_LEVELS): printf("More than %d indent levels!\n", MAX_LEVELS) exit(1) levels[++level_idx] = level /* pop and return top item from levels stack */ int levels_pop(void): return levels[level_idx--] /* print n spaces */ void spaces(int n): while (n--): putchar(' ') /* dedent to less-indented level, generating '}' chars as we go */ void dedents(int to_level): while (levels_top() > to_level): levels_pop() spaces(levels_top()) printf("}\n") /* expand tabs to spaces and copy back into line (must be MAX_LINE big) */ char *expand_tabs(char *line): char *tabbed, *expanded, temp_line[MAX_LINE] int column column = 0 expanded = temp_line for (tabbed=line; *tabbed; tabbed++): if (*tabbed == '\t'): *expanded++ = ' ' while (++column%TAB_SIZE != 0): *expanded++ = ' ' else: *expanded++ = *tabbed column++ *expanded = 0 strcpy(line, temp_line) return line /* strip whitespace chars from end of string */ char *rstrip(char *line): char *end end = line + strlen(line) - 1 while (end >= line && isspace(*end)): *end-- = 0 return line /* get line's indent level (number of chars till first non-space char) */ int get_indent(char *line): int i for (i=0; isspace(*line); i++): line++ return i /* nobraces, here we come */ int main(void): char line[MAX_LINE] int indent, len, in_comment /* read and process lines till EOF */ in_comment = 0 while (fgets(line, MAX_LINE, stdin)): /* massage line, get indent level and length */ rstrip(line) expand_tabs(line) indent = get_indent(line) len = strlen(line) /* ignore blank lines */ if (line[indent] == 0): continue /* leave preprocessor directives alone */ if (line[indent] == '#'): puts(line) continue /* ignore single- and multi-line comments */ if (line[indent] == '/' && line[indent+1] == '/'): continue if (line[indent] == '/' && line[indent+1] == '*'): in_comment = 1 if (in_comment): if (strstr(line, "*/")): in_comment = 0 continue /* from http://docs.python.org/ref/indentation.html */ if (indent > levels_top()): spaces(levels_top()) printf("{\n") levels_push(indent) else if (indent < levels_top()): dedents(indent) /* drop ':' from control structures, add ';' to statements */ if (line[len-1] == ':'): line[len-1] = 0 puts(line) else: fputs(line, stdout) printf(";\n") /* output any last end braces */ dedents(0) return 0