blob: 975046be4b61fcbd83726c38ebf8f1d87098ea30 [file] [log] [blame]
Jari Aalto7117c2d2002-07-17 14:10:11 +00001/* shmbutil.h -- utility functions for multibyte characters. */
2
Jari Aaltob80f6442004-07-27 13:29:18 +00003/* Copyright (C) 2002-2004 Free Software Foundation, Inc.
Jari Aalto7117c2d2002-07-17 14:10:11 +00004
5 This file is part of GNU Bash, the Bourne Again SHell.
6
Jari Aalto31859422009-01-12 13:36:28 +00007 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.
Jari Aalto7117c2d2002-07-17 14:10:11 +000011
Jari Aalto31859422009-01-12 13:36:28 +000012 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.
Jari Aalto7117c2d2002-07-17 14:10:11 +000016
Jari Aalto31859422009-01-12 13:36:28 +000017 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*/
Jari Aalto7117c2d2002-07-17 14:10:11 +000020
21#if !defined (_SH_MBUTIL_H_)
22#define _SH_MBUTIL_H_
23
24#include "stdc.h"
25
Jari Aaltob80f6442004-07-27 13:29:18 +000026/* Include config.h for HANDLE_MULTIBYTE */
27#include <config.h>
Jari Aalto7117c2d2002-07-17 14:10:11 +000028
29#if defined (HANDLE_MULTIBYTE)
Chet Ramey495aee42011-11-22 19:11:26 -050030#include "shmbchar.h"
Jari Aalto7117c2d2002-07-17 14:10:11 +000031
32extern size_t xmbsrtowcs __P((wchar_t *, const char **, size_t, mbstate_t *));
Jari Aaltob80f6442004-07-27 13:29:18 +000033extern size_t xdupmbstowcs __P((wchar_t **, char ***, const char *));
Jari Aalto7117c2d2002-07-17 14:10:11 +000034
Jari Aaltoeb873672004-11-09 21:37:25 +000035extern size_t mbstrlen __P((const char *));
36
Jari Aalto7117c2d2002-07-17 14:10:11 +000037extern char *xstrchr __P((const char *, int));
38
Chet Rameyac50fba2014-02-26 09:36:43 -050039extern int locale_mb_cur_max; /* XXX */
40
Jari Aaltob80f6442004-07-27 13:29:18 +000041#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
Jari Aaltoeb873672004-11-09 21:37:25 +000046#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
Ricardo Cerqueiraafce3192014-11-08 16:24:46 +000049#ifdef __BIONIC__
50#define MBLEN(s, n) ((MB_CUR_MAX > 1) ? mbtowc((wchar_t *)0, (s), (n)) : 1)
51#else
Jari Aalto95732b42005-12-07 14:08:12 +000052#define MBLEN(s, n) ((MB_CUR_MAX > 1) ? mblen ((s), (n)) : 1)
Ricardo Cerqueiraafce3192014-11-08 16:24:46 +000053#endif
Jari Aalto95732b42005-12-07 14:08:12 +000054#define MBRLEN(s, n, p) ((MB_CUR_MAX > 1) ? mbrlen ((s), (n), (p)) : 1)
55
Jari Aalto7117c2d2002-07-17 14:10:11 +000056#else /* !HANDLE_MULTIBYTE */
57
58#undef MB_LEN_MAX
59#undef MB_CUR_MAX
60
61#define MB_LEN_MAX 1
62#define MB_CUR_MAX 1
63
64#undef xstrchr
65#define xstrchr(s, c) strchr(s, c)
66
Jari Aaltob80f6442004-07-27 13:29:18 +000067#ifndef MB_INVALIDCH
68#define MB_INVALIDCH(x) (0)
69#define MB_NULLWCH(x) (0)
70#endif
71
Jari Aaltoeb873672004-11-09 21:37:25 +000072#define MB_STRLEN(s) (STRLEN(s))
73
Jari Aalto95732b42005-12-07 14:08:12 +000074#define MBLEN(s, n) 1
75#define MBRLEN(s, n, p) 1
76
Jari Aalto31859422009-01-12 13:36:28 +000077#ifndef wchar_t
78# define wchar_t int
79#endif
80
Jari Aalto7117c2d2002-07-17 14:10:11 +000081#endif /* !HANDLE_MULTIBYTE */
82
83/* Declare and initialize a multibyte state. Call must be terminated
84 with `;'. */
85#if defined (HANDLE_MULTIBYTE)
86# define DECLARE_MBSTATE \
87 mbstate_t state; \
88 memset (&state, '\0', sizeof (mbstate_t))
89#else
90# define DECLARE_MBSTATE
91#endif /* !HANDLE_MULTIBYTE */
92
93/* Initialize or reinitialize a multibyte state named `state'. Call must be
94 terminated with `;'. */
95#if defined (HANDLE_MULTIBYTE)
96# define INITIALIZE_MBSTATE memset (&state, '\0', sizeof (mbstate_t))
97#else
98# define INITIALIZE_MBSTATE
99#endif /* !HANDLE_MULTIBYTE */
100
101/* Advance one (possibly multi-byte) character in string _STR of length
102 _STRSIZE, starting at index _I. STATE must have already been declared. */
103#if defined (HANDLE_MULTIBYTE)
104# define ADVANCE_CHAR(_str, _strsize, _i) \
105 do \
106 { \
Chet Rameyac50fba2014-02-26 09:36:43 -0500107 if (locale_mb_cur_max > 1) \
Jari Aalto7117c2d2002-07-17 14:10:11 +0000108 { \
109 mbstate_t state_bak; \
110 size_t mblength; \
Chet Ramey495aee42011-11-22 19:11:26 -0500111 int _f; \
Jari Aalto7117c2d2002-07-17 14:10:11 +0000112\
Chet Ramey495aee42011-11-22 19:11:26 -0500113 _f = is_basic ((_str)[_i]); \
114 if (_f) \
115 mblength = 1; \
116 else \
117 { \
118 state_bak = state; \
119 mblength = mbrlen ((_str) + (_i), (_strsize) - (_i), &state); \
120 } \
Jari Aalto7117c2d2002-07-17 14:10:11 +0000121\
122 if (mblength == (size_t)-2 || mblength == (size_t)-1) \
123 { \
124 state = state_bak; \
125 (_i)++; \
126 } \
Jari Aaltob80f6442004-07-27 13:29:18 +0000127 else if (mblength == 0) \
128 (_i)++; \
Jari Aalto7117c2d2002-07-17 14:10:11 +0000129 else \
130 (_i) += mblength; \
131 } \
132 else \
133 (_i)++; \
134 } \
135 while (0)
136#else
137# define ADVANCE_CHAR(_str, _strsize, _i) (_i)++
138#endif /* !HANDLE_MULTIBYTE */
139
140/* Advance one (possibly multibyte) character in the string _STR of length
141 _STRSIZE.
142 SPECIAL: assume that _STR will be incremented by 1 after this call. */
143#if defined (HANDLE_MULTIBYTE)
144# define ADVANCE_CHAR_P(_str, _strsize) \
145 do \
146 { \
Chet Rameyac50fba2014-02-26 09:36:43 -0500147 if (locale_mb_cur_max > 1) \
Jari Aalto7117c2d2002-07-17 14:10:11 +0000148 { \
149 mbstate_t state_bak; \
150 size_t mblength; \
Chet Ramey495aee42011-11-22 19:11:26 -0500151 int _f; \
Jari Aalto7117c2d2002-07-17 14:10:11 +0000152\
Chet Ramey495aee42011-11-22 19:11:26 -0500153 _f = is_basic (*(_str)); \
154 if (_f) \
155 mblength = 1; \
156 else \
157 { \
158 state_bak = state; \
159 mblength = mbrlen ((_str), (_strsize), &state); \
160 } \
Jari Aalto7117c2d2002-07-17 14:10:11 +0000161\
162 if (mblength == (size_t)-2 || mblength == (size_t)-1) \
163 { \
164 state = state_bak; \
165 mblength = 1; \
166 } \
167 else \
168 (_str) += (mblength < 1) ? 0 : (mblength - 1); \
169 } \
170 } \
171 while (0)
172#else
173# define ADVANCE_CHAR_P(_str, _strsize)
174#endif /* !HANDLE_MULTIBYTE */
175
Jari Aaltob80f6442004-07-27 13:29:18 +0000176/* Back up one (possibly multi-byte) character in string _STR of length
177 _STRSIZE, starting at index _I. STATE must have already been declared. */
178#if defined (HANDLE_MULTIBYTE)
179# define BACKUP_CHAR(_str, _strsize, _i) \
180 do \
181 { \
Chet Rameyac50fba2014-02-26 09:36:43 -0500182 if (locale_mb_cur_max > 1) \
Jari Aaltob80f6442004-07-27 13:29:18 +0000183 { \
184 mbstate_t state_bak; \
185 size_t mblength; \
186 int _x, _p; /* _x == temp index into string, _p == prev index */ \
187\
188 _x = _p = 0; \
189 while (_x < (_i)) \
190 { \
191 state_bak = state; \
192 mblength = mbrlen ((_str) + (_x), (_strsize) - (_x), &state); \
193\
194 if (mblength == (size_t)-2 || mblength == (size_t)-1) \
195 { \
196 state = state_bak; \
197 _x++; \
198 } \
199 else if (mblength == 0) \
200 _x++; \
201 else \
202 { \
203 _p = _x; /* _p == start of prev mbchar */ \
204 _x += mblength; \
205 } \
206 } \
207 (_i) = _p; \
208 } \
209 else \
210 (_i)--; \
211 } \
212 while (0)
213#else
214# define BACKUP_CHAR(_str, _strsize, _i) (_i)--
215#endif /* !HANDLE_MULTIBYTE */
216
217/* Back up one (possibly multibyte) character in the string _BASE of length
218 _STRSIZE starting at _STR (_BASE <= _STR <= (_BASE + _STRSIZE) ).
219 SPECIAL: DO NOT assume that _STR will be decremented by 1 after this call. */
220#if defined (HANDLE_MULTIBYTE)
221# define BACKUP_CHAR_P(_base, _strsize, _str) \
222 do \
223 { \
Chet Rameyac50fba2014-02-26 09:36:43 -0500224 if (locale_mb_cur_max > 1) \
Jari Aaltob80f6442004-07-27 13:29:18 +0000225 { \
226 mbstate_t state_bak; \
227 size_t mblength; \
228 char *_x, _p; /* _x == temp pointer into string, _p == prev pointer */ \
229\
230 _x = _p = _base; \
231 while (_x < (_str)) \
232 { \
233 state_bak = state; \
234 mblength = mbrlen (_x, (_strsize) - _x, &state); \
235\
236 if (mblength == (size_t)-2 || mblength == (size_t)-1) \
237 { \
238 state = state_bak; \
239 _x++; \
240 } \
241 else if (mblength == 0) \
242 _x++; \
243 else \
244 { \
245 _p = _x; /* _p == start of prev mbchar */ \
246 _x += mblength; \
247 } \
248 } \
249 (_str) = _p; \
250 } \
251 else \
252 (_str)--; \
253 } \
254 while (0)
255#else
256# define BACKUP_CHAR_P(_base, _strsize, _str) (_str)--
257#endif /* !HANDLE_MULTIBYTE */
258
Jari Aalto7117c2d2002-07-17 14:10:11 +0000259/* Copy a single character from the string _SRC to the string _DST.
260 _SRCEND is a pointer to the end of _SRC. */
261#if defined (HANDLE_MULTIBYTE)
262# define COPY_CHAR_P(_dst, _src, _srcend) \
263 do \
264 { \
Chet Rameyac50fba2014-02-26 09:36:43 -0500265 if (locale_mb_cur_max > 1) \
Jari Aalto7117c2d2002-07-17 14:10:11 +0000266 { \
267 mbstate_t state_bak; \
268 size_t mblength; \
269 int _k; \
270\
Chet Ramey495aee42011-11-22 19:11:26 -0500271 _k = is_basic (*(_src)); \
272 if (_k) \
273 mblength = 1; \
274 else \
275 { \
276 state_bak = state; \
277 mblength = mbrlen ((_src), (_srcend) - (_src), &state); \
278 } \
Jari Aalto7117c2d2002-07-17 14:10:11 +0000279 if (mblength == (size_t)-2 || mblength == (size_t)-1) \
280 { \
281 state = state_bak; \
282 mblength = 1; \
283 } \
284 else \
285 mblength = (mblength < 1) ? 1 : mblength; \
286\
287 for (_k = 0; _k < mblength; _k++) \
288 *(_dst)++ = *(_src)++; \
289 } \
290 else \
291 *(_dst)++ = *(_src)++; \
292 } \
293 while (0)
294#else
295# define COPY_CHAR_P(_dst, _src, _srcend) *(_dst)++ = *(_src)++
296#endif /* !HANDLE_MULTIBYTE */
297
298/* Copy a single character from the string _SRC at index _SI to the string
299 _DST at index _DI. _SRCEND is a pointer to the end of _SRC. */
300#if defined (HANDLE_MULTIBYTE)
301# define COPY_CHAR_I(_dst, _di, _src, _srcend, _si) \
302 do \
303 { \
Chet Rameyac50fba2014-02-26 09:36:43 -0500304 if (locale_mb_cur_max > 1) \
Jari Aalto7117c2d2002-07-17 14:10:11 +0000305 { \
306 mbstate_t state_bak; \
307 size_t mblength; \
308 int _k; \
309\
Chet Ramey495aee42011-11-22 19:11:26 -0500310 _k = is_basic (*((_src) + (_si))); \
311 if (_k) \
312 mblength = 1; \
313 else \
314 {\
315 state_bak = state; \
316 mblength = mbrlen ((_src) + (_si), (_srcend) - ((_src)+(_si)), &state); \
317 } \
Jari Aalto7117c2d2002-07-17 14:10:11 +0000318 if (mblength == (size_t)-2 || mblength == (size_t)-1) \
319 { \
320 state = state_bak; \
321 mblength = 1; \
322 } \
323 else \
324 mblength = (mblength < 1) ? 1 : mblength; \
325\
326 for (_k = 0; _k < mblength; _k++) \
327 _dst[_di++] = _src[_si++]; \
328 } \
329 else \
330 _dst[_di++] = _src[_si++]; \
331 } \
332 while (0)
333#else
334# define COPY_CHAR_I(_dst, _di, _src, _srcend, _si) _dst[_di++] = _src[_si++]
335#endif /* !HANDLE_MULTIBYTE */
336
337/****************************************************************
338 * *
339 * The following are only guaranteed to work in subst.c *
340 * *
341 ****************************************************************/
342
343#if defined (HANDLE_MULTIBYTE)
344# define SCOPY_CHAR_I(_dst, _escchar, _sc, _src, _si, _slen) \
345 do \
346 { \
Chet Rameyac50fba2014-02-26 09:36:43 -0500347 if (locale_mb_cur_max > 1) \
Jari Aalto7117c2d2002-07-17 14:10:11 +0000348 { \
349 mbstate_t state_bak; \
350 size_t mblength; \
351 int _i; \
352\
Chet Ramey495aee42011-11-22 19:11:26 -0500353 _i = is_basic (*((_src) + (_si))); \
354 if (_i) \
355 mblength = 1; \
356 else \
357 { \
358 state_bak = state; \
359 mblength = mbrlen ((_src) + (_si), (_slen) - (_si), &state); \
360 } \
Jari Aalto7117c2d2002-07-17 14:10:11 +0000361 if (mblength == (size_t)-2 || mblength == (size_t)-1) \
362 { \
363 state = state_bak; \
364 mblength = 1; \
365 } \
366 else \
367 mblength = (mblength < 1) ? 1 : mblength; \
368\
369 temp = xmalloc (mblength + 2); \
370 temp[0] = _escchar; \
371 for (_i = 0; _i < mblength; _i++) \
372 temp[_i + 1] = _src[_si++]; \
373 temp[mblength + 1] = '\0'; \
374\
375 goto add_string; \
376 } \
377 else \
378 { \
379 _dst[0] = _escchar; \
380 _dst[1] = _sc; \
381 } \
382 } \
383 while (0)
384#else
385# define SCOPY_CHAR_I(_dst, _escchar, _sc, _src, _si, _slen) \
386 _dst[0] = _escchar; \
387 _dst[1] = _sc
388#endif /* !HANDLE_MULTIBYTE */
389
390#if defined (HANDLE_MULTIBYTE)
391# define SCOPY_CHAR_M(_dst, _src, _srcend, _si) \
392 do \
393 { \
Chet Rameyac50fba2014-02-26 09:36:43 -0500394 if (locale_mb_cur_max > 1) \
Jari Aalto7117c2d2002-07-17 14:10:11 +0000395 { \
396 mbstate_t state_bak; \
397 size_t mblength; \
Chet Ramey495aee42011-11-22 19:11:26 -0500398 int _i; \
Jari Aalto7117c2d2002-07-17 14:10:11 +0000399\
Chet Ramey495aee42011-11-22 19:11:26 -0500400 _i = is_basic (*((_src) + (_si))); \
401 if (_i) \
402 mblength = 1; \
403 else \
404 { \
405 state_bak = state; \
406 mblength = mbrlen ((_src) + (_si), (_srcend) - ((_src) + (_si)), &state); \
407 } \
Jari Aalto7117c2d2002-07-17 14:10:11 +0000408 if (mblength == (size_t)-2 || mblength == (size_t)-1) \
409 { \
410 state = state_bak; \
411 mblength = 1; \
412 } \
413 else \
414 mblength = (mblength < 1) ? 1 : mblength; \
415\
416 FASTCOPY(((_src) + (_si)), (_dst), mblength); \
417\
418 (_dst) += mblength; \
419 (_si) += mblength; \
420 } \
421 else \
422 { \
423 *(_dst)++ = _src[(_si)]; \
424 (_si)++; \
425 } \
426 } \
427 while (0)
428#else
429# define SCOPY_CHAR_M(_dst, _src, _srcend, _si) \
430 *(_dst)++ = _src[(_si)]; \
431 (_si)++
432#endif /* !HANDLE_MULTIBYTE */
433
434#if HANDLE_MULTIBYTE
435# define SADD_MBCHAR(_dst, _src, _si, _srcsize) \
436 do \
437 { \
Chet Rameyac50fba2014-02-26 09:36:43 -0500438 if (locale_mb_cur_max > 1) \
Jari Aalto7117c2d2002-07-17 14:10:11 +0000439 { \
440 int i; \
441 mbstate_t state_bak; \
442 size_t mblength; \
443\
Chet Ramey495aee42011-11-22 19:11:26 -0500444 i = is_basic (*((_src) + (_si))); \
445 if (i) \
446 mblength = 1; \
447 else \
448 { \
449 state_bak = state; \
450 mblength = mbrlen ((_src) + (_si), (_srcsize) - (_si), &state); \
451 } \
Jari Aalto7117c2d2002-07-17 14:10:11 +0000452 if (mblength == (size_t)-1 || mblength == (size_t)-2) \
453 { \
454 state = state_bak; \
455 mblength = 1; \
456 } \
457 if (mblength < 1) \
458 mblength = 1; \
459\
460 _dst = (char *)xmalloc (mblength + 1); \
461 for (i = 0; i < mblength; i++) \
462 (_dst)[i] = (_src)[(_si)++]; \
463 (_dst)[mblength] = '\0'; \
464\
465 goto add_string; \
466 } \
467 } \
468 while (0)
469
470#else
471# define SADD_MBCHAR(_dst, _src, _si, _srcsize)
472#endif
473
Chet Rameyac50fba2014-02-26 09:36:43 -0500474/* Watch out when using this -- it's just straight textual substitution */
Jari Aaltob80f6442004-07-27 13:29:18 +0000475#if defined (HANDLE_MULTIBYTE)
476# define SADD_MBQCHAR_BODY(_dst, _src, _si, _srcsize) \
477\
478 int i; \
479 mbstate_t state_bak; \
480 size_t mblength; \
481\
Chet Ramey495aee42011-11-22 19:11:26 -0500482 i = is_basic (*((_src) + (_si))); \
483 if (i) \
484 mblength = 1; \
485 else \
486 { \
487 state_bak = state; \
488 mblength = mbrlen ((_src) + (_si), (_srcsize) - (_si), &state); \
489 } \
Jari Aaltob80f6442004-07-27 13:29:18 +0000490 if (mblength == (size_t)-1 || mblength == (size_t)-2) \
491 { \
492 state = state_bak; \
493 mblength = 1; \
494 } \
495 if (mblength < 1) \
496 mblength = 1; \
497\
498 (_dst) = (char *)xmalloc (mblength + 2); \
499 (_dst)[0] = CTLESC; \
500 for (i = 0; i < mblength; i++) \
501 (_dst)[i+1] = (_src)[(_si)++]; \
502 (_dst)[mblength+1] = '\0'; \
503\
504 goto add_string
505
506#endif /* HANDLE_MULTIBYTE */
Jari Aalto7117c2d2002-07-17 14:10:11 +0000507#endif /* _SH_MBUTIL_H_ */