/* yuriko3.c - Don Yang (uguu.org) 02/12/06 */ #include #include #include #include #define READ_BUFFER_SIZE 1024 char *dfa_c[] = { "\"1 \'1 /?3 0", "\\2 q0 1", "1", "*!4 /!6 0", "*!5 !4", "*!5 /!0 !4", "\n0 !6" }; 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" }; char *dfa_py[] = { "\"1 \'1 #!7 0", "\\2 q3 1", "1", "q4 \"1 \'1 #!7 0", "q5 4", "q6 4", "q0 4", "\n0 !7" }; char *dfa_scm[] = { "\"1 ;!3 0", "\\2 q0 1", "1", "\n0 !3" }; int state, nest; char quote, buffer_char; int continue_line, line_number; char **dfa, *input; char buffer[READ_BUFFER_SIZE]; size_t size; FILE *infile; int action, a; size_t i; char *p; int InvertOutput = 0; 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 void SingleStepDFA(void) { action = CODE_STATE; #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 != 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); action |= FLUSH_CHAR; } else { buffer_char = *input; } break; case '\'': case '\"': if( *input == *p ) quote = *p; else SKIP_EDGE(); break; default: if( *input != *p ) SKIP_EDGE(); break; } } state = (int)*p - (int)'0'; } int TestDFA(void) { ResetState(); input = buffer; for(i = 0; i < size; i++) { if( *input == '\n' ) { if( ++line_number >= 5 ) return 0; } SingleStepDFA(); input++; if( (action & COMMENT_STATE) != 0 ) return 1; } return 0; } 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; } void ProcessInput(void) { DetectFileType(); ResetState(); while( size > 0 ) { /* RunDFA() */ 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; } SingleStepDFA(); 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(' '); } } size = fread(buffer, 1, READ_BUFFER_SIZE, infile); } } int main(int argc, char **argv) { char *f = __FILE__; InvertOutput = ((int)*f & 1) ^ 1; if( argc == 1 ) { infile = stdin; ProcessInput(); } else { for(a = 1; a < argc; a++) { if( argc > 2 && InvertOutput == 0 ) (void)puts(argv[a]); if( (infile = fopen(argv[a], "rb")) == NULL ) { (void)puts("can not open file"); continue; } ProcessInput(); (void)fclose(infile); } } return 0; }