aboutsummaryrefslogtreecommitdiff
path: root/a8xd.c
diff options
context:
space:
mode:
Diffstat (limited to 'a8xd.c')
-rw-r--r--a8xd.c172
1 files changed, 172 insertions, 0 deletions
diff --git a/a8xd.c b/a8xd.c
new file mode 100644
index 0000000..52a8092
--- /dev/null
+++ b/a8xd.c
@@ -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);
+}