Skip to content

Instantly share code, notes, and snippets.

@acdimalev
Created December 26, 2011 10:47
Show Gist options
  • Save acdimalev/1520923 to your computer and use it in GitHub Desktop.
Save acdimalev/1520923 to your computer and use it in GitHub Desktop.
#include <sys/ioctl.h>
#include <unistd.h>
#include "unicode_ascii_translation_table.c"
#define CSI "\x1B["
int is_ascii_printable(char c) {
return (c > 0x1F) & (c != 0x7F);
}
int is_ascii_non_printable(char c) {
return (c > -1) & (c < 0x20) | (c == 0x7F);
}
int is_line_feed(char c) {
return c == 0x0A;
}
int is_utf8_invalid_byte(unsigned char c) {
return (c == 192) | (c == 193) | (c > 244);
}
int is_utf8_continuation_byte(unsigned char c) {
return (c & 0xC0) == 0x80;
}
int is_utf8_start_byte(unsigned char c) {
return (c > 193) & (c < 245);
}
int x = 0;
int cols;
void barf() {
write(STDOUT_FILENO, CSI "7;33m", 7);
write(STDOUT_FILENO, "\nBARF\n", 6);
write(STDOUT_FILENO, CSI "m", 3);
}
void parse_utf8(unsigned char c) {
int i, n = 0;
unsigned long codepoint;
if ((c & 0xE0) == 0xC0) { n = 1; codepoint = c & 0x1F; }
if ((c & 0xF0) == 0xE0) { n = 2; codepoint = c & 0x0F; }
if ((c & 0xF8) == 0xF0) { n = 3; codepoint = c & 0x07; }
if ((c & 0xFC) == 0xF8) { n = 4; codepoint = c & 0x03; }
if ((c & 0xFE) == 0xFC) { n = 5; codepoint = c & 0x01; }
#ifdef RUNTIME_ERROR_CHECKING
if (n == 0) { barf(); }
#endif
for (i = 0; i < n; i++) {
read(STDIN_FILENO, &c, 1);
if (! is_utf8_continuation_byte(c)) {
write(STDOUT_FILENO, CSI "1;31m", 7);
write(STDOUT_FILENO, "!", 1);
write(STDOUT_FILENO, CSI "m", 3);
x++;
lseek(STDIN_FILENO, -1, SEEK_CUR);
return;
}
codepoint = (codepoint << 6) | (c & 0x3F);
}
if (codepoint < sizeof(unicode_ascii_translation_table)) {
c = unicode_ascii_translation_table[codepoint];
} else {
c = '?';
}
write(STDOUT_FILENO, CSI "1;34m", 7);
write(STDOUT_FILENO, &c, 1);
write(STDOUT_FILENO, CSI "m", 3);
x++;
return;
}
int main(int argc, char **argv) {
char c;
{
struct winsize w;
ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
cols = w.ws_col;
}
void space_fill() {
int i;
for (i = 0; i < cols - x; i++) {
write(STDOUT_FILENO, " ", 1);
}
}
while (read(STDIN_FILENO, &c, 1)) {
if (x == cols) { x = 0; }
if (is_ascii_printable(c)) {
write(STDOUT_FILENO, &c, 1);
x++;
continue;
}
if (is_line_feed(c)) {
write(STDOUT_FILENO, CSI "7m", 4);
space_fill();
write(STDOUT_FILENO, CSI "m", 3);
x = 0;
continue;
}
if (is_ascii_non_printable(c)) {
write(STDOUT_FILENO, CSI "1;32m", 7);
write(STDOUT_FILENO, "?", 1);
write(STDOUT_FILENO, CSI "m", 3);
x++;
continue;
}
if (is_utf8_continuation_byte(c)) {
write(STDOUT_FILENO, CSI "1;34m", 7);
write(STDOUT_FILENO, "!", 1);
write(STDOUT_FILENO, CSI "m", 3);
x++;
continue;
}
if (is_utf8_start_byte(c)) {
parse_utf8(c);
continue;
}
#ifdef RUNTIME_ERROR_CHECKING
if (!is_utf8_invalid_byte(c)) { barf(); }
#endif
write(STDOUT_FILENO, CSI "1;31m", 7);
write(STDOUT_FILENO, "!", 1);
write(STDOUT_FILENO, CSI "m", 3);
x++;
}
return 0;
}
char unicode_ascii_translation_table[] = {
'?', // 00
'?', // 01
'?', // 02
'?', // 03
'?', // 04
'?', // 05
'?', // 06
'?', // 07
'?', // 08
'?', // 09
'?', // 0A
'?', // 0B
'?', // 0C
'?', // 0D
'?', // 0E
'?', // 0F
'?', // 10
'?', // 11
'?', // 12
'?', // 13
'?', // 14
'?', // 15
'?', // 16
'?', // 17
'?', // 18
'?', // 19
'?', // 1A
'?', // 1B
'?', // 1C
'?', // 1D
'?', // 1E
'?', // 1F
'?', // 20
'?', // 21
'?', // 22
'?', // 23
'?', // 24
'?', // 25
'?', // 26
'?', // 27
'?', // 28
'?', // 29
'?', // 2A
'?', // 2B
'?', // 2C
'?', // 2D
'?', // 2E
'?', // 2F
'?', // 30
'?', // 31
'?', // 32
'?', // 33
'?', // 34
'?', // 35
'?', // 36
'?', // 37
'?', // 38
'?', // 39
'?', // 3A
'?', // 3B
'?', // 3C
'?', // 3D
'?', // 3E
'?', // 3F
'?', // 40
'?', // 41
'?', // 42
'?', // 43
'?', // 44
'?', // 45
'?', // 46
'?', // 47
'?', // 48
'?', // 49
'?', // 4A
'?', // 4B
'?', // 4C
'?', // 4D
'?', // 4E
'?', // 4F
'?', // 50
'?', // 51
'?', // 52
'?', // 53
'?', // 54
'?', // 55
'?', // 56
'?', // 57
'?', // 58
'?', // 59
'?', // 5A
'?', // 5B
'?', // 5C
'?', // 5D
'?', // 5E
'?', // 5F
'?', // 60
'?', // 61
'?', // 62
'?', // 63
'?', // 64
'?', // 65
'?', // 66
'?', // 67
'?', // 68
'?', // 69
'?', // 6A
'?', // 6B
'?', // 6C
'?', // 6D
'?', // 6E
'?', // 6F
'?', // 70
'?', // 71
'?', // 72
'?', // 73
'?', // 74
'?', // 75
'?', // 76
'?', // 77
'?', // 78
'?', // 79
'?', // 7A
'?', // 7B
'?', // 7C
'?', // 7D
'?', // 7E
'?', // 7F
'?', // 80
'?', // 81
'?', // 82
'?', // 83
'?', // 84
'?', // 85
'?', // 86
'?', // 87
'?', // 88
'?', // 89
'?', // 8A
'?', // 8B
'?', // 8C
'?', // 8D
'?', // 8E
'?', // 8F
'?', // 90
'?', // 91
'?', // 92
'?', // 93
'?', // 94
'?', // 95
'?', // 96
'?', // 97
'?', // 98
'?', // 99
'?', // 9A
'?', // 9B
'?', // 9C
'?', // 9D
'?', // 9E
'?', // 9F
'?', // A0
'?', // A1
'?', // A2
'?', // A3
'?', // A4
'?', // A5
'?', // A6
'?', // A7
'?', // A8
'?', // A9
'?', // AA
'?', // AB
'?', // AC
'?', // AD
'?', // AE
'?', // AF
'?', // B0
'?', // B1
'?', // B2
'?', // B3
'?', // B4
'?', // B5
'?', // B6
'?', // B7
'?', // B8
'?', // B9
'?', // BA
'?', // BB
'?', // BC
'?', // BD
'?', // BE
'?', // BF
'A', // C0
'A', // C1
'A', // C2
'A', // C3
'A', // C4
'A', // C5
'?', // C6
'C', // C7
'E', // C8
'E', // C9
'E', // CA
'E', // CB
'I', // CC
'I', // CD
'I', // CE
'I', // CF
'D', // D0
'N', // D1
'O', // D2
'O', // D3
'O', // D4
'O', // D5
'O', // D6
'x', // D7
'?', // D8
'U', // D9
'U', // DA
'U', // DB
'U', // DC
'Y', // DD
'?', // DE
'B', // DF
'a', // E0
'a', // E1
'a', // E2
'a', // E3
'a', // E4
'a', // E5
'?', // E6
'c', // E7
'e', // E8
'e', // E9
'e', // EA
'e', // EB
'i', // EC
'i', // ED
'i', // EE
'i', // EF
'd', // F0
'n', // F1
'o', // F2
'o', // F3
'o', // F4
'o', // F5
'o', // F6
'/', // F7
'?', // F8
'u', // F9
'u', // FA
'u', // FB
'u', // FC
'y', // FD
'?', // FE
'y', // FF
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment