/*
* 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;
}