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