summary refs log tree commit diff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rwxr-xr-x.bin/xx.c71
1 files changed, 45 insertions, 26 deletions
diff --git a/.bin/xx.c b/.bin/xx.c
index 6af0d6a7..e92d12d3 100755
--- a/.bin/xx.c
+++ b/.bin/xx.c
@@ -23,34 +23,10 @@ enum {
     FLAG_ASCII = 1,
     FLAG_OFFSET = 2,
     FLAG_SKIP = 4,
+    FLAG_UNDUMP = 8,
 };
 
-int main(int argc, char *argv[]) {
-    size_t cols = 16;
-    size_t group = 8;
-    uint8_t flags = FLAG_ASCII | FLAG_OFFSET;
-    char *path = NULL;
-
-    int opt;
-    while ((opt = getopt(argc, argv, "ac:fg:hk")) > 0) {
-        switch (opt) {
-            case 'a': flags ^= FLAG_ASCII; break;
-            case 'f': flags ^= FLAG_OFFSET; break;
-            case 'k': flags ^= FLAG_SKIP; break;
-            case 'c': cols = strtoul(optarg, NULL, 10); break;
-            case 'g': group = strtoul(optarg, NULL, 10); break;
-            default:
-                fprintf(stderr, "usage: xx [-afk] [-c cols] [-g group] [file]\n");
-                return (opt == 'h') ? EX_OK : EX_USAGE;
-        }
-    }
-    if (!cols) return EX_USAGE;
-    if (argc > optind)
-        path = argv[optind];
-
-    FILE *file = path ? fopen(path, "r") : stdin;
-    if (!file) err(EX_NOINPUT, "%s", path);
-
+void dump(size_t cols, size_t group, uint8_t flags, FILE *file) {
     uint8_t buf[cols];
     size_t offset = 0, len = 0;
     for (;;) {
@@ -87,6 +63,49 @@ int main(int argc, char *argv[]) {
         printf("\n");
         if (len < sizeof(buf)) break;
     }
+}
+
+void undump(FILE *file) {
+    uint8_t byte;
+    int match;
+    while (1 == (match = fscanf(file, " %hhx", &byte))) {
+        printf("%c", byte);
+    }
+    if (match == 0) errx(EX_DATAERR, "invalid input");
+}
+
+int main(int argc, char *argv[]) {
+    size_t cols = 16;
+    size_t group = 8;
+    uint8_t flags = FLAG_ASCII | FLAG_OFFSET;
+    char *path = NULL;
+
+    int opt;
+    while ((opt = getopt(argc, argv, "ac:fg:hku")) > 0) {
+        switch (opt) {
+            case 'a': flags ^= FLAG_ASCII; break;
+            case 'f': flags ^= FLAG_OFFSET; break;
+            case 'k': flags ^= FLAG_SKIP; break;
+            case 'u': flags ^= FLAG_UNDUMP; break;
+            case 'c': cols = strtoul(optarg, NULL, 10); break;
+            case 'g': group = strtoul(optarg, NULL, 10); break;
+            default:
+                fprintf(stderr, "usage: xx [-afku] [-c cols] [-g group] [file]\n");
+                return (opt == 'h') ? EX_OK : EX_USAGE;
+        }
+    }
+    if (!cols) return EX_USAGE;
+    if (argc > optind)
+        path = argv[optind];
+
+    FILE *file = path ? fopen(path, "r") : stdin;
+    if (!file) err(EX_NOINPUT, "%s", path);
+
+    if (flags & FLAG_UNDUMP) {
+        undump(file);
+    } else {
+        dump(cols, group, flags, file);
+    }
 
     if (ferror(file)) err(EX_IOERR, "%s", path);
     return EX_OK;