1 /* shmbutil.h -- utility functions for multibyte characters. */
3 /* Copyright (C) 2002 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 it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 2, or (at your option) any later
12 Bash is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 You should have received a copy of the GNU General Public License along
18 with Bash; see the file COPYING. If not, write to the Free Software
19 Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
21 #if !defined (_SH_MBUTIL_H_)
26 /************************************************/
27 /* check multibyte capability for I18N code */
28 /************************************************/
30 /* For platforms which support the ISO C amendement 1 functionality we
31 support user defined character classes. */
32 /* Solaris 2.5 has a bug: <wchar.h> must be included before <wctype.h>. */
33 #if defined (HAVE_WCTYPE_H) && defined (HAVE_WCHAR_H)
36 # if defined (HAVE_MBSRTOWCS) /* system is supposed to support XPG5 */
37 # define HANDLE_MULTIBYTE 1
39 #endif /* HAVE_WCTYPE_H && HAVE_WCHAR_H */
41 /* Some systems, like BeOS, have multibyte encodings but lack mbstate_t. */
42 #if HANDLE_MULTIBYTE && !defined (HAVE_MBSTATE_T)
43 # define wcsrtombs(dest, src, len, ps) (wcsrtombs) (dest, src, len, 0)
44 # define mbsrtowcs(dest, src, len, ps) (mbsrtowcs) (dest, src, len, 0)
45 # define wcrtomb(s, wc, ps) (wcrtomb) (s, wc, 0)
46 # define mbrtowc(pwc, s, n, ps) (mbrtowc) (pwc, s, n, 0)
47 # define mbrlen(s, n, ps) (mbrlen) (s, n, 0)
48 # define mbstate_t int
49 #endif /* HANDLE_MULTIBYTE && !HAVE_MBSTATE_T */
51 /* Make sure MB_LEN_MAX is at least 16 on systems that claim to be able to
52 handle multibyte chars (some systems define MB_LEN_MAX as 1) */
53 #ifdef HANDLE_MULTIBYTE
55 # if defined(MB_LEN_MAX) && (MB_LEN_MAX < 16)
58 # if !defined (MB_LEN_MAX)
59 # define MB_LEN_MAX 16
61 #endif /* HANDLE_MULTIBYTE */
63 /************************************************/
64 /* end of multibyte capability checks for I18N */
65 /************************************************/
67 #if defined (HANDLE_MULTIBYTE)
69 extern size_t xmbsrtowcs __P((wchar_t *, const char **, size_t, mbstate_t *));
71 extern char *xstrchr __P((const char *, int));
73 #else /* !HANDLE_MULTIBYTE */
82 #define xstrchr(s, c) strchr(s, c)
84 #endif /* !HANDLE_MULTIBYTE */
86 /* Declare and initialize a multibyte state. Call must be terminated
88 #if defined (HANDLE_MULTIBYTE)
89 # define DECLARE_MBSTATE \
91 memset (&state, '\0', sizeof (mbstate_t))
93 # define DECLARE_MBSTATE
94 #endif /* !HANDLE_MULTIBYTE */
96 /* Initialize or reinitialize a multibyte state named `state'. Call must be
97 terminated with `;'. */
98 #if defined (HANDLE_MULTIBYTE)
99 # define INITIALIZE_MBSTATE memset (&state, '\0', sizeof (mbstate_t))
101 # define INITIALIZE_MBSTATE
102 #endif /* !HANDLE_MULTIBYTE */
104 /* Advance one (possibly multi-byte) character in string _STR of length
105 _STRSIZE, starting at index _I. STATE must have already been declared. */
106 #if defined (HANDLE_MULTIBYTE)
107 # define ADVANCE_CHAR(_str, _strsize, _i) \
110 if (MB_CUR_MAX > 1) \
112 mbstate_t state_bak; \
116 mblength = mbrlen ((_str) + (_i), (_strsize) - (_i), &state); \
118 if (mblength == (size_t)-2 || mblength == (size_t)-1) \
131 # define ADVANCE_CHAR(_str, _strsize, _i) (_i)++
132 #endif /* !HANDLE_MULTIBYTE */
134 /* Advance one (possibly multibyte) character in the string _STR of length
136 SPECIAL: assume that _STR will be incremented by 1 after this call. */
137 #if defined (HANDLE_MULTIBYTE)
138 # define ADVANCE_CHAR_P(_str, _strsize) \
141 if (MB_CUR_MAX > 1) \
143 mbstate_t state_bak; \
147 mblength = mbrlen ((_str), (_strsize), &state); \
149 if (mblength == (size_t)-2 || mblength == (size_t)-1) \
155 (_str) += (mblength < 1) ? 0 : (mblength - 1); \
160 # define ADVANCE_CHAR_P(_str, _strsize)
161 #endif /* !HANDLE_MULTIBYTE */
163 /* Copy a single character from the string _SRC to the string _DST.
164 _SRCEND is a pointer to the end of _SRC. */
165 #if defined (HANDLE_MULTIBYTE)
166 # define COPY_CHAR_P(_dst, _src, _srcend) \
169 if (MB_CUR_MAX > 1) \
171 mbstate_t state_bak; \
176 mblength = mbrlen ((_src), (_srcend) - (_src), &state); \
177 if (mblength == (size_t)-2 || mblength == (size_t)-1) \
183 mblength = (mblength < 1) ? 1 : mblength; \
185 for (_k = 0; _k < mblength; _k++) \
186 *(_dst)++ = *(_src)++; \
189 *(_dst)++ = *(_src)++; \
193 # define COPY_CHAR_P(_dst, _src, _srcend) *(_dst)++ = *(_src)++
194 #endif /* !HANDLE_MULTIBYTE */
196 /* Copy a single character from the string _SRC at index _SI to the string
197 _DST at index _DI. _SRCEND is a pointer to the end of _SRC. */
198 #if defined (HANDLE_MULTIBYTE)
199 # define COPY_CHAR_I(_dst, _di, _src, _srcend, _si) \
202 if (MB_CUR_MAX > 1) \
204 mbstate_t state_bak; \
209 mblength = mbrlen ((_src) + (_si), (_srcend) - ((_src)+(_si)), &state); \
210 if (mblength == (size_t)-2 || mblength == (size_t)-1) \
216 mblength = (mblength < 1) ? 1 : mblength; \
218 for (_k = 0; _k < mblength; _k++) \
219 _dst[_di++] = _src[_si++]; \
222 _dst[_di++] = _src[_si++]; \
226 # define COPY_CHAR_I(_dst, _di, _src, _srcend, _si) _dst[_di++] = _src[_si++]
227 #endif /* !HANDLE_MULTIBYTE */
229 /****************************************************************
231 * The following are only guaranteed to work in subst.c *
233 ****************************************************************/
235 #if defined (HANDLE_MULTIBYTE)
236 # define SCOPY_CHAR_I(_dst, _escchar, _sc, _src, _si, _slen) \
239 if (MB_CUR_MAX > 1) \
241 mbstate_t state_bak; \
246 mblength = mbrlen ((_src) + (_si), (_slen) - (_si), &state); \
247 if (mblength == (size_t)-2 || mblength == (size_t)-1) \
253 mblength = (mblength < 1) ? 1 : mblength; \
255 temp = xmalloc (mblength + 2); \
256 temp[0] = _escchar; \
257 for (_i = 0; _i < mblength; _i++) \
258 temp[_i + 1] = _src[_si++]; \
259 temp[mblength + 1] = '\0'; \
265 _dst[0] = _escchar; \
271 # define SCOPY_CHAR_I(_dst, _escchar, _sc, _src, _si, _slen) \
272 _dst[0] = _escchar; \
274 #endif /* !HANDLE_MULTIBYTE */
276 #if defined (HANDLE_MULTIBYTE)
277 # define SCOPY_CHAR_M(_dst, _src, _srcend, _si) \
280 if (MB_CUR_MAX > 1) \
282 mbstate_t state_bak; \
286 mblength = mbrlen ((_src) + (_si), (_srcend) - ((_src) + (_si)), &state); \
287 if (mblength == (size_t)-2 || mblength == (size_t)-1) \
293 mblength = (mblength < 1) ? 1 : mblength; \
295 FASTCOPY(((_src) + (_si)), (_dst), mblength); \
297 (_dst) += mblength; \
302 *(_dst)++ = _src[(_si)]; \
308 # define SCOPY_CHAR_M(_dst, _src, _srcend, _si) \
309 *(_dst)++ = _src[(_si)]; \
311 #endif /* !HANDLE_MULTIBYTE */
314 # define SADD_MBCHAR(_dst, _src, _si, _srcsize) \
317 if (MB_CUR_MAX > 1) \
320 mbstate_t state_bak; \
324 mblength = mbrlen ((_src) + (_si), (_srcsize) - (_si), &state); \
325 if (mblength == (size_t)-1 || mblength == (size_t)-2) \
333 _dst = (char *)xmalloc (mblength + 1); \
334 for (i = 0; i < mblength; i++) \
335 (_dst)[i] = (_src)[(_si)++]; \
336 (_dst)[mblength] = '\0'; \
344 # define SADD_MBCHAR(_dst, _src, _si, _srcsize)
347 #endif /* _SH_MBUTIL_H_ */