]>
git.ipfire.org Git - thirdparty/bash.git/blob - include/shmbutil.h
835fb80cdb6ee23f2e70216fb1fb8bb3e438bd82
1 /* shmbutil.h -- utility functions for multibyte characters. */
3 /* Copyright (C) 2002-2019 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))); \
327 mblength = mbrlen ((_src) + (_si), (_srcend) - ((_src)+(_si)), &state); \
329 if (mblength == (size_t)-2 || mblength == (size_t)-1) \
335 mblength = (mblength < 1) ? 1 : mblength; \
337 for (_k = 0; _k < mblength; _k++) \
338 _dst[_di++] = _src[_si++]; \
341 _dst[_di++] = _src[_si++]; \
345 # define COPY_CHAR_I(_dst, _di, _src, _srcend, _si) _dst[_di++] = _src[_si++]
346 #endif /* !HANDLE_MULTIBYTE */
348 /****************************************************************
350 * The following are only guaranteed to work in subst.c *
352 ****************************************************************/
354 #if defined (HANDLE_MULTIBYTE)
355 # define SCOPY_CHAR_I(_dst, _escchar, _sc, _src, _si, _slen) \
358 if (locale_mb_cur_max > 1) \
360 mbstate_t state_bak; \
364 _i = is_basic (*((_src) + (_si))); \
370 mblength = mbrlen ((_src) + (_si), (_slen) - (_si), &state); \
372 if (mblength == (size_t)-2 || mblength == (size_t)-1) \
378 mblength = (mblength < 1) ? 1 : mblength; \
380 temp = xmalloc (mblength + 2); \
381 temp[0] = _escchar; \
382 for (_i = 0; _i < mblength; _i++) \
383 temp[_i + 1] = _src[_si++]; \
384 temp[mblength + 1] = '\0'; \
390 _dst[0] = _escchar; \
396 # define SCOPY_CHAR_I(_dst, _escchar, _sc, _src, _si, _slen) \
397 _dst[0] = _escchar; \
399 #endif /* !HANDLE_MULTIBYTE */
401 #if defined (HANDLE_MULTIBYTE)
402 # define SCOPY_CHAR_M(_dst, _src, _srcend, _si) \
405 if (locale_mb_cur_max > 1) \
407 mbstate_t state_bak; \
411 _i = is_basic (*((_src) + (_si))); \
417 mblength = mbrlen ((_src) + (_si), (_srcend) - ((_src) + (_si)), &state); \
419 if (mblength == (size_t)-2 || mblength == (size_t)-1) \
425 mblength = (mblength < 1) ? 1 : mblength; \
427 FASTCOPY(((_src) + (_si)), (_dst), mblength); \
429 (_dst) += mblength; \
434 *(_dst)++ = _src[(_si)]; \
440 # define SCOPY_CHAR_M(_dst, _src, _srcend, _si) \
441 *(_dst)++ = _src[(_si)]; \
443 #endif /* !HANDLE_MULTIBYTE */
446 # define SADD_MBCHAR(_dst, _src, _si, _srcsize) \
449 if (locale_mb_cur_max > 1) \
452 mbstate_t state_bak; \
455 i = is_basic (*((_src) + (_si))); \
458 else if (locale_utf8locale && (((_src)[_si] & 0x80) == 0)) \
459 mblength = (_src)[_si] != 0; \
463 mblength = mbrlen ((_src) + (_si), (_srcsize) - (_si), &state); \
465 if (mblength == (size_t)-1 || mblength == (size_t)-2) \
473 _dst = (char *)xmalloc (mblength + 1); \
474 for (i = 0; i < mblength; i++) \
475 (_dst)[i] = (_src)[(_si)++]; \
476 (_dst)[mblength] = '\0'; \
484 # define SADD_MBCHAR(_dst, _src, _si, _srcsize)
487 /* Watch out when using this -- it's just straight textual substitution */
488 #if defined (HANDLE_MULTIBYTE)
489 # define SADD_MBQCHAR_BODY(_dst, _src, _si, _srcsize) \
492 mbstate_t state_bak; \
495 i = is_basic (*((_src) + (_si))); \
498 else if (locale_utf8locale && (((_src)[_si] & 0x80) == 0)) \
499 mblength = (_src)[_si] != 0; \
503 mblength = mbrlen ((_src) + (_si), (_srcsize) - (_si), &state); \
505 if (mblength == (size_t)-1 || mblength == (size_t)-2) \
513 (_dst) = (char *)xmalloc (mblength + 2); \
514 (_dst)[0] = CTLESC; \
515 for (i = 0; i < mblength; i++) \
516 (_dst)[i+1] = (_src)[(_si)++]; \
517 (_dst)[mblength+1] = '\0'; \
521 # define SADD_MBCHAR_BODY(_dst, _src, _si, _srcsize) \
524 mbstate_t state_bak; \
527 i = is_basic (*((_src) + (_si))); \
533 mblength = mbrlen ((_src) + (_si), (_srcsize) - (_si), &state); \
535 if (mblength == (size_t)-1 || mblength == (size_t)-2) \
543 (_dst) = (char *)xmalloc (mblength + 1); \
544 for (i = 0; i < mblength; i++) \
545 (_dst)[i+1] = (_src)[(_si)++]; \
546 (_dst)[mblength+1] = '\0'; \
550 #endif /* HANDLE_MULTIBYTE */
551 #endif /* _SH_MBUTIL_H_ */