[git commit master 1/1] lineedit: fixes for CONFIG_UNICODE_USING_LOCALE=y

Denys Vlasenko vda.linux at googlemail.com
Sun Mar 27 00:18:07 UTC 2011


commit: http://git.busybox.net/busybox/commit/?id=353680aa46dc91ecfd80dd19db131de7aa90bd22
branch: http://git.busybox.net/busybox/commit/?id=refs/heads/master

function                                             old     new   delta
load_string                                           45      91     +46
save_string                                           40      82     +42
reinit_unicode                                        34      61     +27
BB_PUTCHAR                                            97     120     +23
init_unicode                                          17      37     +20
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 5/0 up/down: 158/0)             Total: 158 bytes

Signed-off-by: Denys Vlasenko <vda.linux at googlemail.com>
---
 libbb/lineedit.c |  107 +++++++++++++++++++++++++++++++-----------------------
 libbb/unicode.c  |    7 ++--
 2 files changed, 66 insertions(+), 48 deletions(-)

diff --git a/libbb/lineedit.c b/libbb/lineedit.c
index afd28b7..b7a2b31 100644
--- a/libbb/lineedit.c
+++ b/libbb/lineedit.c
@@ -204,65 +204,82 @@ static void deinit_S(void)
 #if ENABLE_UNICODE_SUPPORT
 static size_t load_string(const char *src, int maxsize)
 {
-	ssize_t len = mbstowcs(command_ps, src, maxsize - 1);
-	if (len < 0)
-		len = 0;
-	command_ps[len] = BB_NUL;
-	return len;
+	if (unicode_status == UNICODE_ON) {
+		ssize_t len = mbstowcs(command_ps, src, maxsize - 1);
+		if (len < 0)
+			len = 0;
+		command_ps[len] = BB_NUL;
+		return len;
+	} else {
+		unsigned i = 0;
+		while ((command_ps[i] = src[i]) != 0)
+			i++;
+		return i;
+	}
 }
 static unsigned save_string(char *dst, unsigned maxsize)
 {
+	if (unicode_status == UNICODE_ON) {
 # if !ENABLE_UNICODE_PRESERVE_BROKEN
-	ssize_t len = wcstombs(dst, command_ps, maxsize - 1);
-	if (len < 0)
-		len = 0;
-	dst[len] = '\0';
-	return len;
+		ssize_t len = wcstombs(dst, command_ps, maxsize - 1);
+		if (len < 0)
+			len = 0;
+		dst[len] = '\0';
+		return len;
 # else
-	unsigned dstpos = 0;
-	unsigned srcpos = 0;
+		unsigned dstpos = 0;
+		unsigned srcpos = 0;
 
-	maxsize--;
-	while (dstpos < maxsize) {
-		wchar_t wc;
-		int n = srcpos;
+		maxsize--;
+		while (dstpos < maxsize) {
+			wchar_t wc;
+			int n = srcpos;
 
-		/* Convert up to 1st invalid byte (or up to end) */
-		while ((wc = command_ps[srcpos]) != BB_NUL
-		    && !unicode_is_raw_byte(wc)
-		) {
+			/* Convert up to 1st invalid byte (or up to end) */
+			while ((wc = command_ps[srcpos]) != BB_NUL
+			    && !unicode_is_raw_byte(wc)
+			) {
+				srcpos++;
+			}
+			command_ps[srcpos] = BB_NUL;
+			n = wcstombs(dst + dstpos, command_ps + n, maxsize - dstpos);
+			if (n < 0) /* should not happen */
+				break;
+			dstpos += n;
+			if (wc == BB_NUL) /* usually is */
+				break;
+
+			/* We do have invalid byte here! */
+			command_ps[srcpos] = wc; /* restore it */
 			srcpos++;
+			if (dstpos == maxsize)
+				break;
+			dst[dstpos++] = (char) wc;
 		}
-		command_ps[srcpos] = BB_NUL;
-		n = wcstombs(dst + dstpos, command_ps + n, maxsize - dstpos);
-		if (n < 0) /* should not happen */
-			break;
-		dstpos += n;
-		if (wc == BB_NUL) /* usually is */
-			break;
-
-		/* We do have invalid byte here! */
-		command_ps[srcpos] = wc; /* restore it */
-		srcpos++;
-		if (dstpos == maxsize)
-			break;
-		dst[dstpos++] = (char) wc;
-	}
-	dst[dstpos] = '\0';
-	return dstpos;
+		dst[dstpos] = '\0';
+		return dstpos;
 # endif
+	} else {
+		unsigned i = 0;
+		while ((dst[i] = command_ps[i]) != 0)
+			i++;
+		return i;
+	}
 }
 /* I thought just fputwc(c, stdout) would work. But no... */
 static void BB_PUTCHAR(wchar_t c)
 {
-	char buf[MB_CUR_MAX + 1];
-	mbstate_t mbst = { 0 };
-	ssize_t len;
-
-	len = wcrtomb(buf, c, &mbst);
-	if (len > 0) {
-		buf[len] = '\0';
-		fputs(buf, stdout);
+	if (unicode_status == UNICODE_ON) {
+		char buf[MB_CUR_MAX + 1];
+		mbstate_t mbst = { 0 };
+		ssize_t len = wcrtomb(buf, c, &mbst);
+		if (len > 0) {
+			buf[len] = '\0';
+			fputs(buf, stdout);
+		}
+	} else {
+		/* In this case, c is always one byte */
+		putchar(c);
 	}
 }
 # if ENABLE_UNICODE_COMBINING_WCHARS || ENABLE_UNICODE_WIDE_WCHARS
diff --git a/libbb/unicode.c b/libbb/unicode.c
index d01efd9..99dc1df 100644
--- a/libbb/unicode.c
+++ b/libbb/unicode.c
@@ -23,12 +23,13 @@ uint8_t unicode_status;
 
 /* Unicode support using libc locale support. */
 
-void FAST_FUNC reinit_unicode(const char *LANG UNUSED_PARAM)
+void FAST_FUNC reinit_unicode(const char *LANG)
 {
 	static const char unicode_0x394[] = { 0xce, 0x94, 0 };
 	size_t width;
 
-//TODO: call setlocale(LC_ALL, LANG) here?
+//TODO: avoid repeated calls by caching last string?
+	setlocale(LC_ALL, (LANG && LANG[0]) ? LANG : "C");
 
 	/* In unicode, this is a one character string */
 // can use unicode_strlen(string) too, but otherwise unicode_strlen() is unused
@@ -39,7 +40,7 @@ void FAST_FUNC reinit_unicode(const char *LANG UNUSED_PARAM)
 void FAST_FUNC init_unicode(void)
 {
 	if (unicode_status == UNICODE_UNKNOWN)
-		reinit_unicode(NULL /*getenv("LANG")*/);
+		reinit_unicode(getenv("LANG"));
 }
 
 #else
-- 
1.7.3.4



More information about the busybox-cvs mailing list