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