]> git.ipfire.org Git - thirdparty/bash.git/blob - include/shmbutil.h
Bash-4.2 distribution sources and documentation
[thirdparty/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_ */