1
0
mirror of git://git.suckless.org/sbase synced 2024-12-23 23:43:33 +00:00
sbase/tr.c

173 lines
2.7 KiB
C
Raw Normal View History

2013-11-15 16:25:10 +00:00
/* 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 [-d] set1 [set2]\n", argv0);
2013-11-15 16:25:10 +00:00
}
2014-01-25 22:07:13 +00:00
static void
2013-11-15 16:25:10 +00:00
handleescapes(char *s)
{
switch(*s) {
case 'n':
*s = '\n';
break;
case 't':
*s = '\t';
break;
case '\\':
*s = '\\';
break;
case 'r':
*s = '\r';
break;
case 'f':
*s = '\f';
break;
case 'a':
*s = '\a';
break;
case 'b':
*s = '\b';
break;
case 'v':
*s = '\v';
break;
}
}
2014-04-12 18:50:51 +00:00
static int
xmbtowc(wchar_t *unicodep, const char *s)
{
int rv;
rv = mbtowc(unicodep, s, 4);
if (rv < 0)
eprintf("mbtowc:");
return rv;
}
2014-01-25 22:07:13 +00:00
static void
2013-11-15 16:25:10 +00:00
parsemapping(const char *set1, const char *set2, wchar_t *mappings)
{
char *s1, *s2;
2013-11-15 16:25:10 +00:00
wchar_t runeleft;
wchar_t runeright;
int leftbytes;
int rightbytes;
s1 = (char *)set1;
if(set2)
s2 = (char *)set2;
else
s2 = (char *)set1;
2013-11-15 16:25:10 +00:00
while(*s1) {
if(*s1 == '\\')
handleescapes(++s1);
2014-04-12 18:50:51 +00:00
leftbytes = xmbtowc(&runeleft, s1);
s1 += leftbytes;
if(*s2 == '\\')
handleescapes(++s2);
if(*s2 != '\0') {
2014-04-12 18:50:51 +00:00
rightbytes = xmbtowc(&runeright, s2);
s2 += rightbytes;
}
2013-11-15 16:25:10 +00:00
mappings[runeleft] = runeright;
}
}
2014-01-25 22:07:13 +00:00
static void
2013-11-15 16:25:10 +00:00
maptonull(const wchar_t *mappings, char *in)
{
const char *s;
wchar_t runeleft;
int leftbytes = 0;
s = in;
while(*s) {
2014-04-12 18:50:51 +00:00
leftbytes = xmbtowc(&runeleft, s);
2013-11-15 16:25:10 +00:00
if(!mappings[runeleft])
putwchar(runeleft);
s += leftbytes;
}
}
2014-01-25 22:07:13 +00:00
static void
2013-11-15 16:25:10 +00:00
maptoset(const wchar_t *mappings, char *in)
{
const char *s;
wchar_t runeleft;
int leftbytes = 0;
s = in;
while(*s) {
2014-04-12 18:50:51 +00:00
leftbytes = xmbtowc(&runeleft, s);
2013-11-15 16:25:10 +00:00
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*);
int dflag = 0;
2013-11-15 16:25:10 +00:00
setlocale(LC_ALL, "");
mappings = mmap(NULL, 0x110000 * sizeof(wchar_t),
PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0);
if (mappings == MAP_FAILED)
eprintf("mmap:");
2013-11-15 16:25:10 +00:00
ARGBEGIN {
case 'd':
dflag = 1;
break;
2013-11-15 16:25:10 +00:00
default:
usage();
} ARGEND;
if(argc == 0)
usage();
if(dflag || argc == 1) {
if(argc != 1)
usage();
2013-11-15 16:25:10 +00:00
parsemapping(argv[0], NULL, mappings);
mapfunc = maptonull;
} else {
if(argc != 2)
usage();
parsemapping(argv[0], argv[1], mappings);
mapfunc = maptoset;
2013-11-15 16:25:10 +00:00
}
while(agetline(&buf, &size, stdin) != -1)
2013-11-15 16:25:10 +00:00
mapfunc(mappings, buf);
free(buf);
if(ferror(stdin))
eprintf("<stdin>: read error:");
munmap(mappings, 0x110000 * sizeof(wchar_t));
2013-11-15 16:25:10 +00:00
return EXIT_SUCCESS;
}