]>
git.ipfire.org Git - thirdparty/bash.git/blob - include/shmbutil.h
1 /* shmbutil.h -- utility functions for multibyte characters. */
3 /* Copyright (C) 2002-2022 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/>.
21 #if !defined (_SH_MBUTIL_H_)
26 /* Include config.h for HANDLE_MULTIBYTE */
29 #if defined (HANDLE_MULTIBYTE)
32 extern size_t xwcsrtombs
PARAMS((char *, const wchar_t **, size_t, mbstate_t *));
33 extern size_t xmbsrtowcs
PARAMS((wchar_t *, const char **, size_t, mbstate_t *));
34 extern size_t xdupmbstowcs
PARAMS((wchar_t **, char ***, const char *));
36 extern size_t mbstrlen
PARAMS((const char *));
38 extern char *xstrchr
PARAMS((const char *, int));
40 extern int locale_mb_cur_max
; /* XXX */
41 extern int locale_utf8locale
; /* XXX */
44 #define MB_INVALIDCH(x) ((x) == (size_t)-1 || (x) == (size_t)-2)
45 #define MB_NULLWCH(x) ((x) == 0)
48 #define MBSLEN(s) (((s) && (s)[0]) ? ((s)[1] ? mbstrlen (s) : 1) : 0)
49 #define MB_STRLEN(s) ((MB_CUR_MAX > 1) ? MBSLEN (s) : STRLEN (s))
51 #define MBLEN(s, n) ((MB_CUR_MAX > 1) ? mblen ((s), (n)) : 1)
52 #define MBRLEN(s, n, p) ((MB_CUR_MAX > 1) ? mbrlen ((s), (n), (p)) : 1)
54 #define UTF8_SINGLEBYTE(c) (((c) & 0x80) == 0)
55 #define UTF8_MBFIRSTCHAR(c) (((c) & 0xc0) == 0xc0)
56 #define UTF8_MBCHAR(c) (((c) & 0xc0) == 0x80)
58 #else /* !HANDLE_MULTIBYTE */
67 #define xstrchr(s, c) strchr(s, c)
70 #define MB_INVALIDCH(x) (0)
71 #define MB_NULLWCH(x) (0)
74 #define MB_STRLEN(s) (STRLEN(s))
77 #define MBRLEN(s, n, p) 1
83 #define UTF8_SINGLEBYTE(c) (1)
84 #define UTF8_MBFIRSTCHAR(c) (0)
86 #endif /* !HANDLE_MULTIBYTE */
88 /* Declare and initialize a multibyte state. Call must be terminated
90 #if defined (HANDLE_MULTIBYTE)
91 # define DECLARE_MBSTATE \
93 memset (&state, '\0', sizeof (mbstate_t))
95 # define DECLARE_MBSTATE
96 #endif /* !HANDLE_MULTIBYTE */
98 /* Initialize or reinitialize a multibyte state named `state'. Call must be
99 terminated with `;'. */
100 #if defined (HANDLE_MULTIBYTE)
101 # define INITIALIZE_MBSTATE memset (&state, '\0', sizeof (mbstate_t))
103 # define INITIALIZE_MBSTATE
104 #endif /* !HANDLE_MULTIBYTE */
106 /* Advance one (possibly multi-byte) character in string _STR of length
107 _STRSIZE, starting at index _I. STATE must have already been declared. */
108 #if defined (HANDLE_MULTIBYTE)
109 # define ADVANCE_CHAR(_str, _strsize, _i) \
112 if (locale_mb_cur_max > 1) \
114 mbstate_t state_bak; \
118 _f = is_basic ((_str)[_i]); \
121 else if (locale_utf8locale && (((_str)[_i] & 0x80) == 0)) \
122 mblength = (_str)[_i] != 0; \
126 mblength = mbrlen ((_str) + (_i), (_strsize) - (_i), &state); \
129 if (mblength == (size_t)-2 || mblength == (size_t)-1) \
134 else if (mblength == 0) \
144 # define ADVANCE_CHAR(_str, _strsize, _i) (_i)++
145 #endif /* !HANDLE_MULTIBYTE */
147 /* Advance one (possibly multibyte) character in the string _STR of length
149 SPECIAL: assume that _STR will be incremented by 1 after this call. */
150 #if defined (HANDLE_MULTIBYTE)
151 # define ADVANCE_CHAR_P(_str, _strsize) \
154 if (locale_mb_cur_max > 1) \
156 mbstate_t state_bak; \
160 _f = is_basic (*(_str)); \
163 else if (locale_utf8locale && ((*(_str) & 0x80) == 0)) \
164 mblength = *(_str) != 0; \
168 mblength = mbrlen ((_str), (_strsize), &state); \
171 if (mblength == (size_t)-2 || mblength == (size_t)-1) \
177 (_str) += (mblength < 1) ? 0 : (mblength - 1); \
182 # define ADVANCE_CHAR_P(_str, _strsize)
183 #endif /* !HANDLE_MULTIBYTE */
185 /* Back up one (possibly multi-byte) character in string _STR of length
186 _STRSIZE, starting at index _I. STATE must have already been declared. */
187 #if defined (HANDLE_MULTIBYTE)
188 # define BACKUP_CHAR(_str, _strsize, _i) \
191 if (locale_mb_cur_max > 1) \
193 mbstate_t state_bak; \
195 int _x, _p; /* _x == temp index into string, _p == prev index */ \
201 mblength = mbrlen ((_str) + (_x), (_strsize) - (_x), &state); \
203 if (mblength == (size_t)-2 || mblength == (size_t)-1) \
208 else if (mblength == 0) \
212 _p = _x; /* _p == start of prev mbchar */ \
223 # define BACKUP_CHAR(_str, _strsize, _i) (_i)--
224 #endif /* !HANDLE_MULTIBYTE */
226 /* Back up one (possibly multibyte) character in the string _BASE of length
227 _STRSIZE starting at _STR (_BASE <= _STR <= (_BASE + _STRSIZE) ).
228 SPECIAL: DO NOT assume that _STR will be decremented by 1 after this call. */
229 #if defined (HANDLE_MULTIBYTE)
230 # define BACKUP_CHAR_P(_base, _strsize, _str) \
233 if (locale_mb_cur_max > 1) \
235 mbstate_t state_bak; \
237 char *_x, _p; /* _x == temp pointer into string, _p == prev pointer */ \
240 while (_x < (_str)) \
243 mblength = mbrlen (_x, (_strsize) - _x, &state); \
245 if (mblength == (size_t)-2 || mblength == (size_t)-1) \
250 else if (mblength == 0) \
254 _p = _x; /* _p == start of prev mbchar */ \
265 # define BACKUP_CHAR_P(_base, _strsize, _str) (_str)--
266 #endif /* !HANDLE_MULTIBYTE */
268 /* Copy a single character from the string _SRC to the string _DST.
269 _SRCEND is a pointer to the end of _SRC. */
270 #if defined (HANDLE_MULTIBYTE)
271 # define COPY_CHAR_P(_dst, _src, _srcend) \
274 if (locale_mb_cur_max > 1) \
276 mbstate_t state_bak; \
280 _k = is_basic (*(_src)); \
283 else if (locale_utf8locale && ((*(_src) & 0x80) == 0)) \
284 mblength = *(_src) != 0; \
288 mblength = mbrlen ((_src), (_srcend) - (_src), &state); \
290 if (mblength == (size_t)-2 || mblength == (size_t)-1) \
296 mblength = (mblength < 1) ? 1 : mblength; \
298 for (_k = 0; _k < mblength; _k++) \
299 *(_dst)++ = *(_src)++; \
302 *(_dst)++ = *(_src)++; \
306 # define COPY_CHAR_P(_dst, _src, _srcend) *(_dst)++ = *(_src)++
307 #endif /* !HANDLE_MULTIBYTE */
309 /* Copy a single character from the string _SRC at index _SI to the string
310 _DST at index _DI. _SRCEND is a pointer to the end of _SRC. */
311 #if defined (HANDLE_MULTIBYTE)
312 # define COPY_CHAR_I(_dst, _di, _src, _srcend, _si) \
315 if (locale_mb_cur_max > 1) \
317 mbstate_t state_bak; \
321 _k = is_basic ((_src)[(_si)]); \
324 else if (locale_utf8locale && ((_src)[(_si)] & 0x80) == 0) \
325 mblength = (_src)[(_si)] != 0; \
329 mblength = mbrlen ((_src) + (_si), (_srcend) - ((_src)+(_si)), &state); \
331 if (mblength == (size_t)-2 || mblength == (size_t)-1) \
337 mblength = (mblength < 1) ? 1 : mblength; \
339 for (_k = 0; _k < mblength; _k++) \
340 _dst[_di++] = _src[_si++]; \
343 _dst[_di++] = _src[_si++]; \
347 # define COPY_CHAR_I(_dst, _di, _src, _srcend, _si) _dst[_di++] = _src[_si++]
348 #endif /* !HANDLE_MULTIBYTE */
350 /****************************************************************
352 * The following are only guaranteed to work in subst.c *
354 ****************************************************************/
356 #if defined (HANDLE_MULTIBYTE)
357 # define SCOPY_CHAR_I(_dst, _escchar, _sc, _src, _si, _slen) \
360 if (locale_mb_cur_max > 1) \
362 mbstate_t state_bak; \
366 _i = is_basic ((_src)[(_si)]); \
369 else if (locale_utf8locale && ((_src)[(_si)] & 0x80) == 0) \
370 mblength = (_src)[(_si)] != 0; \
374 mblength = mbrlen ((_src) + (_si), (_slen) - (_si), &state); \
376 if (mblength == (size_t)-2 || mblength == (size_t)-1) \
382 mblength = (mblength < 1) ? 1 : mblength; \
384 temp = xmalloc (mblength + 2); \
385 temp[0] = _escchar; \
386 for (_i = 0; _i < mblength; _i++) \
387 temp[_i + 1] = _src[_si++]; \
388 temp[mblength + 1] = '\0'; \
394 _dst[0] = _escchar; \
400 # define SCOPY_CHAR_I(_dst, _escchar, _sc, _src, _si, _slen) \
401 _dst[0] = _escchar; \
403 #endif /* !HANDLE_MULTIBYTE */
405 #if defined (HANDLE_MULTIBYTE)
406 # define SCOPY_CHAR_M(_dst, _src, _srcend, _si) \
409 if (locale_mb_cur_max > 1) \
411 mbstate_t state_bak; \
415 _i = is_basic (*((_src) + (_si))); \
418 else if (locale_utf8locale && (((_src)[_si] & 0x80) == 0)) \
419 mblength = (_src)[_si] != 0; \
423 mblength = mbrlen ((_src) + (_si), (_srcend) - ((_src) + (_si)), &state); \
425 if (mblength == (size_t)-2 || mblength == (size_t)-1) \
431 mblength = (mblength < 1) ? 1 : mblength; \
433 FASTCOPY(((_src) + (_si)), (_dst), mblength); \
435 (_dst) += mblength; \
440 *(_dst)++ = _src[(_si)]; \
446 # define SCOPY_CHAR_M(_dst, _src, _srcend, _si) \
447 *(_dst)++ = _src[(_si)]; \
449 #endif /* !HANDLE_MULTIBYTE */
452 # define SADD_MBCHAR(_dst, _src, _si, _srcsize) \
455 if (locale_mb_cur_max > 1) \
458 mbstate_t state_bak; \
461 i = is_basic (*((_src) + (_si))); \
464 else if (locale_utf8locale && (((_src)[_si] & 0x80) == 0)) \
465 mblength = (_src)[_si] != 0; \
469 mblength = mbrlen ((_src) + (_si), (_srcsize) - (_si), &state); \
471 if (mblength == (size_t)-1 || mblength == (size_t)-2) \
479 _dst = (char *)xmalloc (mblength + 1); \
480 for (i = 0; i < mblength; i++) \
481 (_dst)[i] = (_src)[(_si)++]; \
482 (_dst)[mblength] = '\0'; \
490 # define SADD_MBCHAR(_dst, _src, _si, _srcsize)
493 /* Watch out when using this -- it's just straight textual substitution */
494 #if defined (HANDLE_MULTIBYTE)
495 # define SADD_MBQCHAR_BODY(_dst, _src, _si, _srcsize) \
498 mbstate_t state_bak; \
501 i = is_basic (*((_src) + (_si))); \
504 else if (locale_utf8locale && (((_src)[_si] & 0x80) == 0)) \
505 mblength = (_src)[_si] != 0; \
509 mblength = mbrlen ((_src) + (_si), (_srcsize) - (_si), &state); \
511 if (mblength == (size_t)-1 || mblength == (size_t)-2) \
519 (_dst) = (char *)xmalloc (mblength + 2); \
520 (_dst)[0] = CTLESC; \
521 for (i = 0; i < mblength; i++) \
522 (_dst)[i+1] = (_src)[(_si)++]; \
523 (_dst)[mblength+1] = '\0'; \
527 # define SADD_MBCHAR_BODY(_dst, _src, _si, _srcsize) \
530 mbstate_t state_bak; \
533 i = is_basic (*((_src) + (_si))); \
536 else if (locale_utf8locale && (((_src)[_si] & 0x80) == 0)) \
537 mblength = (_src)[_si] != 0; \
541 mblength = mbrlen ((_src) + (_si), (_srcsize) - (_si), &state); \
543 if (mblength == (size_t)-1 || mblength == (size_t)-2) \
551 (_dst) = (char *)xmalloc (mblength + 1); \
552 for (i = 0; i < mblength; i++) \
553 (_dst)[i+1] = (_src)[(_si)++]; \
554 (_dst)[mblength+1] = '\0'; \
558 #endif /* HANDLE_MULTIBYTE */
559 #endif /* _SH_MBUTIL_H_ */