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 size_t mbstrlen __P((const char *));
36 extern char *xstrchr __P((const char *, int));
39 #define MB_INVALIDCH(x) ((x) == (size_t)-1 || (x) == (size_t)-2)
40 #define MB_NULLWCH(x) ((x) == 0)
43 #define MBSLEN(s) (((s) && (s)[0]) ? ((s)[1] ? mbstrlen (s) : 1) : 0)
44 #define MB_STRLEN(s) ((MB_CUR_MAX > 1) ? MBSLEN (s) : STRLEN (s))
46 #define MBLEN(s, n) ((MB_CUR_MAX > 1) ? mblen ((s), (n)) : 1)
47 #define MBRLEN(s, n, p) ((MB_CUR_MAX > 1) ? mbrlen ((s), (n), (p)) : 1)
49 #else /* !HANDLE_MULTIBYTE */
58 #define xstrchr(s, c) strchr(s, c)
61 #define MB_INVALIDCH(x) (0)
62 #define MB_NULLWCH(x) (0)
65 #define MB_STRLEN(s) (STRLEN(s))
68 #define MBRLEN(s, n, p) 1
70 #endif /* !HANDLE_MULTIBYTE */
72 /* Declare and initialize a multibyte state. Call must be terminated
74 #if defined (HANDLE_MULTIBYTE)
75 # define DECLARE_MBSTATE \
77 memset (&state, '\0', sizeof (mbstate_t))
79 # define DECLARE_MBSTATE
80 #endif /* !HANDLE_MULTIBYTE */
82 /* Initialize or reinitialize a multibyte state named `state'. Call must be
83 terminated with `;'. */
84 #if defined (HANDLE_MULTIBYTE)
85 # define INITIALIZE_MBSTATE memset (&state, '\0', sizeof (mbstate_t))
87 # define INITIALIZE_MBSTATE
88 #endif /* !HANDLE_MULTIBYTE */
90 /* Advance one (possibly multi-byte) character in string _STR of length
91 _STRSIZE, starting at index _I. STATE must have already been declared. */
92 #if defined (HANDLE_MULTIBYTE)
93 # define ADVANCE_CHAR(_str, _strsize, _i) \
98 mbstate_t state_bak; \
102 mblength = mbrlen ((_str) + (_i), (_strsize) - (_i), &state); \
104 if (mblength == (size_t)-2 || mblength == (size_t)-1) \
109 else if (mblength == 0) \
119 # define ADVANCE_CHAR(_str, _strsize, _i) (_i)++
120 #endif /* !HANDLE_MULTIBYTE */
122 /* Advance one (possibly multibyte) character in the string _STR of length
124 SPECIAL: assume that _STR will be incremented by 1 after this call. */
125 #if defined (HANDLE_MULTIBYTE)
126 # define ADVANCE_CHAR_P(_str, _strsize) \
129 if (MB_CUR_MAX > 1) \
131 mbstate_t state_bak; \
135 mblength = mbrlen ((_str), (_strsize), &state); \
137 if (mblength == (size_t)-2 || mblength == (size_t)-1) \
143 (_str) += (mblength < 1) ? 0 : (mblength - 1); \
148 # define ADVANCE_CHAR_P(_str, _strsize)
149 #endif /* !HANDLE_MULTIBYTE */
151 /* Back up one (possibly multi-byte) character in string _STR of length
152 _STRSIZE, starting at index _I. STATE must have already been declared. */
153 #if defined (HANDLE_MULTIBYTE)
154 # define BACKUP_CHAR(_str, _strsize, _i) \
157 if (MB_CUR_MAX > 1) \
159 mbstate_t state_bak; \
161 int _x, _p; /* _x == temp index into string, _p == prev index */ \
167 mblength = mbrlen ((_str) + (_x), (_strsize) - (_x), &state); \
169 if (mblength == (size_t)-2 || mblength == (size_t)-1) \
174 else if (mblength == 0) \
178 _p = _x; /* _p == start of prev mbchar */ \
189 # define BACKUP_CHAR(_str, _strsize, _i) (_i)--
190 #endif /* !HANDLE_MULTIBYTE */
192 /* Back up one (possibly multibyte) character in the string _BASE of length
193 _STRSIZE starting at _STR (_BASE <= _STR <= (_BASE + _STRSIZE) ).
194 SPECIAL: DO NOT assume that _STR will be decremented by 1 after this call. */
195 #if defined (HANDLE_MULTIBYTE)
196 # define BACKUP_CHAR_P(_base, _strsize, _str) \
199 if (MB_CUR_MAX > 1) \
201 mbstate_t state_bak; \
203 char *_x, _p; /* _x == temp pointer into string, _p == prev pointer */ \
206 while (_x < (_str)) \
209 mblength = mbrlen (_x, (_strsize) - _x, &state); \
211 if (mblength == (size_t)-2 || mblength == (size_t)-1) \
216 else if (mblength == 0) \
220 _p = _x; /* _p == start of prev mbchar */ \
231 # define BACKUP_CHAR_P(_base, _strsize, _str) (_str)--
232 #endif /* !HANDLE_MULTIBYTE */
234 /* Copy a single character from the string _SRC to the string _DST.
235 _SRCEND is a pointer to the end of _SRC. */
236 #if defined (HANDLE_MULTIBYTE)
237 # define COPY_CHAR_P(_dst, _src, _srcend) \
240 if (MB_CUR_MAX > 1) \
242 mbstate_t state_bak; \
247 mblength = mbrlen ((_src), (_srcend) - (_src), &state); \
248 if (mblength == (size_t)-2 || mblength == (size_t)-1) \
254 mblength = (mblength < 1) ? 1 : mblength; \
256 for (_k = 0; _k < mblength; _k++) \
257 *(_dst)++ = *(_src)++; \
260 *(_dst)++ = *(_src)++; \
264 # define COPY_CHAR_P(_dst, _src, _srcend) *(_dst)++ = *(_src)++
265 #endif /* !HANDLE_MULTIBYTE */
267 /* Copy a single character from the string _SRC at index _SI to the string
268 _DST at index _DI. _SRCEND is a pointer to the end of _SRC. */
269 #if defined (HANDLE_MULTIBYTE)
270 # define COPY_CHAR_I(_dst, _di, _src, _srcend, _si) \
273 if (MB_CUR_MAX > 1) \
275 mbstate_t state_bak; \
280 mblength = mbrlen ((_src) + (_si), (_srcend) - ((_src)+(_si)), &state); \
281 if (mblength == (size_t)-2 || mblength == (size_t)-1) \
287 mblength = (mblength < 1) ? 1 : mblength; \
289 for (_k = 0; _k < mblength; _k++) \
290 _dst[_di++] = _src[_si++]; \
293 _dst[_di++] = _src[_si++]; \
297 # define COPY_CHAR_I(_dst, _di, _src, _srcend, _si) _dst[_di++] = _src[_si++]
298 #endif /* !HANDLE_MULTIBYTE */
300 /****************************************************************
302 * The following are only guaranteed to work in subst.c *
304 ****************************************************************/
306 #if defined (HANDLE_MULTIBYTE)
307 # define SCOPY_CHAR_I(_dst, _escchar, _sc, _src, _si, _slen) \
310 if (MB_CUR_MAX > 1) \
312 mbstate_t state_bak; \
317 mblength = mbrlen ((_src) + (_si), (_slen) - (_si), &state); \
318 if (mblength == (size_t)-2 || mblength == (size_t)-1) \
324 mblength = (mblength < 1) ? 1 : mblength; \
326 temp = xmalloc (mblength + 2); \
327 temp[0] = _escchar; \
328 for (_i = 0; _i < mblength; _i++) \
329 temp[_i + 1] = _src[_si++]; \
330 temp[mblength + 1] = '\0'; \
336 _dst[0] = _escchar; \
342 # define SCOPY_CHAR_I(_dst, _escchar, _sc, _src, _si, _slen) \
343 _dst[0] = _escchar; \
345 #endif /* !HANDLE_MULTIBYTE */
347 #if defined (HANDLE_MULTIBYTE)
348 # define SCOPY_CHAR_M(_dst, _src, _srcend, _si) \
351 if (MB_CUR_MAX > 1) \
353 mbstate_t state_bak; \
357 mblength = mbrlen ((_src) + (_si), (_srcend) - ((_src) + (_si)), &state); \
358 if (mblength == (size_t)-2 || mblength == (size_t)-1) \
364 mblength = (mblength < 1) ? 1 : mblength; \
366 FASTCOPY(((_src) + (_si)), (_dst), mblength); \
368 (_dst) += mblength; \
373 *(_dst)++ = _src[(_si)]; \
379 # define SCOPY_CHAR_M(_dst, _src, _srcend, _si) \
380 *(_dst)++ = _src[(_si)]; \
382 #endif /* !HANDLE_MULTIBYTE */
385 # define SADD_MBCHAR(_dst, _src, _si, _srcsize) \
388 if (MB_CUR_MAX > 1) \
391 mbstate_t state_bak; \
395 mblength = mbrlen ((_src) + (_si), (_srcsize) - (_si), &state); \
396 if (mblength == (size_t)-1 || mblength == (size_t)-2) \
404 _dst = (char *)xmalloc (mblength + 1); \
405 for (i = 0; i < mblength; i++) \
406 (_dst)[i] = (_src)[(_si)++]; \
407 (_dst)[mblength] = '\0'; \
415 # define SADD_MBCHAR(_dst, _src, _si, _srcsize)
418 /* Watch out when using this -- it's just straight textual subsitution */
419 #if defined (HANDLE_MULTIBYTE)
420 # define SADD_MBQCHAR_BODY(_dst, _src, _si, _srcsize) \
423 mbstate_t state_bak; \
427 mblength = mbrlen ((_src) + (_si), (_srcsize) - (_si), &state); \
428 if (mblength == (size_t)-1 || mblength == (size_t)-2) \
436 (_dst) = (char *)xmalloc (mblength + 2); \
437 (_dst)[0] = CTLESC; \
438 for (i = 0; i < mblength; i++) \
439 (_dst)[i+1] = (_src)[(_si)++]; \
440 (_dst)[mblength+1] = '\0'; \
444 #endif /* HANDLE_MULTIBYTE */
445 #endif /* _SH_MBUTIL_H_ */