Code:
/*
* Known issues:
* a) Escaped characters in quotes or double quotes
* b) Multiline comments end up being replaced by a newline (not a huge issue)
* c) probably more
*
* I apologise for the lack of comments. I removed them.
*/
#include <stdlib.h>
#include <stdio.h>
enum StateId {
UNDEFINED_STATE,
CODE, /* */
DOUBLEQUOTED,
SINGLEQUOTED,
SLASH,
COMMENTLINE,
COMMENT,
ASTERISK
};
#define MAX_TRANSITIONS 4
#define ANY_CHAR '\0'
#define MATCH 0
#define MATCH_NOT 1
/* Pointless comment
*/
struct Transition {
int match_not;
char match;
enum StateId next;
int print_prev;
int suppress_out;
};
struct State {
enum StateId state;
struct Transition transitions[MAX_TRANSITIONS];
};
static const struct State StateMachine[] = {
{ 0 }, // Undefined
{ CODE, {{MATCH, '"', DOUBLEQUOTED}, {MATCH, '\'', SINGLEQUOTED}, {MATCH, '/', SLASH}} },
{ DOUBLEQUOTED, {{MATCH, '"', CODE}} },
{ SINGLEQUOTED, {{MATCH, '\'', CODE}} },
{ SLASH, {{MATCH, '/', COMMENTLINE}, {MATCH, '*', COMMENT}, {MATCH, ANY_CHAR, CODE, 1}} },
{ COMMENTLINE, {{MATCH, '\n', CODE}} },
{ COMMENT, {{MATCH, '*', ASTERISK}} },
{ ASTERISK, {{MATCH, '/', CODE, 0, 1}, {MATCH_NOT, '*', COMMENT}} }
};
enum StateId get_state_idx(int c, enum StateId current_state, int *print_prev, int *suppress)
{
int token_match;
int candidate_tr;
const struct State *st = &StateMachine[current_state];
for (candidate_tr = 0; st->transitions[candidate_tr].next != UNDEFINED_STATE; candidate_tr++) {
if (st->transitions[candidate_tr].match == ANY_CHAR)
token_match = 1;
else
token_match = (c == st->transitions[candidate_tr].match);
if (st->transitions[candidate_tr].match_not)
token_match = !token_match;
if (token_match) {
current_state = st->transitions[candidate_tr].next;
*print_prev = st->transitions[candidate_tr].print_prev;
*suppress = st->transitions[candidate_tr].suppress_out;
break;
}
}
return current_state;
}
void process(FILE *in, FILE *out)
{
int c;
int prev_c = '\0';
int print_prev = 0; /* bool */
int suppress_out = 0; /* bool */
enum StateId st = CODE;
while ((c = getc(in)) != EOF) {
st = get_state_idx(c, st, &print_prev, &suppress_out);
if (print_prev && prev_c != '\0') {
putc(prev_c, out);
print_prev = 0;
}
switch (st) {
case CODE: case DOUBLEQUOTED: case SINGLEQUOTED:
if (!suppress_out)
putc(c, out);
else
suppress_out = 0;
break;
default:
break;
}
prev_c = c;
}
}
int main(void)
{
#if 0
int a = 2 / 3;
printf("This removes comments like /* comment */ and // comment from a file\n");
printf("Since it's a test input is from stdin and output is stdout\n");
#endif
process(stdin, stdout);
return 0;
}