Line data Source code
1 : /* mbschr.c - strchr(3) that handles multibyte characters. */ 2 : 3 : /* Copyright (C) 2002 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 : #include <config.h> 22 : 23 : #ifdef HAVE_STDLIB_H 24 : # include <stdlib.h> 25 : #endif 26 : 27 : #include "bashansi.h" 28 : #include "shmbutil.h" 29 : 30 : extern int locale_mb_cur_max; 31 : 32 : #undef mbschr 33 : 34 : /* In some locales, the non-first byte of some multibyte characters have 35 : the same value as some ascii character. Faced with these strings, a 36 : legacy strchr() might return the wrong value. */ 37 : 38 : char * 39 : #if defined (PROTOTYPES) 40 7210255792 : mbschr (const char *s, int c) 41 : #else 42 : mbschr (s, c) 43 : const char *s; 44 : int c; 45 : #endif 46 : { 47 : #if HANDLE_MULTIBYTE 48 7210255792 : char *pos; 49 7210255792 : mbstate_t state; 50 7210255792 : size_t strlength, mblength; 51 : 52 : /* The locale encodings with said weird property are BIG5, BIG5-HKSCS, 53 : GBK, GB18030, SHIFT_JIS, and JOHAB. They exhibit the problem only 54 : when c >= 0x30. We can therefore use the faster bytewise search if 55 : c <= 0x30. */ 56 7210255792 : if ((unsigned char)c >= '0' && locale_mb_cur_max > 1) 57 : { 58 5932727744 : pos = (char *)s; 59 5932727744 : memset (&state, '\0', sizeof(mbstate_t)); 60 5932727744 : strlength = strlen (s); 61 : 62 63462780293 : while (strlength > 0) 63 : { 64 >11530*10^7 : if (is_basic (*pos)) 65 : mblength = 1; 66 : else 67 : { 68 5630403020 : mblength = mbrlen (pos, strlength, &state); 69 5630403020 : if (mblength == (size_t)-2 || mblength == (size_t)-1 || mblength == (size_t)0) 70 : mblength = 1; 71 : } 72 : 73 57654104676 : if (mblength == 1 && c == (unsigned char)*pos) 74 124052127 : return pos; 75 : 76 57530052549 : strlength -= mblength; 77 57530052549 : pos += mblength; 78 : } 79 : 80 : return ((char *)NULL); 81 : } 82 : else 83 : #endif 84 1277528048 : return (strchr (s, c)); 85 : }