/* yuriko2.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" }; /* struct State */ int state, nest; char quote, buffer_char; int continue_line, line_number; /* Function arguments */ char **dfa, *input; char buffer[READ_BUFFER_SIZE]; size_t size; FILE *infile; static int InvertOutput = 0; static void ResetState(void); static int SingleStepDFA(char input_c); static int TestDFA(void); static void RunDFA(void); static void DetectFileType(void); int main(int argc, char **argv) { int i; char *f = __FILE__; InvertOutput = ((int)*f & 1) ^ 1; if( argc == 1 ) { infile = stdin; DetectFileType(); ResetState(); while( size > 0 ) { RunDFA(); 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; } DetectFileType(); ResetState(); while( size > 0 ) { RunDFA(); size = fread(buffer, 1, READ_BUFFER_SIZE, infile); } (void)fclose(infile); } } return 0; } static void ResetState(void) { state = nest = continue_line = line_number = 0; buffer_char = '\0'; } #define CODE_STATE 0 #define COMMENT_STATE 1 #define BUFFER_CHAR 2 #define FLUSH_CHAR 4 static int SingleStepDFA(char input_c) { int action = CODE_STATE; char *p; #define SKIP_EDGE() \ p = strpbrk(p, "0123456789") for(p = dfa[state]; !isdigit(*p); p++) { assert(p != NULL); if( *p == ' ' ) continue; switch( *p ) { case 'q': if( input_c != quote ) SKIP_EDGE(); break; case 'z': if( nest != 1 ) SKIP_EDGE(); break; case '+': nest++; break; case '-': nest--; break; case '!': action |= COMMENT_STATE; break; case '?': action |= BUFFER_CHAR; if( buffer_char != '\0' ) { assert(buffer_char == input_c); action |= FLUSH_CHAR; } else { buffer_char = input_c; } break; case '\'': case '\"': if( input_c == *p ) quote = *p; else SKIP_EDGE(); break; default: if( input_c != *p ) SKIP_EDGE(); break; } } state = (int)*p - (int)'0'; return action; } static int TestDFA(void) { size_t i; ResetState(); input = buffer; for(i = 0; i < size; i++) { if( *input == '\n' ) { if( ++line_number >= 5 ) return 0; } if( (SingleStepDFA(*input++) & COMMENT_STATE) != 0 ) return 1; } return 0; } static void RunDFA(void) { int action; size_t i; input = buffer; for(i = 0; i < size; i++, input++) { if( InvertOutput == 0 ) { if( continue_line == 0 ) { printf("%7d ", ++line_number); continue_line = 1; } if( *input == '\n' ) continue_line = 0; } action = SingleStepDFA(*input); if( (action & FLUSH_CHAR) != 0 ) { if( (action & COMMENT_STATE) != 0 ) (void)putchar(buffer_char); else (void)putchar(' '); } if( (action & BUFFER_CHAR) != 0 ) continue; if( (action & COMMENT_STATE) != InvertOutput ) { if( buffer_char != '\0' ) { (void)putchar(buffer_char); buffer_char = '\0'; } (void)putchar(*input); } else { if( buffer_char != '\0' ) { (void)putchar(' '); buffer_char = '\0'; } if( isspace(*input) ) (void)putchar(*input); else (void)putchar(' '); } } } static void DetectFileType(void) { size = fread(buffer, 1, READ_BUFFER_SIZE, infile); dfa = dfa_c; if( TestDFA() != 0 ) return; dfa = dfa_ml; if( TestDFA() != 0 ) return; dfa = dfa_py; if( TestDFA() != 0 ) return; dfa = dfa_scm; if( TestDFA() != 0 ) return; dfa = dfa_c; }