Skip to content

Instantly share code, notes, and snippets.

@CoolOppo
Created July 22, 2014 01:27
Show Gist options
  • Save CoolOppo/93671a9c373f8686e3c5 to your computer and use it in GitHub Desktop.
Save CoolOppo/93671a9c373f8686e3c5 to your computer and use it in GitHub Desktop.
/* 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#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
@bogen
Copy link

bogen commented Jun 14, 2015

/* 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#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;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment