/* yuriko1.c - Don Yang (uguu.org) 02/12/06 */ #include #include #include #include #define READ_BUFFER_SIZE 1024 static char *dfa_c[] = { "\"1 \'1 /?3 0", "\\2 q0 1", "1", "*!4 /!6 0", "*!5 !4", "*!5 /!0 !4", "\n0 !6" }; static char *dfa_ml[] = { "\"1 \'1 (?3 0", "\\2 q0 1", "1", "*!+4 (?3 0", "(!5 *!6 !4", "*!+4 (!5 !4", "*!6 )z-!0 )-!4 !4" }; static char *dfa_py[] = { "\"1 \'1 #!7 0", "\\2 q3 1", "1", "q4 \"1 \'1 #!7 0", "q5 4", "q6 4", "q0 4", "\n0 !7" }; static char *dfa_scm[] = { "\"1 ;!3 0", "\\2 q0 1", "1", "\n0 !3" }; typedef struct { int state, nest; char quote, buffer_char; int continue_line, line_number; } State; static int InvertOutput = 0; static int SingleStepDFA(char **dfa, State *state, char input); static int TestDFA(char **dfa, char *input, size_t input_size); static void RunDFA(char **dfa, State *state, char *input, size_t input_size); static char **DetectFileType(FILE *infile, char *buffer, size_t *size); int main(int argc, char **argv) { char **dfa; char buffer[READ_BUFFER_SIZE]; FILE *infile; State state; size_t size; int i; char *f = __FILE__; InvertOutput = ((int)*f & 1) ^ 1; if( argc == 1 ) { dfa = DetectFileType(stdin, buffer, &size); memset(&state, 0, sizeof(State)); while( size > 0 ) { RunDFA(dfa, &state, buffer, size); size = fread(buffer, 1, READ_BUFFER_SIZE, stdin); } } else { for(i = 1; i < argc; i++) { if( argc > 2 && InvertOutput == 0 ) (void)puts(argv[i]); if( (infile = fopen(argv[i], "rb")) == NULL ) { (void)puts("can not open file"); continue; } dfa = DetectFileType(infile, buffer, &size); memset(&state, 0, sizeof(State)); while( size > 0 ) { RunDFA(dfa, &state, buffer, size); size = fread(buffer, 1, READ_BUFFER_SIZE, infile); } (void)fclose(infile); } } return 0; } #define CODE_STATE 0 #define COMMENT_STATE 1 #define BUFFER_CHAR 2 #define FLUSH_CHAR 4 static int SingleStepDFA(char **dfa, State *state, char input) { int action = CODE_STATE; char *p; #define SKIP_EDGE() \ p = strpbrk(p, "0123456789") for(p = dfa[state->state]; !isdigit(*p); p++) { assert(p != NULL); if( *p == ' ' ) continue; switch( *p ) { case 'q': if( input != state->quote ) SKIP_EDGE(); break; case 'z': if( state->nest != 1 ) SKIP_EDGE(); break; case '+': state->nest++; break; case '-': state->nest--; break; case '!': action |= COMMENT_STATE; break; case '?': action |= BUFFER_CHAR; if( state->buffer_char != '\0' ) { assert(state->buffer_char == input); action |= FLUSH_CHAR; } else { state->buffer_char = input; } break; case '\'': case '\"': if( input == *p ) state->quote = *p; else SKIP_EDGE(); break; default: if( input != *p ) SKIP_EDGE(); break; } } state->state = (int)*p - (int)'0'; return action; } static int TestDFA(char **dfa, char *input, size_t input_size) { State state; size_t i; memset(&state, 0, sizeof(State)); for(i = 0; i < input_size; i++) { if( *input == '\n' ) { if( ++(state.line_number) >= 5 ) return 0; } if( (SingleStepDFA(dfa, &state, *input++) & COMMENT_STATE) != 0 ) return 1; } return 0; } static void RunDFA(char **dfa, State *state, char *input, size_t input_size) { int action; size_t i; for(i = 0; i < input_size; i++, input++) { if( InvertOutput == 0 ) { if( state->continue_line == 0 ) { printf("%7d ", ++(state->line_number)); state->continue_line = 1; } if( *input == '\n' ) state->continue_line = 0; } action = SingleStepDFA(dfa, state, *input); if( (action & FLUSH_CHAR) != 0 ) { if( (action & COMMENT_STATE) != 0 ) (void)putchar(state->buffer_char); else (void)putchar(' '); } if( (action & BUFFER_CHAR) != 0 ) continue; if( (action & COMMENT_STATE) != InvertOutput ) { if( state->buffer_char != '\0' ) { (void)putchar(state->buffer_char); state->buffer_char = '\0'; } (void)putchar(*input); } else { if( state->buffer_char != '\0' ) { (void)putchar(' '); state->buffer_char = '\0'; } if( isspace(*input) ) (void)putchar(*input); else (void)putchar(' '); } } } static char **DetectFileType(FILE *infile, char *buffer, size_t *size) { *size = fread(buffer, 1, READ_BUFFER_SIZE, infile); if( TestDFA(dfa_c, buffer, *size) != 0 ) return dfa_c; if( TestDFA(dfa_ml, buffer, *size) != 0 ) return dfa_ml; if( TestDFA(dfa_py, buffer, *size) != 0 ) return dfa_py; if( TestDFA(dfa_scm, buffer, *size) != 0 ) return dfa_scm; return dfa_c; }