| xf.li | bdd93d5 | 2023-05-12 07:10:14 -0700 | [diff] [blame] | 1 | /* Copyright (C) 2000-2016 Free Software Foundation, Inc. | 
|  | 2 | This file is part of the GNU C Library. | 
|  | 3 | Contributed by Ulrich Drepper <drepper@redhat.com>, 2000. | 
|  | 4 |  | 
|  | 5 | The GNU C Library is free software; you can redistribute it and/or | 
|  | 6 | modify it under the terms of the GNU Lesser General Public | 
|  | 7 | License as published by the Free Software Foundation; either | 
|  | 8 | version 2.1 of the License, or (at your option) any later version. | 
|  | 9 |  | 
|  | 10 | The GNU C Library is distributed in the hope that it will be useful, | 
|  | 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
|  | 13 | Lesser General Public License for more details. | 
|  | 14 |  | 
|  | 15 | You should have received a copy of the GNU Lesser General Public | 
|  | 16 | License along with the GNU C Library; if not, see | 
|  | 17 | <http://www.gnu.org/licenses/>.  */ | 
|  | 18 |  | 
|  | 19 | /* We always want assert to be fully defined.  */ | 
|  | 20 | #undef NDEBUG | 
|  | 21 | #include <assert.h> | 
|  | 22 | #include <locale.h> | 
|  | 23 | #include <stdio.h> | 
|  | 24 | #include <stdlib.h> | 
|  | 25 | #include <string.h> | 
|  | 26 | #include <wchar.h> | 
|  | 27 |  | 
|  | 28 |  | 
|  | 29 | static int check_ascii (const char *locname); | 
|  | 30 |  | 
|  | 31 | /* UTF-8 single byte feeding test for mbrtowc(), | 
|  | 32 | contributed by Markus Kuhn <mkuhn@acm.org>.  */ | 
|  | 33 | static int | 
|  | 34 | utf8_test_1 (void) | 
|  | 35 | { | 
|  | 36 | wchar_t wc; | 
|  | 37 | mbstate_t s; | 
|  | 38 |  | 
|  | 39 | wc = 42;			/* arbitrary number */ | 
|  | 40 | memset (&s, 0, sizeof (s));	/* get s into initial state */ | 
|  | 41 | assert (mbrtowc (&wc, "\xE2", 1, &s) == (size_t) -2);	/* 1st byte processed */ | 
|  | 42 | assert (mbrtowc (&wc, "\x89", 1, &s) == (size_t) -2);	/* 2nd byte processed */ | 
|  | 43 | assert (wc == 42);		/* no value has not been stored into &wc yet */ | 
|  | 44 | assert (mbrtowc (&wc, "\xA0", 1, &s) == 1);	/* 3nd byte processed */ | 
|  | 45 | assert (wc == 0x2260);	/* E2 89 A0 = U+2260 (not equal) decoded correctly */ | 
|  | 46 | assert (mbrtowc (&wc, "", 1, &s) == 0);	/* test final byte processing */ | 
|  | 47 | assert (wc == 0);		/* test final byte decoding */ | 
|  | 48 |  | 
|  | 49 | /* The following test is by Al Viro <aviro@redhat.com>.  */ | 
|  | 50 | const char str[] = "\xe0\xa0\x80"; | 
|  | 51 |  | 
|  | 52 | wc = 42;			/* arbitrary number */ | 
|  | 53 | memset (&s, 0, sizeof (s));	/* get s into initial state */ | 
|  | 54 | assert (mbrtowc (&wc, str, 1, &s) == -2); | 
|  | 55 | assert (mbrtowc (&wc, str + 1, 2, &s) == 2); | 
|  | 56 | assert (wc == 0x800); | 
|  | 57 |  | 
|  | 58 | wc = 42;			/* arbitrary number */ | 
|  | 59 | memset (&s, 0, sizeof (s));	/* get s into initial state */ | 
|  | 60 | assert (mbrtowc (&wc, str, 3, &s) == 3); | 
|  | 61 | assert (wc == 0x800); | 
|  | 62 |  | 
|  | 63 | return 0; | 
|  | 64 | } | 
|  | 65 |  | 
|  | 66 | /* Test for NUL byte processing via empty string.  */ | 
|  | 67 | static int | 
|  | 68 | utf8_test_2 (void) | 
|  | 69 | { | 
|  | 70 | wchar_t wc; | 
|  | 71 | mbstate_t s; | 
|  | 72 |  | 
|  | 73 | wc = 42;			/* arbitrary number */ | 
|  | 74 | memset (&s, 0, sizeof (s));	/* get s into initial state */ | 
|  | 75 | assert (mbrtowc (NULL, "", 1, &s) == 0); /* valid terminator */ | 
|  | 76 | assert (mbsinit (&s)); | 
|  | 77 |  | 
|  | 78 | wc = 42;			/* arbitrary number */ | 
|  | 79 | memset (&s, 0, sizeof (s));	/* get s into initial state */ | 
|  | 80 | assert (mbrtowc (&wc, "\xE2", 1, &s) == (size_t) -2);	/* 1st byte processed */ | 
|  | 81 | assert (mbrtowc (NULL, "", 1, &s) == (size_t) -1); /* invalid terminator */ | 
|  | 82 |  | 
|  | 83 | wc = 42;			/* arbitrary number */ | 
|  | 84 | memset (&s, 0, sizeof (s));	/* get s into initial state */ | 
|  | 85 | assert (mbrtowc (&wc, "\xE2", 1, &s) == (size_t) -2);	/* 1st byte processed */ | 
|  | 86 | assert (mbrtowc (&wc, "\x89", 1, &s) == (size_t) -2);	/* 2nd byte processed */ | 
|  | 87 | assert (mbrtowc (NULL, "", 1, &s) == (size_t) -1); /* invalid terminator */ | 
|  | 88 |  | 
|  | 89 | wc = 42;			/* arbitrary number */ | 
|  | 90 | memset (&s, 0, sizeof (s));	/* get s into initial state */ | 
|  | 91 | assert (mbrtowc (&wc, "\xE2", 1, &s) == (size_t) -2);	/* 1st byte processed */ | 
|  | 92 | assert (mbrtowc (&wc, "\x89", 1, &s) == (size_t) -2);	/* 2nd byte processed */ | 
|  | 93 | assert (mbrtowc (&wc, "\xA0", 1, &s) == 1);	/* 3nd byte processed */ | 
|  | 94 | assert (mbrtowc (NULL, "", 1, &s) == 0); /* valid terminator */ | 
|  | 95 | assert (mbsinit (&s)); | 
|  | 96 |  | 
|  | 97 | return 0; | 
|  | 98 | } | 
|  | 99 |  | 
|  | 100 | /* Test for NUL byte processing via NULL string.  */ | 
|  | 101 | static int | 
|  | 102 | utf8_test_3 (void) | 
|  | 103 | { | 
|  | 104 | wchar_t wc; | 
|  | 105 | mbstate_t s; | 
|  | 106 |  | 
|  | 107 | wc = 42;			/* arbitrary number */ | 
|  | 108 | memset (&s, 0, sizeof (s));	/* get s into initial state */ | 
|  | 109 | assert (mbrtowc (NULL, NULL, 0, &s) == 0); /* valid terminator */ | 
|  | 110 | assert (mbsinit (&s)); | 
|  | 111 |  | 
|  | 112 | wc = 42;			/* arbitrary number */ | 
|  | 113 | memset (&s, 0, sizeof (s));	/* get s into initial state */ | 
|  | 114 | assert (mbrtowc (&wc, "\xE2", 1, &s) == (size_t) -2);	/* 1st byte processed */ | 
|  | 115 | assert (mbrtowc (NULL, NULL, 0, &s) == (size_t) -1); /* invalid terminator */ | 
|  | 116 |  | 
|  | 117 | wc = 42;			/* arbitrary number */ | 
|  | 118 | memset (&s, 0, sizeof (s));	/* get s into initial state */ | 
|  | 119 | assert (mbrtowc (&wc, "\xE2", 1, &s) == (size_t) -2);	/* 1st byte processed */ | 
|  | 120 | assert (mbrtowc (&wc, "\x89", 1, &s) == (size_t) -2);	/* 2nd byte processed */ | 
|  | 121 | assert (mbrtowc (NULL, NULL, 0, &s) == (size_t) -1); /* invalid terminator */ | 
|  | 122 |  | 
|  | 123 | wc = 42;			/* arbitrary number */ | 
|  | 124 | memset (&s, 0, sizeof (s));	/* get s into initial state */ | 
|  | 125 | assert (mbrtowc (&wc, "\xE2", 1, &s) == (size_t) -2);	/* 1st byte processed */ | 
|  | 126 | assert (mbrtowc (&wc, "\x89", 1, &s) == (size_t) -2);	/* 2nd byte processed */ | 
|  | 127 | assert (mbrtowc (&wc, "\xA0", 1, &s) == 1);	/* 3nd byte processed */ | 
|  | 128 | assert (mbrtowc (NULL, NULL, 0, &s) == 0); /* valid terminator */ | 
|  | 129 | assert (mbsinit (&s)); | 
|  | 130 |  | 
|  | 131 | return 0; | 
|  | 132 | } | 
|  | 133 |  | 
|  | 134 | static int | 
|  | 135 | utf8_test (void) | 
|  | 136 | { | 
|  | 137 | const char *locale = "de_DE.UTF-8"; | 
|  | 138 | int error = 0; | 
|  | 139 |  | 
|  | 140 | if (!setlocale (LC_CTYPE, locale)) | 
|  | 141 | { | 
|  | 142 | fprintf (stderr, "locale '%s' not available!\n", locale); | 
|  | 143 | exit (1); | 
|  | 144 | } | 
|  | 145 |  | 
|  | 146 | error |= utf8_test_1 (); | 
|  | 147 | error |= utf8_test_2 (); | 
|  | 148 | error |= utf8_test_3 (); | 
|  | 149 |  | 
|  | 150 | return error; | 
|  | 151 | } | 
|  | 152 |  | 
|  | 153 |  | 
|  | 154 | static int | 
|  | 155 | do_test (void) | 
|  | 156 | { | 
|  | 157 | int result = 0; | 
|  | 158 |  | 
|  | 159 | /* Check mapping of ASCII range for some character sets which have | 
|  | 160 | ASCII as a subset.  For those the wide char generated must have | 
|  | 161 | the same value.  */ | 
|  | 162 | setlocale (LC_ALL, "C"); | 
|  | 163 | result |= check_ascii (setlocale (LC_ALL, NULL)); | 
|  | 164 |  | 
|  | 165 | setlocale (LC_ALL, "de_DE.UTF-8"); | 
|  | 166 | result |= check_ascii (setlocale (LC_ALL, NULL)); | 
|  | 167 | result |= utf8_test (); | 
|  | 168 |  | 
|  | 169 | setlocale (LC_ALL, "ja_JP.EUC-JP"); | 
|  | 170 | result |= check_ascii (setlocale (LC_ALL, NULL)); | 
|  | 171 |  | 
|  | 172 | return result; | 
|  | 173 | } | 
|  | 174 |  | 
|  | 175 |  | 
|  | 176 | static int | 
|  | 177 | check_ascii (const char *locname) | 
|  | 178 | { | 
|  | 179 | int c; | 
|  | 180 | int res = 0; | 
|  | 181 |  | 
|  | 182 | printf ("Testing locale \"%s\":\n", locname); | 
|  | 183 |  | 
|  | 184 | for (c = 0; c <= 127; ++c) | 
|  | 185 | { | 
|  | 186 | char buf[MB_CUR_MAX]; | 
|  | 187 | wchar_t wc = 0xffffffff; | 
|  | 188 | mbstate_t s; | 
|  | 189 | size_t n, i; | 
|  | 190 |  | 
|  | 191 | for (i = 0; i < MB_CUR_MAX; ++i) | 
|  | 192 | buf[i] = c + i; | 
|  | 193 |  | 
|  | 194 | memset (&s, '\0', sizeof (s)); | 
|  | 195 |  | 
|  | 196 | n = mbrtowc (&wc, buf, MB_CUR_MAX, &s); | 
|  | 197 | if (n == (size_t) -1) | 
|  | 198 | { | 
|  | 199 | printf ("%s: '\\x%x': encoding error\n", locname, c); | 
|  | 200 | ++res; | 
|  | 201 | } | 
|  | 202 | else if (n == (size_t) -2) | 
|  | 203 | { | 
|  | 204 | printf ("%s: '\\x%x': incomplete character\n", locname, c); | 
|  | 205 | ++res; | 
|  | 206 | } | 
|  | 207 | else if (n == 0 && c != 0) | 
|  | 208 | { | 
|  | 209 | printf ("%s: '\\x%x': 0 returned\n", locname, c); | 
|  | 210 | ++res; | 
|  | 211 | } | 
|  | 212 | else if (n != 0 && c == 0) | 
|  | 213 | { | 
|  | 214 | printf ("%s: '\\x%x': not 0 returned\n", locname, c); | 
|  | 215 | ++res; | 
|  | 216 | } | 
|  | 217 | else if (c != 0 && n != 1) | 
|  | 218 | { | 
|  | 219 | printf ("%s: '\\x%x': not 1 returned\n", locname, c); | 
|  | 220 | ++res; | 
|  | 221 | } | 
|  | 222 | else if (wc != (wchar_t) c) | 
|  | 223 | { | 
|  | 224 | printf ("%s: '\\x%x': wc != L'\\x%x'\n", locname, c, c); | 
|  | 225 | ++res; | 
|  | 226 | } | 
|  | 227 | } | 
|  | 228 |  | 
|  | 229 | printf (res == 1 ? "%d error\n" : "%d errors\n", res); | 
|  | 230 |  | 
|  | 231 | return res != 0; | 
|  | 232 | } | 
|  | 233 |  | 
|  | 234 | #define TEST_FUNCTION do_test () | 
|  | 235 | #include "../test-skeleton.c" |