2020-12-12 06:33:20 +00:00
|
|
|
#define _POSIX_C_SOURCE 200809L
|
|
|
|
|
2020-02-12 05:30:50 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
|
2022-10-09 16:35:42 +00:00
|
|
|
int ctoi(char c); /* A bit of a helper function */
|
2020-02-12 05:30:50 +00:00
|
|
|
|
|
|
|
int main(int argc, char ** argv) {
|
|
|
|
int i, j, oct_temp;
|
|
|
|
char char_temp;
|
2022-10-09 16:35:42 +00:00
|
|
|
/*
|
|
|
|
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;
|
2020-02-12 05:30:50 +00:00
|
|
|
|
2022-10-09 16:35:42 +00:00
|
|
|
/*
|
|
|
|
Outer loop handles each word passed in,
|
|
|
|
inner loop handles characters within each word.
|
|
|
|
*/
|
2020-02-12 05:30:50 +00:00
|
|
|
for(i = 1; i < argc; i++) {
|
|
|
|
for(j = 0; argv[i][j] != '\0'; j++) {
|
2022-10-09 16:35:42 +00:00
|
|
|
/* We need to handle escape sequences ourself. */
|
2020-02-12 05:30:50 +00:00
|
|
|
if(argv[i][j] == '\\') {
|
2022-10-09 16:35:42 +00:00
|
|
|
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;
|
|
|
|
}
|
2020-02-12 05:30:50 +00:00
|
|
|
}
|
|
|
|
else {
|
2022-10-09 16:35:42 +00:00
|
|
|
printf("%c", argv[i][j]); /* Not a backslash? Print the character */
|
2020-02-12 05:30:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-09 16:35:42 +00:00
|
|
|
/* Print trailing newline */
|
2020-02-12 05:30:50 +00:00
|
|
|
if(trailing_newline) {
|
|
|
|
printf("\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2022-10-09 16:35:42 +00:00
|
|
|
/*
|
|
|
|
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
|
|
|
|
*/
|
2020-02-12 05:30:50 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|