summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Smeding <tom@tomsmeding.com>2024-07-14 17:53:28 +0200
committerTom Smeding <tom@tomsmeding.com>2024-07-14 17:53:28 +0200
commit0ac23b651bb8b4f8f117e3061044eab173ef6d33 (patch)
treea02d22787ecb6c3bd02e61b22f2be5f3edd70031
parente11158c8390e16e20f201dbbe38abed286b5c548 (diff)
weerklank
-rw-r--r--src/weerklank.c100
1 files changed, 100 insertions, 0 deletions
diff --git a/src/weerklank.c b/src/weerklank.c
new file mode 100644
index 0000000..3092b3a
--- /dev/null
+++ b/src/weerklank.c
@@ -0,0 +1,100 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <unistd.h>
+
+#include "util/map.h"
+#include "util/versie.h"
+
+static void usage(FILE *f) {
+ fprintf(f,
+ "Gebruik: weerklank [-nehV] [touwtje]...\n"
+ "\n"
+ "Exporteer de touwtjes.\n"
+ "\n"
+ " -n Voeg geen nieuwe regel toe\n"
+ " -e Ontleed terugslagontsnappingen\n"
+ " -h Toon deze hulptekst\n"
+ " -V Toon versienummer\n");
+}
+
+struct options {
+ bool nonewline;
+ bool unescape;
+};
+
+// Returns pointer to argument array containing the file names
+static char** parse_options(int argc, char **argv, struct options *opts) {
+ int opt;
+ while ((opt = getopt(argc, argv, "nehV")) != -1) {
+ switch (opt) {
+ case 'n':
+ opts->nonewline = true;
+ break;
+
+ case 'e':
+ opts->unescape = true;
+ break;
+
+ case 'h':
+ usage(stdout);
+ exit(0);
+
+ case 'V':
+ drukkedoos_print_versie(stdout, "weerklank");
+ exit(0);
+
+ case '?':
+ usage(stderr);
+ exit(1);
+ }
+ }
+
+ return argv + optind;
+}
+
+static const char lowercase_escapes[] = "\a\b\0\0\e\f\0\0\0\0\0\0\0\n\0\0\0\r\0\t\0\v\0\0\0\0";
+
+static int fromhexdigit(char c) {
+ if ('0' <= c && c <= '9') return c - '0';
+ if ('a' <= c && c <= 'f') return c - 'a' + 10;
+ if ('A' <= c && c <= 'F') return c - 'A' + 10;
+ return -1;
+}
+
+int entry_weerklank(int argc, char **argv) {
+ struct options opts = {0};
+
+ char **args = parse_options(argc, argv, &opts);
+
+ for (int i = 0; args[i]; i++) {
+ if (i != 0) putchar(' ');
+
+ if (!opts.unescape) fputs(args[i], stdout);
+ else for (int j = 0; args[i][j]; j++) {
+ if (args[i][j] != '\\') putchar(args[i][j]);
+ else if ('a' <= args[i][j+1] && args[i][j+1] <= 'z'
+ && lowercase_escapes[args[i][j+1] - 'a'] != '\0') {
+ putchar(lowercase_escapes[args[i][j+1] - 'a']);
+ j++;
+ } else if (args[i][j+1] == '0') {
+ char n = 0;
+ int len = 0;
+ while (isdigit(args[i][j+1 + len+1]) && len < 3)
+ n = 8 * n + (args[i][j+1 + ++len] - '0');
+ putchar(n);
+ j += 1 + len;
+ } else if (args[i][j+1] == 'x') {
+ int n1, n2;
+ if ((n1 = fromhexdigit(args[i][j+2])) == -1) fputs("\\x", stdout);
+ else if ((n2 = fromhexdigit(args[i][j+3])) == -1) { putchar(n1); j += 2; }
+ else { putchar(16 * n1 + n2); j += 3; }
+ } else putchar('\\');
+ }
+ }
+
+ if (!opts.nonewline) putchar('\n');
+
+ return 0;
+}