diff options
Diffstat (limited to 'a8xd.c')
-rw-r--r-- | a8xd.c | 172 |
1 files changed, 172 insertions, 0 deletions
@@ -0,0 +1,172 @@ +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <unistd.h> +#include <locale.h> +#include <wchar.h> +#include <errno.h> + +#include "atables.h" + +const char **table = ata2utf; +const char *inverse_on = "\x1b[7m"; +const char *inverse_off = "\x1b[0m"; + +int verbose = 0, color = 1; + +const char *self; + +void set_self(const char *argv0) { + char *p; + + self = argv0; + p = strrchr(self, '/'); + if(p) self = p + 1; +} + +void die(const char *msg) { + fprintf(stderr, "%s: %s\n", self, msg); + exit(1); +} + +void print_help(void) { + printf("Usage: %s [-v] [file ...]\n", self); +} + +FILE *open_input(const char *file) { + FILE *input; + + if(file[0] == '-' && file[1] == 0) { + if(verbose) + fprintf(stderr, "%s: reading from standard input.\n", self); + if(freopen(NULL, "rb", stdin)) { + input = stdin; + } else { + perror("(standard input)"); + return NULL; + } + } else if(!(input = fopen(file, "rb"))) { + perror(file); + return NULL; + } + + if(verbose) + fprintf(stderr, "%s: reading from file '%s'.\n", self, file); + + return input; +} + +const char *color_off = "\x1b[0m"; + +char *get_color(unsigned char c) { + int color; + unsigned char c7 = c & 0x7f; + static char outbuf[32]; + + if(c == 0 || c == 0x9b) { + color = 1; /* red */ + } else if(c7 < 32 || c7 == 0x60 || c7 == 0x7b || c7 == 0x7d || c7 == 0x7e || c7 == 0x7f) { + color = 3; /* yellow/orange */ + } else { + color = 2; + } + + if(color) { + sprintf(outbuf, "\x1b[0;3%dm", color); + if(c & 0x80) strcat(outbuf, inverse_on); + } else { + outbuf[0] = '\0'; + } + + return outbuf; +} + +void dump_line(const unsigned char *buf, int len) { + char hex[1024], asc[1024]; + static int filepos = 0; + int hpos = 0, apos = 0, count = len; + + memset(hex, 0, sizeof(hex)); + memset(asc, 0, sizeof(asc)); + + printf("%04x: ", filepos); + while(len) { + if(color) hpos += sprintf(hex + hpos, "%s", get_color(*buf)); + hpos += sprintf(hex + hpos, "%02x", *buf); + if(color) hpos += sprintf(hex + hpos, "%s", color_off); + hex[hpos++] = ' '; + if(count - len == 7) hex[hpos++] = ' '; + + if(*buf & 0x80) apos += sprintf(asc + apos, "%s", inverse_on); + if(color) apos += sprintf(asc + apos, "%s", get_color(*buf)); + apos += sprintf(asc + apos, "%s", table[*buf & 0x7f]); + if(color || *buf & 0x80) apos += sprintf(asc + apos, "%s", color_off); + + filepos++; + buf++; + len--; + } + printf("%s", hex); + + /* what shall we use to fill the empty spaces? */ + if(count < 8) putchar(' '); + for(; count < 16; count++) fputs(" ", stdout); + + printf(" %s\n", asc); +} + +int a8xd(const char *file) { + FILE *input; + int c, len = 0; + unsigned char buf[16]; + + if( !(input = open_input(file)) ) + return 1; + + while( (c = fgetc(input)) != EOF ) { + if(len && (len % 16 == 0)) { + dump_line(buf, len); + len = 0; + } + buf[len++] = c; + } + + if(len) dump_line(buf, len); + + return 0; +} + +int main(int argc, char **argv) { + int opt, result = 0; + + set_self(argv[0]); + + if(argc > 1 && strcmp(argv[1], "--help") == 0) { + print_help(); + exit(0); + } + + if(argc > 1 && strcmp(argv[1], "--version") == 0) { + printf("%s %s\n", self, VERSION); + exit(0); + } + + while( (opt = getopt(argc, argv, "vim")) != -1) { + switch(opt) { + case 'v': verbose = 1; break; + case 'i': table = ics2utf; break; + case 'm': color = 0; break; + default: print_help(); exit(1); break; + } + } + + if(optind >= argc) { + result = a8xd("-"); + } else { + while(optind < argc) { + result += a8xd(argv[optind]); + optind++; + } + } + exit(result); +} |