1 /* xmbsrtowcs.c -- replacement function for mbsrtowcs */
3 /* Copyright (C) 2002-2004 Free Software Foundation, Inc.
5 This file is part of GNU Bash, the Bourne Again SHell.
7 Bash is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
12 Bash is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with Bash. If not, see <http://www.gnu.org/licenses/>.
25 /* <wchar.h>, <wctype.h> and <stdlib.h> are included in "shmbutil.h".
26 If <wchar.h>, <wctype.h>, mbsrtowcs(), exist, HANDLE_MULTIBYTE
33 # define FREE(x) do { if (x) free (x); } while (0)
35 /* On some locales (ex. ja_JP.sjis), mbsrtowc doesn't convert 0x5c to U<0x5c>.
36 So, this function is made for converting 0x5c to U<0x5c>. */
38 static mbstate_t local_state
;
39 static int local_state_use
= 0;
42 xmbsrtowcs (dest
, src
, len
, pstate
)
49 size_t mblength
, wclength
, n
;
56 memset (&local_state
, '\0', sizeof(mbstate_t));
70 /* It doesn't matter if malloc fails here, since mbsrtowcs should do
71 the right thing with a NULL first argument. */
72 wsbuf
= (wchar_t *) malloc ((n
+ 1) * sizeof(wchar_t));
76 wclength
= mbsrtowcs (wsbuf
, &mbs
, n
, &psbuf
);
83 for (wclength
= 0; wclength
< len
; wclength
++, dest
++)
93 else if (**src
== '\\')
99 mblength
= mbrtowc(dest
, *src
, n
, ps
);
102 mblength
= mbrtowc(dest
, *src
, n
, ps
);
104 /* Cannot convert multibyte character to wide character. */
105 if (mblength
== (size_t)-1 || mblength
== (size_t)-2)
111 /* The multibyte string has been completely converted,
112 including the terminating '\0'. */
123 /* Convert a multibyte string to a wide character string. Memory for the
124 new wide character string is obtained with malloc.
126 The return value is the length of the wide character string. Returns a
127 pointer to the wide character string in DESTP. If INDICESP is not NULL,
128 INDICESP stores the pointer to the pointer array. Each pointer is to
129 the first byte of each multibyte character. Memory for the pointer array
130 is obtained with malloc, too.
131 If conversion is failed, the return value is (size_t)-1 and the values
132 of DESTP and INDICESP are NULL. */
137 xdupmbstowcs (destp
, indicesp
, src
)
138 wchar_t **destp
; /* Store the pointer to the wide character string */
139 char ***indicesp
; /* Store the pointer to the pointer array. */
140 const char *src
; /* Multibyte character string */
142 const char *p
; /* Conversion start position of src */
143 wchar_t wc
; /* Created wide character by conversion */
144 wchar_t *wsbuf
; /* Buffer for wide characters. */
145 char **indices
; /* Buffer for indices. */
146 size_t wsbuf_size
; /* Size of WSBUF */
147 size_t wcnum
; /* Number of wide characters in WSBUF */
148 mbstate_t state
; /* Conversion State */
150 /* In case SRC or DESP is NULL, conversion doesn't take place. */
151 if (src
== NULL
|| destp
== NULL
)
158 memset (&state
, '\0', sizeof(mbstate_t));
159 wsbuf_size
= WSBUF_INC
;
161 wsbuf
= (wchar_t *) malloc (wsbuf_size
* sizeof(wchar_t));
171 indices
= (char **) malloc (wsbuf_size
* sizeof(char *));
184 size_t mblength
; /* Byte length of one multibyte character. */
186 if (mbsinit (&state
))
199 mblength
= mbrtowc(&wc
, p
, MB_LEN_MAX
, &state
);
202 mblength
= mbrtowc(&wc
, p
, MB_LEN_MAX
, &state
);
204 /* Conversion failed. */
205 if (MB_INVALIDCH (mblength
))
215 /* Resize buffers when they are not large enough. */
216 if (wsbuf_size
< wcnum
)
221 wsbuf_size
+= WSBUF_INC
;
223 wstmp
= (wchar_t *) realloc (wsbuf
, wsbuf_size
* sizeof (wchar_t));
235 idxtmp
= (char **) realloc (indices
, wsbuf_size
* sizeof (char **));
247 wsbuf
[wcnum
- 1] = wc
;
249 indices
[wcnum
- 1] = (char *)p
;
252 while (MB_NULLWCH (wc
) == 0);
254 /* Return the length of the wide character string, not including `\0'. */
256 if (indicesp
!= NULL
)
262 #endif /* HANDLE_MULTIBYTE */