xref: /Universal-ctags/main/mbcs.c (revision f38d6693208ea5a7f60d44f253d90567ab505254)
12acdcfa1SYasuhiro Matsumoto /*
22acdcfa1SYasuhiro Matsumoto *   $Id$
32acdcfa1SYasuhiro Matsumoto *
42acdcfa1SYasuhiro Matsumoto *   Copyright (c) 2015, vim-jp
52acdcfa1SYasuhiro Matsumoto *
62acdcfa1SYasuhiro Matsumoto *   This source code is released for free distribution under the terms of the
70ce38835Sviccuad *   GNU General Public License version 2 or (at your option) any later version.
82acdcfa1SYasuhiro Matsumoto *
92acdcfa1SYasuhiro Matsumoto *   This module contains functions for checking multibyte character set.
102acdcfa1SYasuhiro Matsumoto */
112acdcfa1SYasuhiro Matsumoto 
122acdcfa1SYasuhiro Matsumoto /*
132acdcfa1SYasuhiro Matsumoto *   INCLUDE FILES
142acdcfa1SYasuhiro Matsumoto */
15119fb560SK.Takata #ifndef __USE_GNU
162acdcfa1SYasuhiro Matsumoto # define __USE_GNU
17119fb560SK.Takata #endif
182acdcfa1SYasuhiro Matsumoto #include "general.h"  /* must always come first */
192acdcfa1SYasuhiro Matsumoto 
202acdcfa1SYasuhiro Matsumoto #ifdef HAVE_ICONV
212acdcfa1SYasuhiro Matsumoto 
222acdcfa1SYasuhiro Matsumoto #include <stdio.h>
232acdcfa1SYasuhiro Matsumoto #include <string.h>
242acdcfa1SYasuhiro Matsumoto #include <iconv.h>
252acdcfa1SYasuhiro Matsumoto #include <errno.h>
262acdcfa1SYasuhiro Matsumoto #include "options.h"
272acdcfa1SYasuhiro Matsumoto #include "mbcs.h"
28*f38d6693SMasatake YAMATO #include "mbcs_p.h"
292acdcfa1SYasuhiro Matsumoto #include "routines.h"
302acdcfa1SYasuhiro Matsumoto 
312acdcfa1SYasuhiro Matsumoto static iconv_t iconv_fd = (iconv_t) -1;
322acdcfa1SYasuhiro Matsumoto 
openConverter(const char * inputEncoding,const char * outputEncoding)33bde9f60aSColomban Wendling extern bool openConverter (const char* inputEncoding, const char* outputEncoding)
342acdcfa1SYasuhiro Matsumoto {
352acdcfa1SYasuhiro Matsumoto 	if (!inputEncoding || !outputEncoding)
362acdcfa1SYasuhiro Matsumoto 	{
37ce990805SThomas Braun 		static bool warn = false;
382acdcfa1SYasuhiro Matsumoto 		/* --output-encoding is specified but not --input-encoding provided */
392acdcfa1SYasuhiro Matsumoto 		if (!warn && outputEncoding)
402acdcfa1SYasuhiro Matsumoto 		{
412acdcfa1SYasuhiro Matsumoto 			error (WARNING, "--input-encoding is not specified");
42ce990805SThomas Braun 			warn = true;
432acdcfa1SYasuhiro Matsumoto 		}
44ce990805SThomas Braun 		return false;
452acdcfa1SYasuhiro Matsumoto 	}
462acdcfa1SYasuhiro Matsumoto 	iconv_fd = iconv_open(outputEncoding, inputEncoding);
472acdcfa1SYasuhiro Matsumoto 	if (iconv_fd == (iconv_t) -1)
482acdcfa1SYasuhiro Matsumoto 	{
492acdcfa1SYasuhiro Matsumoto 		error (FATAL,
501ac6fd0fSK.Takata 					"failed opening encoding from '%s' to '%s'", inputEncoding, outputEncoding);
51ce990805SThomas Braun 		return false;
522acdcfa1SYasuhiro Matsumoto 	}
53ce990805SThomas Braun 	return true;
542acdcfa1SYasuhiro Matsumoto }
552acdcfa1SYasuhiro Matsumoto 
isConverting()56ce990805SThomas Braun extern bool isConverting ()
572acdcfa1SYasuhiro Matsumoto {
582acdcfa1SYasuhiro Matsumoto 	return iconv_fd != (iconv_t) -1;
592acdcfa1SYasuhiro Matsumoto }
602acdcfa1SYasuhiro Matsumoto 
convertString(vString * const string)61ce990805SThomas Braun extern bool convertString (vString *const string)
622acdcfa1SYasuhiro Matsumoto {
632acdcfa1SYasuhiro Matsumoto 	size_t dest_len, src_len;
642acdcfa1SYasuhiro Matsumoto 	char *dest, *dest_ptr, *src;
652acdcfa1SYasuhiro Matsumoto 	if (iconv_fd == (iconv_t) -1)
66ce990805SThomas Braun 		return false;
672acdcfa1SYasuhiro Matsumoto 	src_len = vStringLength (string);
682acdcfa1SYasuhiro Matsumoto 	/* Should be longest length of bytes. so maybe utf8. */
692acdcfa1SYasuhiro Matsumoto 	dest_len = src_len * 4;
702acdcfa1SYasuhiro Matsumoto 	dest_ptr = dest = xCalloc (dest_len, char);
712acdcfa1SYasuhiro Matsumoto 	if (!dest)
72ce990805SThomas Braun 		return false;
732acdcfa1SYasuhiro Matsumoto 	src = vStringValue (string);
742acdcfa1SYasuhiro Matsumoto retry:
752acdcfa1SYasuhiro Matsumoto 	if (iconv (iconv_fd, &src, &src_len, &dest_ptr, &dest_len) == (size_t) -1)
762acdcfa1SYasuhiro Matsumoto 	{
772acdcfa1SYasuhiro Matsumoto 		if (errno == EILSEQ)
782acdcfa1SYasuhiro Matsumoto 		{
792acdcfa1SYasuhiro Matsumoto 			*dest_ptr++ = '?';
802acdcfa1SYasuhiro Matsumoto 			dest_len--;
812acdcfa1SYasuhiro Matsumoto 			src++;
822acdcfa1SYasuhiro Matsumoto 			src_len--;
832acdcfa1SYasuhiro Matsumoto 			verbose ("  Encoding: %s\n", strerror(errno));
842acdcfa1SYasuhiro Matsumoto 			goto retry;
852acdcfa1SYasuhiro Matsumoto 		}
862acdcfa1SYasuhiro Matsumoto 		eFree (dest);
87ce990805SThomas Braun 		return false;
882acdcfa1SYasuhiro Matsumoto 	}
892acdcfa1SYasuhiro Matsumoto 
902acdcfa1SYasuhiro Matsumoto 	dest_len = dest_ptr - dest;
912acdcfa1SYasuhiro Matsumoto 
922acdcfa1SYasuhiro Matsumoto 	vStringClear (string);
938a3d0750SJiří Techet 	if (vStringSize (string) < dest_len + 1)
948a3d0750SJiří Techet 		vStringResize (string, dest_len + 1);
952acdcfa1SYasuhiro Matsumoto 	memcpy (vStringValue (string), dest, dest_len + 1);
962acdcfa1SYasuhiro Matsumoto 	vStringLength (string) = dest_len;
972acdcfa1SYasuhiro Matsumoto 	eFree (dest);
982acdcfa1SYasuhiro Matsumoto 
992acdcfa1SYasuhiro Matsumoto 	iconv (iconv_fd, NULL, NULL, NULL, NULL);
1002acdcfa1SYasuhiro Matsumoto 
101ce990805SThomas Braun 	return true;
1022acdcfa1SYasuhiro Matsumoto }
1032acdcfa1SYasuhiro Matsumoto 
closeConverter()1042acdcfa1SYasuhiro Matsumoto extern void closeConverter ()
1052acdcfa1SYasuhiro Matsumoto {
1062acdcfa1SYasuhiro Matsumoto 	if (iconv_fd != (iconv_t) -1)
1072acdcfa1SYasuhiro Matsumoto 	{
1082acdcfa1SYasuhiro Matsumoto 		iconv_close(iconv_fd);
1092acdcfa1SYasuhiro Matsumoto 		iconv_fd = (iconv_t) -1;
1102acdcfa1SYasuhiro Matsumoto 	}
1112acdcfa1SYasuhiro Matsumoto }
1122acdcfa1SYasuhiro Matsumoto 
1132acdcfa1SYasuhiro Matsumoto #endif	/* HAVE_ICONV */
114