1 /* shmbutil.h -- utility functions for multibyte characters. */
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 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 /* Include config.h for HANDLE_MULTIBYTE */
29 #if defined (HANDLE_MULTIBYTE)
31 extern size_t xmbsrtowcs __P((wchar_t *, const char **, size_t, mbstate_t *));
32 extern size_t xdupmbstowcs __P((wchar_t **, char ***, const char *));
34 extern char *xstrchr __P((const char *, int));
37 #define MB_INVALIDCH(x) ((x) == (size_t)-1 || (x) == (size_t)-2)
38 #define MB_NULLWCH(x) ((x) == 0)
41 #else /* !HANDLE_MULTIBYTE */
50 #define xstrchr(s, c) strchr(s, c)
53 #define MB_INVALIDCH(x) (0)
54 #define MB_NULLWCH(x) (0)
57 #endif /* !HANDLE_MULTIBYTE */
59 /* Declare and initialize a multibyte state. Call must be terminated
61 #if defined (HANDLE_MULTIBYTE)
62 # define DECLARE_MBSTATE \
64 memset (&state, '\0', sizeof (mbstate_t))
66 # define DECLARE_MBSTATE
67 #endif /* !HANDLE_MULTIBYTE */
69 /* Initialize or reinitialize a multibyte state named `state'. Call must be
70 terminated with `;'. */
71 #if defined (HANDLE_MULTIBYTE)
72 # define INITIALIZE_MBSTATE memset (&state, '\0', sizeof (mbstate_t))
74 # define INITIALIZE_MBSTATE
75 #endif /* !HANDLE_MULTIBYTE */
77 /* Advance one (possibly multi-byte) character in string _STR of length
78 _STRSIZE, starting at index _I. STATE must have already been declared. */
79 #if defined (HANDLE_MULTIBYTE)
80 # define ADVANCE_CHAR(_str, _strsize, _i) \
85 mbstate_t state_bak; \
89 mblength = mbrlen ((_str) + (_i), (_strsize) - (_i), &state); \
91 if (mblength == (size_t)-2 || mblength == (size_t)-1) \
96 else if (mblength == 0) \
106 # define ADVANCE_CHAR(_str, _strsize, _i) (_i)++
107 #endif /* !HANDLE_MULTIBYTE */
109 /* Advance one (possibly multibyte) character in the string _STR of length
111 SPECIAL: assume that _STR will be incremented by 1 after this call. */
112 #if defined (HANDLE_MULTIBYTE)
113 # define ADVANCE_CHAR_P(_str, _strsize) \
116 if (MB_CUR_MAX > 1) \
118 mbstate_t state_bak; \
122 mblength = mbrlen ((_str), (_strsize), &state); \
124 if (mblength == (size_t)-2 || mblength == (size_t)-1) \
130 (_str) += (mblength < 1) ? 0 : (mblength - 1); \
135 # define ADVANCE_CHAR_P(_str, _strsize)
136 #endif /* !HANDLE_MULTIBYTE */
138 /* Back up one (possibly multi-byte) character in string _STR of length
139 _STRSIZE, starting at index _I. STATE must have already been declared. */
140 #if defined (HANDLE_MULTIBYTE)
141 # define BACKUP_CHAR(_str, _strsize, _i) \
144 if (MB_CUR_MAX > 1) \
146 mbstate_t state_bak; \
148 int _x, _p; /* _x == temp index into string, _p == prev index */ \
154 mblength = mbrlen ((_str) + (_x), (_strsize) - (_x), &state); \
156 if (mblength == (size_t)-2 || mblength == (size_t)-1) \
161 else if (mblength == 0) \
165 _p = _x; /* _p == start of prev mbchar */ \
176 # define BACKUP_CHAR(_str, _strsize, _i) (_i)--
177 #endif /* !HANDLE_MULTIBYTE */
179 /* Back up one (possibly multibyte) character in the string _BASE of length
180 _STRSIZE starting at _STR (_BASE <= _STR <= (_BASE + _STRSIZE) ).
181 SPECIAL: DO NOT assume that _STR will be decremented by 1 after this call. */
182 #if defined (HANDLE_MULTIBYTE)
183 # define BACKUP_CHAR_P(_base, _strsize, _str) \
186 if (MB_CUR_MAX > 1) \
188 mbstate_t state_bak; \
190 char *_x, _p; /* _x == temp pointer into string, _p == prev pointer */ \
193 while (_x < (_str)) \
196 mblength = mbrlen (_x, (_strsize) - _x, &state); \
198 if (mblength == (size_t)-2 || mblength == (size_t)-1) \
203 else if (mblength == 0) \
207 _p = _x; /* _p == start of prev mbchar */ \
218 # define BACKUP_CHAR_P(_base, _strsize, _str) (_str)--
219 #endif /* !HANDLE_MULTIBYTE */
221 /* Copy a single character from the string _SRC to the string _DST.
222 _SRCEND is a pointer to the end of _SRC. */
223 #if defined (HANDLE_MULTIBYTE)
224 # define COPY_CHAR_P(_dst, _src, _srcend) \
227 if (MB_CUR_MAX > 1) \
229 mbstate_t state_bak; \
234 mblength = mbrlen ((_src), (_srcend) - (_src), &state); \
235 if (mblength == (size_t)-2 || mblength == (size_t)-1) \
241 mblength = (mblength < 1) ? 1 : mblength; \
243 for (_k = 0; _k < mblength; _k++) \
244 *(_dst)++ = *(_src)++; \
247 *(_dst)++ = *(_src)++; \
251 # define COPY_CHAR_P(_dst, _src, _srcend) *(_dst)++ = *(_src)++
252 #endif /* !HANDLE_MULTIBYTE */
254 /* Copy a single character from the string _SRC at index _SI to the string
255 _DST at index _DI. _SRCEND is a pointer to the end of _SRC. */
256 #if defined (HANDLE_MULTIBYTE)
257 # define COPY_CHAR_I(_dst, _di, _src, _srcend, _si) \
260 if (MB_CUR_MAX > 1) \
262 mbstate_t state_bak; \
267 mblength = mbrlen ((_src) + (_si), (_srcend) - ((_src)+(_si)), &state); \
268 if (mblength == (size_t)-2 || mblength == (size_t)-1) \
274 mblength = (mblength < 1) ? 1 : mblength; \
276 for (_k = 0; _k < mblength; _k++) \
277 _dst[_di++] = _src[_si++]; \
280 _dst[_di++] = _src[_si++]; \
284 # define COPY_CHAR_I(_dst, _di, _src, _srcend, _si) _dst[_di++] = _src[_si++]
285 #endif /* !HANDLE_MULTIBYTE */
287 /****************************************************************
289 * The following are only guaranteed to work in subst.c *
291 ****************************************************************/
293 #if defined (HANDLE_MULTIBYTE)
294 # define SCOPY_CHAR_I(_dst, _escchar, _sc, _src, _si, _slen) \
297 if (MB_CUR_MAX > 1) \
299 mbstate_t state_bak; \
304 mblength = mbrlen ((_src) + (_si), (_slen) - (_si), &state); \
305 if (mblength == (size_t)-2 || mblength == (size_t)-1) \
311 mblength = (mblength < 1) ? 1 : mblength; \
313 temp = xmalloc (mblength + 2); \
314 temp[0] = _escchar; \
315 for (_i = 0; _i < mblength; _i++) \
316 temp[_i + 1] = _src[_si++]; \
317 temp[mblength + 1] = '\0'; \
323 _dst[0] = _escchar; \
329 # define SCOPY_CHAR_I(_dst, _escchar, _sc, _src, _si, _slen) \
330 _dst[0] = _escchar; \
332 #endif /* !HANDLE_MULTIBYTE */
334 #if defined (HANDLE_MULTIBYTE)
335 # define SCOPY_CHAR_M(_dst, _src, _srcend, _si) \
338 if (MB_CUR_MAX > 1) \
340 mbstate_t state_bak; \
344 mblength = mbrlen ((_src) + (_si), (_srcend) - ((_src) + (_si)), &state); \
345 if (mblength == (size_t)-2 || mblength == (size_t)-1) \
351 mblength = (mblength < 1) ? 1 : mblength; \
353 FASTCOPY(((_src) + (_si)), (_dst), mblength); \
355 (_dst) += mblength; \
360 *(_dst)++ = _src[(_si)]; \
366 # define SCOPY_CHAR_M(_dst, _src, _srcend, _si) \
367 *(_dst)++ = _src[(_si)]; \
369 #endif /* !HANDLE_MULTIBYTE */
372 # define SADD_MBCHAR(_dst, _src, _si, _srcsize) \
375 if (MB_CUR_MAX > 1) \
378 mbstate_t state_bak; \
382 mblength = mbrlen ((_src) + (_si), (_srcsize) - (_si), &state); \
383 if (mblength == (size_t)-1 || mblength == (size_t)-2) \
391 _dst = (char *)xmalloc (mblength + 1); \
392 for (i = 0; i < mblength; i++) \
393 (_dst)[i] = (_src)[(_si)++]; \
394 (_dst)[mblength] = '\0'; \
402 # define SADD_MBCHAR(_dst, _src, _si, _srcsize)
405 /* Watch out when using this -- it's just straight textual subsitution */
406 #if defined (HANDLE_MULTIBYTE)
407 # define SADD_MBQCHAR_BODY(_dst, _src, _si, _srcsize) \
410 mbstate_t state_bak; \
414 mblength = mbrlen ((_src) + (_si), (_srcsize) - (_si), &state); \
415 if (mblength == (size_t)-1 || mblength == (size_t)-2) \
423 (_dst) = (char *)xmalloc (mblength + 2); \
424 (_dst)[0] = CTLESC; \
425 for (i = 0; i < mblength; i++) \
426 (_dst)[i+1] = (_src)[(_si)++]; \
427 (_dst)[mblength+1] = '\0'; \
431 #endif /* HANDLE_MULTIBYTE */
432 #endif /* _SH_MBUTIL_H_ */