Imported from ../bash-2.05b.tar.gz.
[platform/upstream/bash.git] / include / shmbutil.h
1 /* shmbutil.h -- utility functions for multibyte characters. */
2
3 /* Copyright (C) 2002 Free Software Foundation, Inc.
4
5    This file is part of GNU Bash, the Bourne Again SHell.
6
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
10    version.
11
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
15    for more details.
16
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. */
20                                  
21 #if !defined (_SH_MBUTIL_H_)
22 #define _SH_MBUTIL_H_
23
24 #include "stdc.h"
25
26 /************************************************/
27 /* check multibyte capability for I18N code     */
28 /************************************************/
29
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)
34 #  include <wchar.h>
35 #  include <wctype.h>
36 #  if defined (HAVE_MBSRTOWCS) /* system is supposed to support XPG5 */
37 #    define HANDLE_MULTIBYTE      1
38 #  endif
39 #endif /* HAVE_WCTYPE_H && HAVE_WCHAR_H */
40
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 */
50
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
54 #  include <limits.h>
55 #  if defined(MB_LEN_MAX) && (MB_LEN_MAX < 16)
56 #    undef MB_LEN_MAX
57 #  endif
58 #  if !defined (MB_LEN_MAX)
59 #    define MB_LEN_MAX 16
60 #  endif
61 #endif /* HANDLE_MULTIBYTE */
62
63 /************************************************/
64 /* end of multibyte capability checks for I18N  */
65 /************************************************/
66
67 #if defined (HANDLE_MULTIBYTE)
68
69 extern size_t xmbsrtowcs __P((wchar_t *, const char **, size_t, mbstate_t *));
70
71 extern char *xstrchr __P((const char *, int));
72
73 #else /* !HANDLE_MULTIBYTE */
74
75 #undef MB_LEN_MAX
76 #undef MB_CUR_MAX
77
78 #define MB_LEN_MAX      1
79 #define MB_CUR_MAX      1
80
81 #undef xstrchr
82 #define xstrchr(s, c)   strchr(s, c)
83
84 #endif /* !HANDLE_MULTIBYTE */
85
86 /* Declare and initialize a multibyte state.  Call must be terminated
87    with `;'. */
88 #if defined (HANDLE_MULTIBYTE)
89 #  define DECLARE_MBSTATE \
90         mbstate_t state; \
91         memset (&state, '\0', sizeof (mbstate_t))
92 #else
93 #  define DECLARE_MBSTATE
94 #endif  /* !HANDLE_MULTIBYTE */
95
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))
100 #else
101 #  define INITIALIZE_MBSTATE
102 #endif  /* !HANDLE_MULTIBYTE */
103
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) \
108     do \
109       { \
110         if (MB_CUR_MAX > 1) \
111           { \
112             mbstate_t state_bak; \
113             size_t mblength; \
114 \
115             state_bak = state; \
116             mblength = mbrlen ((_str) + (_i), (_strsize) - (_i), &state); \
117 \
118             if (mblength == (size_t)-2 || mblength == (size_t)-1) \
119               { \
120                 state = state_bak; \
121                 (_i)++; \
122               } \
123             else \
124               (_i) += mblength; \
125           } \
126         else \
127           (_i)++; \
128       } \
129     while (0)
130 #else
131 #  define ADVANCE_CHAR(_str, _strsize, _i)      (_i)++
132 #endif  /* !HANDLE_MULTIBYTE */
133
134 /* Advance one (possibly multibyte) character in the string _STR of length
135    _STRSIZE.
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) \
139     do \
140       { \
141         if (MB_CUR_MAX > 1) \
142           { \
143             mbstate_t state_bak; \
144             size_t mblength; \
145 \
146             state_bak = state; \
147             mblength = mbrlen ((_str), (_strsize), &state); \
148 \
149             if (mblength == (size_t)-2 || mblength == (size_t)-1) \
150               { \
151                 state = state_bak; \
152                 mblength = 1; \
153               } \
154             else \
155               (_str) += (mblength < 1) ? 0 : (mblength - 1); \
156           } \
157       } \
158     while (0)
159 #else
160 #  define ADVANCE_CHAR_P(_str, _strsize)
161 #endif  /* !HANDLE_MULTIBYTE */
162
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) \
167     do \
168       { \
169         if (MB_CUR_MAX > 1) \
170           { \
171             mbstate_t state_bak; \
172             size_t mblength; \
173             int _k; \
174 \
175             state_bak = state; \
176             mblength = mbrlen ((_src), (_srcend) - (_src), &state); \
177             if (mblength == (size_t)-2 || mblength == (size_t)-1) \
178               { \
179                 state = state_bak; \
180                 mblength = 1; \
181               } \
182             else \
183               mblength = (mblength < 1) ? 1 : mblength; \
184 \
185             for (_k = 0; _k < mblength; _k++) \
186               *(_dst)++ = *(_src)++; \
187           } \
188         else \
189           *(_dst)++ = *(_src)++; \
190       } \
191     while (0)
192 #else
193 #  define COPY_CHAR_P(_dst, _src, _srcend)      *(_dst)++ = *(_src)++
194 #endif  /* !HANDLE_MULTIBYTE */
195
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) \
200     do \
201       { \
202         if (MB_CUR_MAX > 1) \
203           { \
204             mbstate_t state_bak; \
205             size_t mblength; \
206             int _k; \
207 \
208             state_bak = state; \
209             mblength = mbrlen ((_src) + (_si), (_srcend) - ((_src)+(_si)), &state); \
210             if (mblength == (size_t)-2 || mblength == (size_t)-1) \
211               { \
212                 state = state_bak; \
213                 mblength = 1; \
214               } \
215             else \
216               mblength = (mblength < 1) ? 1 : mblength; \
217 \
218             for (_k = 0; _k < mblength; _k++) \
219               _dst[_di++] = _src[_si++]; \
220           } \
221         else \
222           _dst[_di++] = _src[_si++]; \
223       } \
224     while (0)
225 #else
226 #  define COPY_CHAR_I(_dst, _di, _src, _srcend, _si)    _dst[_di++] = _src[_si++]
227 #endif  /* !HANDLE_MULTIBYTE */
228
229 /****************************************************************
230  *                                                              *
231  * The following are only guaranteed to work in subst.c         *
232  *                                                              *
233  ****************************************************************/
234
235 #if defined (HANDLE_MULTIBYTE)
236 #  define SCOPY_CHAR_I(_dst, _escchar, _sc, _src, _si, _slen) \
237     do \
238       { \
239         if (MB_CUR_MAX > 1) \
240           { \
241             mbstate_t state_bak; \
242             size_t mblength; \
243             int _i; \
244 \
245             state_bak = state; \
246             mblength = mbrlen ((_src) + (_si), (_slen) - (_si), &state); \
247             if (mblength == (size_t)-2 || mblength == (size_t)-1) \
248               { \
249                 state = state_bak; \
250                 mblength = 1; \
251               } \
252             else \
253               mblength = (mblength < 1) ? 1 : mblength; \
254 \
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'; \
260 \
261             goto add_string; \
262           } \
263         else \
264           { \
265             _dst[0] = _escchar; \
266             _dst[1] = _sc; \
267           } \
268       } \
269     while (0)
270 #else
271 #  define SCOPY_CHAR_I(_dst, _escchar, _sc, _src, _si, _slen) \
272     _dst[0] = _escchar; \
273     _dst[1] = _sc
274 #endif  /* !HANDLE_MULTIBYTE */
275
276 #if defined (HANDLE_MULTIBYTE)
277 #  define SCOPY_CHAR_M(_dst, _src, _srcend, _si) \
278     do \
279       { \
280         if (MB_CUR_MAX > 1) \
281           { \
282             mbstate_t state_bak; \
283             size_t mblength; \
284 \
285             state_bak = state; \
286             mblength = mbrlen ((_src) + (_si), (_srcend) - ((_src) + (_si)), &state); \
287             if (mblength == (size_t)-2 || mblength == (size_t)-1) \
288               { \
289                 state = state_bak; \
290                 mblength = 1; \
291               } \
292             else \
293               mblength = (mblength < 1) ? 1 : mblength; \
294 \
295             FASTCOPY(((_src) + (_si)), (_dst), mblength); \
296 \
297             (_dst) += mblength; \
298             (_si) += mblength; \
299           } \
300         else \
301           { \
302             *(_dst)++ = _src[(_si)]; \
303             (_si)++; \
304           } \
305       } \
306     while (0)
307 #else
308 #  define SCOPY_CHAR_M(_dst, _src, _srcend, _si) \
309         *(_dst)++ = _src[(_si)]; \
310         (_si)++
311 #endif  /* !HANDLE_MULTIBYTE */
312
313 #if HANDLE_MULTIBYTE
314 #  define SADD_MBCHAR(_dst, _src, _si, _srcsize) \
315     do \
316       { \
317         if (MB_CUR_MAX > 1) \
318           { \
319             int i; \
320             mbstate_t state_bak; \
321             size_t mblength; \
322 \
323             state_bak = state; \
324             mblength = mbrlen ((_src) + (_si), (_srcsize) - (_si), &state); \
325             if (mblength == (size_t)-1 || mblength == (size_t)-2) \
326               { \
327                 state = state_bak; \
328                 mblength = 1; \
329               } \
330             if (mblength < 1) \
331               mblength = 1; \
332 \
333             _dst = (char *)xmalloc (mblength + 1); \
334             for (i = 0; i < mblength; i++) \
335               (_dst)[i] = (_src)[(_si)++]; \
336             (_dst)[mblength] = '\0'; \
337 \
338             goto add_string; \
339           } \
340       } \
341     while (0)
342
343 #else
344 #  define SADD_MBCHAR(_dst, _src, _si, _srcsize)
345 #endif
346
347 #endif /* _SH_MBUTIL_H_ */