/* * uncomment.c * Copyright 2002-2003, Kimmo Kulovesi * * A program to remove all comments from a C program. Supports * C99 and C++ -style doubleslash comments. Should also work on * similar languages, like Objective C and Java. * * Perverse line continuation with backslashes can sometimes * confuse this, but some support is included for that, too. */ #include #include enum STATE { GOT_SLASH, CONT_SLASH, NORMAL, POSSIBLE_CONT_SLASH, IN_COMMENT, IN_COMMENT_GOT_ASTERISK_BACKSLASH, IN_COMMENT_GOT_ASTERISK, IN_COMMENT_UNTIL_EOL, IN_COMMENT_UNTIL_EOL_GOT_BACKSLASH, IN_STRING = '\"', IN_CHAR_CONST = '\'', IN_STRING_BACKSLASH = '\"' + 1, IN_CHAR_CONST_BACKSLASH = '\'' + 1 }; int main(void) { int c; enum STATE state = NORMAL; while ((c = getchar()) != EOF) { switch (state) { case CONT_SLASH: case GOT_SLASH: if (c == '*') { state = IN_COMMENT; break; } else if (c == '/') { state = IN_COMMENT_UNTIL_EOL; break; } else if (c == '\\' && state != CONT_SLASH) { state = POSSIBLE_CONT_SLASH; break; } (void) putchar('/'); if (state == CONT_SLASH) { (void) putchar('\\'); (void) putchar('\n'); } state = NORMAL; /* * FALLTHROUGH */ case NORMAL: if (c == '/') { state = GOT_SLASH; break; } if (c == '\"' || c == '\'') state = c; (void) putchar(c); break; case POSSIBLE_CONT_SLASH: /* backslash after a slash */ if (c == '\n') { state = CONT_SLASH; } else { state = NORMAL; (void) putchar('/'); (void) putchar('\\'); } break; case IN_COMMENT: if (c == '*') state = IN_COMMENT_GOT_ASTERISK; break; case IN_COMMENT_GOT_ASTERISK_BACKSLASH: if (c == '\n' || c == '*') state = IN_COMMENT_GOT_ASTERISK; else state = IN_COMMENT; break; case IN_COMMENT_GOT_ASTERISK: if (c == '/') state = NORMAL; else if (c == '\\') state = IN_COMMENT_GOT_ASTERISK_BACKSLASH; else if (c != '*') state = IN_COMMENT; break; case IN_COMMENT_UNTIL_EOL: if (c == '\\') { state = IN_COMMENT_UNTIL_EOL_GOT_BACKSLASH; } else if (c == '\n') { (void) putchar('\n'); state = NORMAL; } break; case IN_COMMENT_UNTIL_EOL_GOT_BACKSLASH: if (c != '\\') state = IN_COMMENT_UNTIL_EOL; break; case IN_STRING: case IN_CHAR_CONST: if (c == '\\') state++; /* -> to the matching backslash state */ else if (c == state) state = NORMAL; (void) putchar(c); break; case IN_STRING_BACKSLASH: case IN_CHAR_CONST_BACKSLASH: state--; /* -> to the matching non-backslash state */ (void) putchar(c); break; } } return EXIT_SUCCESS; }