diff -Naur bash-4.1/lib/glob/xmbsrtowcs.c bash-4.1-fasterWideCharConversion/lib/glob/xmbsrtowcs.c
--- bash-4.1/lib/glob/xmbsrtowcs.c 2008-08-12 16:17:54.000000000 +0200
+++ bash-4.1-fasterWideCharConversion/lib/glob/xmbsrtowcs.c 2010-03-03 16:40:58.664811945 +0100
@@ -18,6 +18,14 @@
along with Bash. If not, see .
*/
+/* Tell glibc's and to provide
+ prototypes for strchrnul() and mbsnrtowcs().
+ This must come before because may include
+ , and once has been included, it's too late. */
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE 1
+#endif
+
#include
#include
@@ -131,6 +139,91 @@
If conversion is failed, the return value is (size_t)-1 and the values
of DESTP and INDICESP are NULL. */
+#ifndef _GNU_SOURCE
+# error "Optimized conversion to wide-character strings requires _GNU_SOURCE"
+#endif
+
+static size_t
+xdupmbstowcs__no_indices (destp, src)
+ wchar_t **destp; /* Store the pointer to the wide character string */
+ const char *src; /* Multibyte character string */
+{
+ const char *p; /* Conversion start position of src */
+ wchar_t *wsbuf; /* Buffer for wide characters. */
+ size_t wsbuf_size; /* Size of WSBUF */
+ size_t wcnum; /* Number of wide characters in WSBUF */
+ mbstate_t state; /* Conversion State */
+
+ memset (&state, '\0', sizeof(mbstate_t));
+
+ wsbuf_size = 0;
+ wsbuf = NULL;
+
+ p = src;
+ wcnum = 0;
+ do
+ {
+ size_t wcslength; /* Number of wide characters produced by the conversion. */
+ const char *end_or_backslash;
+ size_t nms; /* Number of multibyte characters to convert at one time. */
+ mbstate_t tmp_state;
+ const char *tmp_p;
+
+ end_or_backslash = strchrnul(p, '\\');
+ nms = (end_or_backslash - p);
+ if(*end_or_backslash == '\0')
+ nms++;
+
+ /* Compute the number of produced wide-characters. */
+ tmp_p = p;
+ tmp_state = state;
+ wcslength = mbsnrtowcs(NULL, &tmp_p, nms, 0, &tmp_state);
+
+ /* Conversion failed. */
+ if (wcslength == (size_t)-1)
+ {
+ free (wsbuf);
+ *destp = NULL;
+ return (size_t)-1;
+ }
+
+ /* Resize the buffer if it is not large enough. */
+ if (wsbuf_size < wcnum+wcslength+1) /* 1 for the L'\0' or the potential L'\\' */
+ {
+ wchar_t *wstmp;
+
+ wsbuf_size = wcnum+wcslength+1; /* 1 for the L'\0' or the potential L'\\' */
+
+ wstmp = (wchar_t *) realloc (wsbuf, wsbuf_size * sizeof (wchar_t));
+ if (wstmp == NULL)
+ {
+ free (wsbuf);
+ *destp = NULL;
+ return (size_t)-1;
+ }
+ wsbuf = wstmp;
+ }
+
+ /* Perform the conversion. This is assumed to return 'wcslength'.
+ * It may set 'p' to NULL. */
+ mbsnrtowcs(wsbuf+wcnum, &p, nms, wsbuf_size-wcnum, &state);
+
+ wcnum += wcslength;
+
+ if (mbsinit (&state) && (p != NULL) && (*p == '\\'))
+ {
+ wsbuf[wcnum++] = L'\\';
+ p++;
+ }
+ }
+ while (p != NULL);
+
+ *destp = wsbuf;
+
+ /* Return the length of the wide character string, not including `\0'. */
+ return wcnum;
+}
+
#define WSBUF_INC 32
size_t
@@ -155,6 +248,10 @@
return (size_t)-1;
}
+ /* Use faster version if 'indicesp' is NULL. */
+ if (indicesp == NULL)
+ return xdupmbstowcs__no_indices(destp, src);
+
memset (&state, '\0', sizeof(mbstate_t));
wsbuf_size = WSBUF_INC;