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