#define _POSIX_C_SOURCE 200809L #include int ctoi(char c); /* A bit of a helper function */ int main(int argc, char ** argv) { int i, j, oct_temp; char char_temp; /* If /c is present in the text, we're not supposed to print a trailing newline at the end. Otherwise, we do. Hence, we start with 1 (true) for printing this and switch it to 0 if \c shows up */ int trailing_newline = 1; /* Outer loop handles each word passed in, inner loop handles characters within each word. */ for(i = 1; i < argc; i++) { for(j = 0; argv[i][j] != '\0'; j++) { /* We need to handle escape sequences ourself. */ if(argv[i][j] == '\\') { j++; switch(argv[i][j]) { case 'a': printf("\a"); break; /* alert */ case 'b': printf("\b"); break; /* backspace */ case 'c': trailing_newline = 0; break; /* suppress trailing newline */ case 'f': printf("\f"); break; /* form feed */ case 'n': printf("\n"); break; /* new line */ case 'r': printf("\r"); break; /* carriage return */ case 't': printf("\t"); break; /* horizontal tab */ case 'v': printf("\v"); break; /* vertical tab */ case '\\': printf("\\"); break; /* just print a backslash */ /* Octal sequences */ case '0': { j++; oct_temp = ctoi(argv[i][j]); /* 1 digit escape (e.g. 08) */ j++; /* 2 digit escape (e.g. 063) */ if(ctoi(argv[i][j] != -1)) { oct_temp *= 8; oct_temp += ctoi(argv[i][j]); j++; /* 3 digit escape (e.g. 0127) This is all the POSIX spec allows. */ if(ctoi(argv[i][j] != -1)) { oct_temp *= 8; oct_temp += ctoi(argv[i][j]); } else { j--; } } else { j--; } printf("%c", (char)oct_temp); } break; /* On unrecognized escape, just print it literal */ default: printf("\\%c", argv[i][j]); break; } } else { printf("%c", argv[i][j]); /* Not a backslash? Print the character */ } } } /* Print trailing newline */ if(trailing_newline) { printf("\n"); } return 0; } /* I'm really not sure whether writing a ctoi function was ideal here. Maybe I should have just used atoi? I dunno. But, at this point, I'm just gonna leave it as is. - Kat */ int ctoi(char c) { switch(c) { case '0': return 0; case '1': return 1; case '2': return 2; case '3': return 3; case '4': return 4; case '5': return 5; case '6': return 6; case '7': return 7; case '8': return 8; case '9': return 9; default: return -1; } }