---
Makefile | 1 +
tr.c | 142 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 143 insertions(+)
create mode 100644 tr.c
diff --git a/Makefile b/Makefile
index 81dfaf6..ee84221 100644
--- a/Makefile
+++ b/Makefile
_AT_@ -81,6 +81,7 @@ SRC = \
tee.c \
test.c \
touch.c \
+ tr.c \
true.c \
tty.c \
uname.c \
diff --git a/tr.c b/tr.c
new file mode 100644
index 0000000..869dbfa
--- /dev/null
+++ b/tr.c
_AT_@ -0,0 +1,142 @@
+/* See LICENSE file for copyright and license details. */
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <locale.h>
+#include <wchar.h>
+#include "text.h"
+#include "util.h"
+
+static void
+usage(void)
+{
+ eprintf("usage: %s set1 [set2]\n", argv0);
+}
+
+void
+handle_escapes(char *s)
+{
+ switch(*s) {
+ case 'n':
+ *s = '\x0A';
+ break;
+ case 't':
+ *s = '\x09';
+ break;
+ case '\\':
+ *s = '\x5c';
+ break;
+ }
+}
+
+void
+parse_mapping(char *set1, char *set2, wchar_t *mappings)
+{
+ char *s;
+ wchar_t runeleft;
+ wchar_t runeright;
+ int leftbytes;
+ int rightbytes;
+ size_t n = 0;
+ size_t lset2;
+
+ if(set2) {
+ lset2 = strnlen(set2, 255 * sizeof(wchar_t));
+ } else {
+ set2 = (char*) &set1[0];
+ lset2 = 0;
+ }
+
+ s = set1;
+ while(*s) {
+ if(*s == '\\') {
+ handle_escapes(++s);
+ }
+
+ leftbytes = mbtowc(&runeleft, (const char *) s, 4);
+ if(*(set2 + n))
+ rightbytes = mbtowc(&runeright, (const char *) set2 + n, 4);
+ mappings[runeleft] = runeright;
+
+ s += leftbytes;
+ if(n < lset2)
+ n += rightbytes;
+ }
+}
+
+void
+map_to_null(const wchar_t *mappings, char *in)
+{
+ const char *s;
+ wchar_t runeleft;
+ int leftbytes = 0;
+
+ s = in;
+ while(*s) {
+ leftbytes = mbtowc(&runeleft, s, 4);
+ if(!mappings[runeleft])
+ putwchar(runeleft);
+ s += leftbytes;
+ }
+}
+
+void
+map_to_set(const wchar_t *mappings, char *in)
+{
+ const char *s;
+ wchar_t runeleft;
+ int leftbytes = 0;
+
+ s = in;
+ while(*s) {
+ leftbytes = mbtowc(&runeleft, s, 4);
+ if(!mappings[runeleft]) {
+ putwchar(runeleft);
+ } else {
+ putwchar(mappings[runeleft]);
+ }
+ s += leftbytes;
+ }
+}
+
+int
+main(int argc, char *argv[])
+{
+ wchar_t *mappings;
+ char *buf = NULL;
+ size_t size = 0;
+ void (*mapfunc) (const wchar_t*, char*);
+
+ setlocale(LC_ALL, "");
+
+ mappings = (wchar_t *) mmap(NULL, 0x110000 * sizeof(wchar_t), PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
+
+ ARGBEGIN {
+ default:
+ usage();
+ } ARGEND;
+
+ if(!argc)
+ usage();
+
+ if(argc >= 2) {
+ parse_mapping(argv[0], argv[1], mappings);
+ mapfunc = map_to_set;
+ } else {
+ parse_mapping(argv[0], NULL, mappings);
+ mapfunc = map_to_null;
+ }
+
+ while(afgets(&buf, &size, stdin))
+ mapfunc(mappings, buf);
+ free(buf);
+
+ if (ferror(stdin)) {
+ eprintf("<stdin>: read error:");
+ return EXIT_FAILURE;
+ }
+
+ return EXIT_SUCCESS;
+}
--
1.8.5.2
Received on Mon Jan 13 2014 - 20:19:49 CET
This archive was generated by hypermail 2.3.0 : Mon Jan 13 2014 - 20:24:07 CET