My turn to try: --snip-- /* * escaped string interpreter * * gcc version * * plp 2007 * * Convention: * * Input is a string in ASCIIZ suppied as argv[1] * Escape characters escape themselves: CHAR_ESC CHAR_ESC -> CHAR_ESC * * Example usage: * * ./escape 'abc \"\e "ABC\"def\"GHI\t"' * * Note that by convention an input consisting of a single escape char * '\' is illegal. The program does not detect this. * * compile with: * * gcc -Wall -g -o escape escape.c * */ #include #include #include #define VERSION "0.0" #define BANNER "escape.c " VERSION "\n" #define CHAR_ESC '\\' #define CHAR_DQUOTE '"' #define CHAR_CR '\r' #define CHAR_NL '\n' #define CHAR_TAB '\t' enum _interp_states { I_IDLE = 0, I_STRING, I_OTHER }; int main( int argc, char *argv[] ) { int Is = I_IDLE; char *p; printf( BANNER ); if(argc != 2) err( 1, "usage: scape \"string\"\n" ); // process argv[1] p = argv[1]; if(!*(p+1)) { // special, length == 1 printf( "short input '%c'\n", *p); } else { // length >= 2 while(*p++) { // now *p and *(p-1) exist and are not NUL // esc is always esc, other escs depend on context // this can be changed by moving this code inside the state machine if(*(p-1) == CHAR_ESC) { switch(*p) { case CHAR_ESC: printf( "%c", CHAR_ESC ); ++p; continue; // at while() default: ; // handled in state machine below } } // state machine, defines context (in string etc) switch( Is ) { case I_IDLE: if(*(p-1) == CHAR_ESC) { switch(*p) { case CHAR_DQUOTE: printf( "ESC-QUOTE\n" ); ++p; break; default: printf( "ESC-OTHER: '%c'\n", *p ); ++p; break; } } else { if(*(p-1) == CHAR_DQUOTE) { // string start quote Is = I_STRING; printf( "\nString: '" ); } else { printf( "%c", *(p-1)); // ordinary char outside string } } break; case I_STRING: if(*(p-1) == CHAR_ESC) { switch(*p) { // inside string, escape various things case CHAR_DQUOTE: printf( "%c", CHAR_DQUOTE ); break; case CHAR_CR: printf( "\r" ); break; case CHAR_NL: printf( "\n" ); break; case CHAR_TAB: printf( "\t" ); break; default: // unknown escape, print error and cont. printf( "ESC-UNKNOWN: '%c'\n", *p ); break; } ++p; // eat both escape and escaped } else { if(*(p-1) == CHAR_DQUOTE) { // string closing quote Is = I_IDLE; printf( "'\n" ); } else { printf( "%c", *(p-1)); // ordinary char inside string } } break; } } } printf( "\n\n*** Success. End.\n" ); return( 0 ); } // editor settings: set tabs to 2 spaces // vim:ts=2:sw=2 --snap-- Peter 'state machines always win' P. -- http://www.piclist.com PIC/SX FAQ & list archive View/change your membership options at http://mailman.mit.edu/mailman/listinfo/piclist