]>
Commit | Line | Data |
---|---|---|
7117c2d2 JA |
1 | /* shmbutil.h -- utility functions for multibyte characters. */ |
2 | ||
b80f6443 | 3 | /* Copyright (C) 2002-2004 Free Software Foundation, Inc. |
7117c2d2 JA |
4 | |
5 | This file is part of GNU Bash, the Bourne Again SHell. | |
6 | ||
3185942a JA |
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 | */ | |
7117c2d2 JA |
20 | |
21 | #if !defined (_SH_MBUTIL_H_) | |
22 | #define _SH_MBUTIL_H_ | |
23 | ||
24 | #include "stdc.h" | |
25 | ||
b80f6443 JA |
26 | /* Include config.h for HANDLE_MULTIBYTE */ |
27 | #include <config.h> | |
7117c2d2 JA |
28 | |
29 | #if defined (HANDLE_MULTIBYTE) | |
495aee44 | 30 | #include "shmbchar.h" |
7117c2d2 JA |
31 | |
32 | extern size_t xmbsrtowcs __P((wchar_t *, const char **, size_t, mbstate_t *)); | |
b80f6443 | 33 | extern size_t xdupmbstowcs __P((wchar_t **, char ***, const char *)); |
7117c2d2 | 34 | |
eb873671 JA |
35 | extern size_t mbstrlen __P((const char *)); |
36 | ||
7117c2d2 JA |
37 | extern char *xstrchr __P((const char *, int)); |
38 | ||
ac50fbac CR |
39 | extern int locale_mb_cur_max; /* XXX */ |
40 | ||
b80f6443 JA |
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 | ||
eb873671 JA |
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 | ||
95732b49 JA |
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 | ||
7117c2d2 JA |
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 | ||
b80f6443 JA |
63 | #ifndef MB_INVALIDCH |
64 | #define MB_INVALIDCH(x) (0) | |
65 | #define MB_NULLWCH(x) (0) | |
66 | #endif | |
67 | ||
eb873671 JA |
68 | #define MB_STRLEN(s) (STRLEN(s)) |
69 | ||
95732b49 JA |
70 | #define MBLEN(s, n) 1 |
71 | #define MBRLEN(s, n, p) 1 | |
72 | ||
3185942a JA |
73 | #ifndef wchar_t |
74 | # define wchar_t int | |
75 | #endif | |
76 | ||
7117c2d2 JA |
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 | { \ | |
ac50fbac | 103 | if (locale_mb_cur_max > 1) \ |
7117c2d2 JA |
104 | { \ |
105 | mbstate_t state_bak; \ | |
106 | size_t mblength; \ | |
495aee44 | 107 | int _f; \ |
7117c2d2 | 108 | \ |
495aee44 CR |
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 | } \ | |
7117c2d2 JA |
117 | \ |
118 | if (mblength == (size_t)-2 || mblength == (size_t)-1) \ | |
119 | { \ | |
120 | state = state_bak; \ | |
121 | (_i)++; \ | |
122 | } \ | |
b80f6443 JA |
123 | else if (mblength == 0) \ |
124 | (_i)++; \ | |
7117c2d2 JA |
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 | { \ | |
ac50fbac | 143 | if (locale_mb_cur_max > 1) \ |
7117c2d2 JA |
144 | { \ |
145 | mbstate_t state_bak; \ | |
146 | size_t mblength; \ | |
495aee44 | 147 | int _f; \ |
7117c2d2 | 148 | \ |
495aee44 CR |
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 | } \ | |
7117c2d2 JA |
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 | ||
b80f6443 JA |
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 | { \ | |
ac50fbac | 178 | if (locale_mb_cur_max > 1) \ |
b80f6443 JA |
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 | { \ | |
ac50fbac | 220 | if (locale_mb_cur_max > 1) \ |
b80f6443 JA |
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 | ||
7117c2d2 JA |
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 | { \ | |
ac50fbac | 261 | if (locale_mb_cur_max > 1) \ |
7117c2d2 JA |
262 | { \ |
263 | mbstate_t state_bak; \ | |
264 | size_t mblength; \ | |
265 | int _k; \ | |
266 | \ | |
495aee44 CR |
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 | } \ | |
7117c2d2 JA |
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 | { \ | |
ac50fbac | 300 | if (locale_mb_cur_max > 1) \ |
7117c2d2 JA |
301 | { \ |
302 | mbstate_t state_bak; \ | |
303 | size_t mblength; \ | |
304 | int _k; \ | |
305 | \ | |
495aee44 CR |
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 | } \ | |
7117c2d2 JA |
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 | { \ | |
ac50fbac | 343 | if (locale_mb_cur_max > 1) \ |
7117c2d2 JA |
344 | { \ |
345 | mbstate_t state_bak; \ | |
346 | size_t mblength; \ | |
347 | int _i; \ | |
348 | \ | |
495aee44 CR |
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 | } \ | |
7117c2d2 JA |
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 | { \ | |
ac50fbac | 390 | if (locale_mb_cur_max > 1) \ |
7117c2d2 JA |
391 | { \ |
392 | mbstate_t state_bak; \ | |
393 | size_t mblength; \ | |
495aee44 | 394 | int _i; \ |
7117c2d2 | 395 | \ |
495aee44 CR |
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 | } \ | |
7117c2d2 JA |
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 | { \ | |
ac50fbac | 434 | if (locale_mb_cur_max > 1) \ |
7117c2d2 JA |
435 | { \ |
436 | int i; \ | |
437 | mbstate_t state_bak; \ | |
438 | size_t mblength; \ | |
439 | \ | |
495aee44 CR |
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 | } \ | |
7117c2d2 JA |
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 | ||
ac50fbac | 470 | /* Watch out when using this -- it's just straight textual substitution */ |
b80f6443 JA |
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 | \ | |
495aee44 CR |
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 | } \ | |
b80f6443 JA |
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 */ | |
7117c2d2 | 503 | #endif /* _SH_MBUTIL_H_ */ |