1139d5035df82a9ca61b0420f1357a4fc7559de0
[platform/upstream/bash.git] / include / shmbutil.h
1 /* shmbutil.h -- utility functions for multibyte characters. */
2
3 /* Copyright (C) 2002-2004 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 /* Include config.h for HANDLE_MULTIBYTE */
27 #include <config.h>
28
29 #if defined (HANDLE_MULTIBYTE)
30
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 *));
33
34 extern size_t mbstrlen __P((const char *));
35
36 extern char *xstrchr __P((const char *, int));
37
38 #ifndef MB_INVALIDCH
39 #define MB_INVALIDCH(x)         ((x) == (size_t)-1 || (x) == (size_t)-2)
40 #define MB_NULLWCH(x)           ((x) == 0)
41 #endif
42
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))
45
46 #else /* !HANDLE_MULTIBYTE */
47
48 #undef MB_LEN_MAX
49 #undef MB_CUR_MAX
50
51 #define MB_LEN_MAX      1
52 #define MB_CUR_MAX      1
53
54 #undef xstrchr
55 #define xstrchr(s, c)   strchr(s, c)
56
57 #ifndef MB_INVALIDCH
58 #define MB_INVALIDCH(x)         (0)
59 #define MB_NULLWCH(x)           (0)
60 #endif
61
62 #define MB_STRLEN(s)            (STRLEN(s))
63
64 #endif /* !HANDLE_MULTIBYTE */
65
66 /* Declare and initialize a multibyte state.  Call must be terminated
67    with `;'. */
68 #if defined (HANDLE_MULTIBYTE)
69 #  define DECLARE_MBSTATE \
70         mbstate_t state; \
71         memset (&state, '\0', sizeof (mbstate_t))
72 #else
73 #  define DECLARE_MBSTATE
74 #endif  /* !HANDLE_MULTIBYTE */
75
76 /* Initialize or reinitialize a multibyte state named `state'.  Call must be
77    terminated with `;'. */
78 #if defined (HANDLE_MULTIBYTE)
79 #  define INITIALIZE_MBSTATE memset (&state, '\0', sizeof (mbstate_t))
80 #else
81 #  define INITIALIZE_MBSTATE
82 #endif  /* !HANDLE_MULTIBYTE */
83
84 /* Advance one (possibly multi-byte) character in string _STR of length
85    _STRSIZE, starting at index _I.  STATE must have already been declared. */
86 #if defined (HANDLE_MULTIBYTE)
87 #  define ADVANCE_CHAR(_str, _strsize, _i) \
88     do \
89       { \
90         if (MB_CUR_MAX > 1) \
91           { \
92             mbstate_t state_bak; \
93             size_t mblength; \
94 \
95             state_bak = state; \
96             mblength = mbrlen ((_str) + (_i), (_strsize) - (_i), &state); \
97 \
98             if (mblength == (size_t)-2 || mblength == (size_t)-1) \
99               { \
100                 state = state_bak; \
101                 (_i)++; \
102               } \
103             else if (mblength == 0) \
104               (_i)++; \
105             else \
106               (_i) += mblength; \
107           } \
108         else \
109           (_i)++; \
110       } \
111     while (0)
112 #else
113 #  define ADVANCE_CHAR(_str, _strsize, _i)      (_i)++
114 #endif  /* !HANDLE_MULTIBYTE */
115
116 /* Advance one (possibly multibyte) character in the string _STR of length
117    _STRSIZE.
118    SPECIAL:  assume that _STR will be incremented by 1 after this call. */
119 #if defined (HANDLE_MULTIBYTE)
120 #  define ADVANCE_CHAR_P(_str, _strsize) \
121     do \
122       { \
123         if (MB_CUR_MAX > 1) \
124           { \
125             mbstate_t state_bak; \
126             size_t mblength; \
127 \
128             state_bak = state; \
129             mblength = mbrlen ((_str), (_strsize), &state); \
130 \
131             if (mblength == (size_t)-2 || mblength == (size_t)-1) \
132               { \
133                 state = state_bak; \
134                 mblength = 1; \
135               } \
136             else \
137               (_str) += (mblength < 1) ? 0 : (mblength - 1); \
138           } \
139       } \
140     while (0)
141 #else
142 #  define ADVANCE_CHAR_P(_str, _strsize)
143 #endif  /* !HANDLE_MULTIBYTE */
144
145 /* Back up one (possibly multi-byte) character in string _STR of length
146    _STRSIZE, starting at index _I.  STATE must have already been declared. */
147 #if defined (HANDLE_MULTIBYTE)
148 #  define BACKUP_CHAR(_str, _strsize, _i) \
149     do \
150       { \
151         if (MB_CUR_MAX > 1) \
152           { \
153             mbstate_t state_bak; \
154             size_t mblength; \
155             int _x, _p; /* _x == temp index into string, _p == prev index */ \
156 \
157             _x = _p = 0; \
158             while (_x < (_i)) \
159               { \
160                 state_bak = state; \
161                 mblength = mbrlen ((_str) + (_x), (_strsize) - (_x), &state); \
162 \
163                 if (mblength == (size_t)-2 || mblength == (size_t)-1) \
164                   { \
165                     state = state_bak; \
166                     _x++; \
167                   } \
168                 else if (mblength == 0) \
169                   _x++; \
170                 else \
171                   { \
172                     _p = _x; /* _p == start of prev mbchar */ \
173                     _x += mblength; \
174                   } \
175               } \
176             (_i) = _p; \
177           } \
178         else \
179           (_i)--; \
180       } \
181     while (0)
182 #else
183 #  define BACKUP_CHAR(_str, _strsize, _i)       (_i)--
184 #endif  /* !HANDLE_MULTIBYTE */
185
186 /* Back up one (possibly multibyte) character in the string _BASE of length
187    _STRSIZE starting at _STR (_BASE <= _STR <= (_BASE + _STRSIZE) ).
188    SPECIAL: DO NOT assume that _STR will be decremented by 1 after this call. */
189 #if defined (HANDLE_MULTIBYTE)
190 #  define BACKUP_CHAR_P(_base, _strsize, _str) \
191     do \
192       { \
193         if (MB_CUR_MAX > 1) \
194           { \
195             mbstate_t state_bak; \
196             size_t mblength; \
197             char *_x, _p; /* _x == temp pointer into string, _p == prev pointer */ \
198 \
199             _x = _p = _base; \
200             while (_x < (_str)) \
201               { \
202                 state_bak = state; \
203                 mblength = mbrlen (_x, (_strsize) - _x, &state); \
204 \
205                 if (mblength == (size_t)-2 || mblength == (size_t)-1) \
206                   { \
207                     state = state_bak; \
208                     _x++; \
209                   } \
210                 else if (mblength == 0) \
211                   _x++; \
212                 else \
213                   { \
214                     _p = _x; /* _p == start of prev mbchar */ \
215                     _x += mblength; \
216                   } \
217               } \
218             (_str) = _p; \
219           } \
220         else \
221           (_str)--; \
222       } \
223     while (0)
224 #else
225 #  define BACKUP_CHAR_P(_base, _strsize, _str) (_str)--
226 #endif  /* !HANDLE_MULTIBYTE */
227
228 /* Copy a single character from the string _SRC to the string _DST.
229    _SRCEND is a pointer to the end of _SRC. */
230 #if defined (HANDLE_MULTIBYTE)
231 #  define COPY_CHAR_P(_dst, _src, _srcend) \
232     do \
233       { \
234         if (MB_CUR_MAX > 1) \
235           { \
236             mbstate_t state_bak; \
237             size_t mblength; \
238             int _k; \
239 \
240             state_bak = state; \
241             mblength = mbrlen ((_src), (_srcend) - (_src), &state); \
242             if (mblength == (size_t)-2 || mblength == (size_t)-1) \
243               { \
244                 state = state_bak; \
245                 mblength = 1; \
246               } \
247             else \
248               mblength = (mblength < 1) ? 1 : mblength; \
249 \
250             for (_k = 0; _k < mblength; _k++) \
251               *(_dst)++ = *(_src)++; \
252           } \
253         else \
254           *(_dst)++ = *(_src)++; \
255       } \
256     while (0)
257 #else
258 #  define COPY_CHAR_P(_dst, _src, _srcend)      *(_dst)++ = *(_src)++
259 #endif  /* !HANDLE_MULTIBYTE */
260
261 /* Copy a single character from the string _SRC at index _SI to the string
262    _DST at index _DI.  _SRCEND is a pointer to the end of _SRC. */
263 #if defined (HANDLE_MULTIBYTE)
264 #  define COPY_CHAR_I(_dst, _di, _src, _srcend, _si) \
265     do \
266       { \
267         if (MB_CUR_MAX > 1) \
268           { \
269             mbstate_t state_bak; \
270             size_t mblength; \
271             int _k; \
272 \
273             state_bak = state; \
274             mblength = mbrlen ((_src) + (_si), (_srcend) - ((_src)+(_si)), &state); \
275             if (mblength == (size_t)-2 || mblength == (size_t)-1) \
276               { \
277                 state = state_bak; \
278                 mblength = 1; \
279               } \
280             else \
281               mblength = (mblength < 1) ? 1 : mblength; \
282 \
283             for (_k = 0; _k < mblength; _k++) \
284               _dst[_di++] = _src[_si++]; \
285           } \
286         else \
287           _dst[_di++] = _src[_si++]; \
288       } \
289     while (0)
290 #else
291 #  define COPY_CHAR_I(_dst, _di, _src, _srcend, _si)    _dst[_di++] = _src[_si++]
292 #endif  /* !HANDLE_MULTIBYTE */
293
294 /****************************************************************
295  *                                                              *
296  * The following are only guaranteed to work in subst.c         *
297  *                                                              *
298  ****************************************************************/
299
300 #if defined (HANDLE_MULTIBYTE)
301 #  define SCOPY_CHAR_I(_dst, _escchar, _sc, _src, _si, _slen) \
302     do \
303       { \
304         if (MB_CUR_MAX > 1) \
305           { \
306             mbstate_t state_bak; \
307             size_t mblength; \
308             int _i; \
309 \
310             state_bak = state; \
311             mblength = mbrlen ((_src) + (_si), (_slen) - (_si), &state); \
312             if (mblength == (size_t)-2 || mblength == (size_t)-1) \
313               { \
314                 state = state_bak; \
315                 mblength = 1; \
316               } \
317             else \
318               mblength = (mblength < 1) ? 1 : mblength; \
319 \
320             temp = xmalloc (mblength + 2); \
321             temp[0] = _escchar; \
322             for (_i = 0; _i < mblength; _i++) \
323               temp[_i + 1] = _src[_si++]; \
324             temp[mblength + 1] = '\0'; \
325 \
326             goto add_string; \
327           } \
328         else \
329           { \
330             _dst[0] = _escchar; \
331             _dst[1] = _sc; \
332           } \
333       } \
334     while (0)
335 #else
336 #  define SCOPY_CHAR_I(_dst, _escchar, _sc, _src, _si, _slen) \
337     _dst[0] = _escchar; \
338     _dst[1] = _sc
339 #endif  /* !HANDLE_MULTIBYTE */
340
341 #if defined (HANDLE_MULTIBYTE)
342 #  define SCOPY_CHAR_M(_dst, _src, _srcend, _si) \
343     do \
344       { \
345         if (MB_CUR_MAX > 1) \
346           { \
347             mbstate_t state_bak; \
348             size_t mblength; \
349 \
350             state_bak = state; \
351             mblength = mbrlen ((_src) + (_si), (_srcend) - ((_src) + (_si)), &state); \
352             if (mblength == (size_t)-2 || mblength == (size_t)-1) \
353               { \
354                 state = state_bak; \
355                 mblength = 1; \
356               } \
357             else \
358               mblength = (mblength < 1) ? 1 : mblength; \
359 \
360             FASTCOPY(((_src) + (_si)), (_dst), mblength); \
361 \
362             (_dst) += mblength; \
363             (_si) += mblength; \
364           } \
365         else \
366           { \
367             *(_dst)++ = _src[(_si)]; \
368             (_si)++; \
369           } \
370       } \
371     while (0)
372 #else
373 #  define SCOPY_CHAR_M(_dst, _src, _srcend, _si) \
374         *(_dst)++ = _src[(_si)]; \
375         (_si)++
376 #endif  /* !HANDLE_MULTIBYTE */
377
378 #if HANDLE_MULTIBYTE
379 #  define SADD_MBCHAR(_dst, _src, _si, _srcsize) \
380     do \
381       { \
382         if (MB_CUR_MAX > 1) \
383           { \
384             int i; \
385             mbstate_t state_bak; \
386             size_t mblength; \
387 \
388             state_bak = state; \
389             mblength = mbrlen ((_src) + (_si), (_srcsize) - (_si), &state); \
390             if (mblength == (size_t)-1 || mblength == (size_t)-2) \
391               { \
392                 state = state_bak; \
393                 mblength = 1; \
394               } \
395             if (mblength < 1) \
396               mblength = 1; \
397 \
398             _dst = (char *)xmalloc (mblength + 1); \
399             for (i = 0; i < mblength; i++) \
400               (_dst)[i] = (_src)[(_si)++]; \
401             (_dst)[mblength] = '\0'; \
402 \
403             goto add_string; \
404           } \
405       } \
406     while (0)
407
408 #else
409 #  define SADD_MBCHAR(_dst, _src, _si, _srcsize)
410 #endif
411
412 /* Watch out when using this -- it's just straight textual subsitution */
413 #if defined (HANDLE_MULTIBYTE)
414 #  define SADD_MBQCHAR_BODY(_dst, _src, _si, _srcsize) \
415 \
416             int i; \
417             mbstate_t state_bak; \
418             size_t mblength; \
419 \
420             state_bak = state; \
421             mblength = mbrlen ((_src) + (_si), (_srcsize) - (_si), &state); \
422             if (mblength == (size_t)-1 || mblength == (size_t)-2) \
423               { \
424                 state = state_bak; \
425                 mblength = 1; \
426               } \
427             if (mblength < 1) \
428               mblength = 1; \
429 \
430             (_dst) = (char *)xmalloc (mblength + 2); \
431             (_dst)[0] = CTLESC; \
432             for (i = 0; i < mblength; i++) \
433               (_dst)[i+1] = (_src)[(_si)++]; \
434             (_dst)[mblength+1] = '\0'; \
435 \
436             goto add_string
437
438 #endif /* HANDLE_MULTIBYTE */
439 #endif /* _SH_MBUTIL_H_ */