1 /* 2 * Copyright (c) 2016 Ingo Schwarze <schwarze@openbsd.org> 3 * 4 * Permission to use, copy, modify, and distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17 #include <sys/types.h> 18 #include <err.h> 19 #include <errno.h> 20 #include <limits.h> 21 #include <locale.h> 22 #include <stdlib.h> 23 #include <string.h> 24 #include <wchar.h> 25 26 static mbstate_t mbs; 27 28 void 29 onetest(const char *name, const wchar_t wcin, int outerr, const char *out) 30 { 31 char buf[MB_LEN_MAX]; 32 size_t sz, outsz; 33 34 memset(buf, 0, MB_LEN_MAX); 35 outsz = out == NULL ? (size_t)-1 : *out == '\0' ? 1 : strlen(out); 36 sz = wcrtomb(buf, wcin, &mbs); 37 if (errno != outerr) 38 err(1, "%d %s U+%04X", MB_CUR_MAX, name, wcin); 39 if (sz != outsz || (out != NULL && strncmp(buf, out, sz))) 40 errx(1, "%d %s U+%04X: %4.4s(%zd) != %4.4s(%zd)", 41 MB_CUR_MAX, name, wcin, buf, sz, 42 out == NULL ? "(NULL)" : out, outsz); 43 if (mbsinit(&mbs) == 0) 44 errx(1, "%d %s U+%04X mbsinit", MB_CUR_MAX, name, wcin); 45 if (errno == 0 && outerr == 0) 46 return; 47 errno = 0; 48 memset(&mbs, 0, sizeof(mbs)); 49 } 50 51 int 52 main(void) 53 { 54 onetest("NUL", L'\0', 0, ""); 55 onetest("BEL", L'\a', 0, "\a"); 56 onetest("A", L'A', 0, "A"); 57 onetest("DEL", L'\177', 0, "\177"); 58 onetest("CSI", L'\233', 0, "\233"); 59 onetest("0x100", 0x100, EILSEQ, NULL); 60 61 if (setlocale(LC_CTYPE, "en_US.UTF-8") == NULL) 62 errx(1, "setlocale(UTF-8) failed"), 63 64 onetest("NUL", L'\0', 0, ""); 65 onetest("BEL", L'\a', 0, "\a"); 66 onetest("A", L'A', 0, "A"); 67 onetest("DEL", L'\177', 0, "\177"); 68 onetest("CSI", L'\233', 0, "\302\233"); 69 onetest("0xe9", 0xe9, 0, "\303\251"); 70 onetest("0xcfff", 0xcfff, 0, "\354\277\277"); 71 onetest("0xd800", 0xd800, EILSEQ, NULL); 72 73 if (setlocale(LC_CTYPE, "POSIX") == NULL) 74 errx(1, "setlocale(POSIX) failed"), 75 76 onetest("0xff", L'\377', 0, "\377"); 77 78 if (setlocale(LC_CTYPE, "en_US.UTF-8") == NULL) 79 errx(1, "second setlocale(UTF-8) failed"), 80 81 onetest("U+13000", 0x13000, 0, "\360\223\200\200"); 82 83 return 0; 84 } 85