/* Print command line arguments to stdout. We implemented this to see how much code it would cost to support escape sequences. Functionally, this tool is redundant since the "echo" command available in every shell does roughly the same thing. */ #include /* Convert a single hexadecimal digit. */ static int Convert(char c) { return c >= '0' && c <= '9' ? c - '0' : (c & 15) + 9; } /* Rewrite backslash escape sequences in strings. */ static void Escape(char *s) { char *r = s, *w = s; while( *r != '\0' ) { if( *r == '\\' ) { switch( *++r ) { /* C standard escape sequences. */ #define SLASH_CHAR(input, output) \ case input: *w++ = output; r++; break; SLASH_CHAR('\\', '\\') SLASH_CHAR('\'', '\'') SLASH_CHAR('"', '"') SLASH_CHAR('?', '?') SLASH_CHAR('a', '\a') SLASH_CHAR('b', '\b') SLASH_CHAR('f', '\f') SLASH_CHAR('n', '\n') SLASH_CHAR('r', '\r') SLASH_CHAR('t', '\t') SLASH_CHAR('v', '\v') #undef SLASH_CHAR case 'x': case 'X': /* Hexadecimal character. C++23 \x{} notation is not supported. */ if( (r[1] >= '0' && r[1] <= '9') || (r[1] >= 'a' && r[1] <= 'f') || (r[1] >= 'A' && r[1] <= 'F') ) { if( (r[2] >= '0' && r[2] <= '9') || (r[2] >= 'a' && r[2] <= 'f') || (r[2] >= 'A' && r[2] <= 'F') ) { *w++ = (Convert(r[1]) << 4) | Convert(r[2]); r += 3; } else { *w++ = Convert(r[1]); r += 2; } } else { *w++ = '\\'; } break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': /* Octal character. C++23 \o{} notation is not supported. */ if( r[1] >= '0' && r[1] <= '7' ) { if( r[2] >= '0' && r[2] <= '7' ) { *w++ = (Convert(r[0]) << 6) | (Convert(r[1]) << 3) | Convert(r[2]); r += 3; } else { *w++ = (Convert(r[0]) << 3) | Convert(r[1]); r += 2; } } else { *w++ = Convert(r[0]); r++; } break; case 'e': /* ESC code. Not in the C standard, but supported by many shells. */ *w++ = 27; r++; break; default: /* Unsupported escape sequence (e.g. \u, \N, etc.) */ *w++ = '\\'; break; } } else { *w++ = *r++; } } *w = '\0'; } int main(int argc, char **argv) { int i; for(i = 1; i < argc; i++) { if( i > 1 ) putchar(' '); Escape(argv[i]); fputs(argv[i], stdout); } if( argc > 1 ) putchar('\n'); return 0; }