| 
									
										
										
										
											2013-11-15 17:25:10 +01: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) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2014-04-09 14:12:34 +02:00
										 |  |  | 	eprintf("usage: %s [-d] set1 [set2]\n", argv0); | 
					
						
							| 
									
										
										
										
											2013-11-15 17:25:10 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-01-25 22:07:13 +00:00
										 |  |  | static void | 
					
						
							| 
									
										
										
										
											2013-11-15 17:25:10 +01: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 20:50:51 +02: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 17:25:10 +01:00
										 |  |  | parsemapping(const char *set1, const char *set2, wchar_t *mappings) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2014-04-09 14:03:02 +02:00
										 |  |  | 	char *s1, *s2; | 
					
						
							| 
									
										
										
										
											2013-11-15 17:25:10 +01:00
										 |  |  | 	wchar_t runeleft; | 
					
						
							|  |  |  | 	wchar_t runeright; | 
					
						
							|  |  |  | 	int leftbytes; | 
					
						
							|  |  |  | 	int rightbytes; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-04-09 14:03:02 +02:00
										 |  |  | 	s1 = (char *)set1; | 
					
						
							|  |  |  | 	if(set2) | 
					
						
							|  |  |  | 		s2 = (char *)set2; | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		s2 = (char *)set1; | 
					
						
							| 
									
										
										
										
											2013-11-15 17:25:10 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-04-09 14:03:02 +02:00
										 |  |  | 	while(*s1) { | 
					
						
							|  |  |  | 		if(*s1 == '\\') | 
					
						
							|  |  |  | 			handleescapes(++s1); | 
					
						
							| 
									
										
										
										
											2014-04-12 20:50:51 +02:00
										 |  |  | 		leftbytes = xmbtowc(&runeleft, s1); | 
					
						
							| 
									
										
										
										
											2014-04-09 14:03:02 +02:00
										 |  |  | 		s1 += leftbytes; | 
					
						
							|  |  |  | 		if(*s2 == '\\') | 
					
						
							|  |  |  | 			handleescapes(++s2); | 
					
						
							|  |  |  | 		if(*s2 != '\0') { | 
					
						
							| 
									
										
										
										
											2014-04-12 20:50:51 +02:00
										 |  |  | 			rightbytes = xmbtowc(&runeright, s2); | 
					
						
							| 
									
										
										
										
											2014-04-09 14:03:02 +02:00
										 |  |  | 			s2 += rightbytes; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2013-11-15 17:25:10 +01:00
										 |  |  | 		mappings[runeleft] = runeright; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-01-25 22:07:13 +00:00
										 |  |  | static void | 
					
						
							| 
									
										
										
										
											2013-11-15 17:25:10 +01:00
										 |  |  | maptonull(const wchar_t *mappings, char *in) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	const char *s; | 
					
						
							|  |  |  | 	wchar_t runeleft; | 
					
						
							|  |  |  | 	int leftbytes = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	s = in; | 
					
						
							|  |  |  | 	while(*s) { | 
					
						
							| 
									
										
										
										
											2014-04-12 20:50:51 +02:00
										 |  |  | 		leftbytes = xmbtowc(&runeleft, s); | 
					
						
							| 
									
										
										
										
											2013-11-15 17:25:10 +01:00
										 |  |  | 		if(!mappings[runeleft]) | 
					
						
							|  |  |  | 			putwchar(runeleft); | 
					
						
							|  |  |  | 		s += leftbytes; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-01-25 22:07:13 +00:00
										 |  |  | static void | 
					
						
							| 
									
										
										
										
											2013-11-15 17:25:10 +01:00
										 |  |  | maptoset(const wchar_t *mappings, char *in) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	const char *s; | 
					
						
							|  |  |  | 	wchar_t runeleft; | 
					
						
							|  |  |  | 	int leftbytes = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	s = in; | 
					
						
							|  |  |  | 	while(*s) { | 
					
						
							| 
									
										
										
										
											2014-04-12 20:50:51 +02:00
										 |  |  | 		leftbytes = xmbtowc(&runeleft, s); | 
					
						
							| 
									
										
										
										
											2013-11-15 17:25:10 +01: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*); | 
					
						
							| 
									
										
										
										
											2014-04-09 14:12:34 +02:00
										 |  |  | 	int dflag = 0; | 
					
						
							| 
									
										
										
										
											2013-11-15 17:25:10 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	setlocale(LC_ALL, ""); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-04-12 20:32:39 +01:00
										 |  |  | 	mappings = mmap(NULL, 0x110000 * sizeof(wchar_t), | 
					
						
							|  |  |  | 			PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0); | 
					
						
							| 
									
										
										
										
											2014-01-20 11:25:57 +00:00
										 |  |  | 	if (mappings == MAP_FAILED) | 
					
						
							|  |  |  | 		eprintf("mmap:"); | 
					
						
							| 
									
										
										
										
											2013-11-15 17:25:10 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	ARGBEGIN { | 
					
						
							| 
									
										
										
										
											2014-04-09 14:12:34 +02:00
										 |  |  | 	case 'd': | 
					
						
							|  |  |  | 		dflag = 1; | 
					
						
							|  |  |  | 		break; | 
					
						
							| 
									
										
										
										
											2013-11-15 17:25:10 +01:00
										 |  |  | 	default: | 
					
						
							|  |  |  | 		usage(); | 
					
						
							|  |  |  | 	} ARGEND; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(argc == 0) | 
					
						
							|  |  |  | 		usage(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-04-12 12:56:56 +02:00
										 |  |  | 	if(dflag || argc == 1) { | 
					
						
							|  |  |  | 		if(argc != 1) | 
					
						
							| 
									
										
										
										
											2014-04-09 14:12:34 +02:00
										 |  |  | 			usage(); | 
					
						
							| 
									
										
										
										
											2013-11-15 17:25:10 +01:00
										 |  |  | 		parsemapping(argv[0], NULL, mappings); | 
					
						
							|  |  |  | 		mapfunc = maptonull; | 
					
						
							| 
									
										
										
										
											2014-04-09 14:12:34 +02:00
										 |  |  | 	} else { | 
					
						
							|  |  |  | 		if(argc != 2) | 
					
						
							|  |  |  | 			usage(); | 
					
						
							|  |  |  | 		parsemapping(argv[0], argv[1], mappings); | 
					
						
							|  |  |  | 		mapfunc = maptoset; | 
					
						
							| 
									
										
										
										
											2013-11-15 17:25:10 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-01 15:04:32 +02:00
										 |  |  | 	while(agetline(&buf, &size, stdin) != -1) | 
					
						
							| 
									
										
										
										
											2013-11-15 17:25:10 +01:00
										 |  |  | 		mapfunc(mappings, buf); | 
					
						
							|  |  |  | 	free(buf); | 
					
						
							|  |  |  | 	if(ferror(stdin)) | 
					
						
							|  |  |  | 		eprintf("<stdin>: read error:"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-01-20 11:25:57 +00:00
										 |  |  | 	munmap(mappings, 0x110000 * sizeof(wchar_t)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-15 17:25:10 +01:00
										 |  |  | 	return EXIT_SUCCESS; | 
					
						
							|  |  |  | } |