1 /* $OpenBSD: setlocale.c,v 1.4 2018/03/29 16:34:25 schwarze Exp $ */ 2 /* 3 * Copyright (c) 2015 Sebastien Marie <semarie@openbsd.org> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include <err.h> 19 #include <locale.h> 20 #include <stdlib.h> 21 #include <stdio.h> 22 #include <string.h> 23 #include <ctype.h> 24 25 /* 26 * test helpers for __LINE__ 27 */ 28 #define test_setlocale(_e, _c, _l) _test_setlocale(_e, _c, _l, __LINE__) 29 #define test_MB_CUR_MAX(_e) _test_MB_CUR_MAX(_e, __LINE__) 30 #define test_isalpha(_e, _c) _test_isalpha(_e, _c, __LINE__) 31 32 33 static void 34 _test_setlocale(char *expected, int category, char *locale, int line) 35 { 36 char *result = setlocale(category, locale); 37 38 if ((expected == NULL) || (result == NULL)) { 39 if (expected == result) 40 return; 41 42 errx(1, "[%d] setlocale(%d, \"%s\")=\"%s\" [expected: \"%s\"]", 43 line, category, locale, result, expected); 44 } 45 46 if (strcmp(expected, result) != 0) 47 errx(1, "[%d] setlocale(%d, \"%s\")=\"%s\" [expected: \"%s\"]", 48 line, category, locale, result, expected); 49 } 50 51 static void 52 _test_MB_CUR_MAX(size_t expected, int line) 53 { 54 if (MB_CUR_MAX != expected) 55 errx(1, "[%d] MB_CUR_MAX=%ld [expected %ld]", 56 line, MB_CUR_MAX, expected); 57 } 58 59 static void 60 _test_isalpha(int expected, int c, int line) 61 { 62 int result = isalpha(c); 63 if (!!result != expected) 64 errx(1, "[%d] isalpha(%d)=%d [expected %d]", 65 line, c, result, expected); 66 } 67 68 int 69 main(int argc, char *argv[]) 70 { 71 /* check initial state (should be "C") */ 72 test_setlocale("C", LC_ALL, NULL); /* check */ 73 test_MB_CUR_MAX(1); 74 test_isalpha(0, 0xe9); /* iso-8859-1 eacute */ 75 76 /* load from env */ 77 /* NOTE: we don't support non-C locales for some categories */ 78 test_setlocale("fr_FR.UTF-8", LC_CTYPE, ""); /* set */ 79 test_setlocale("fr_FR.UTF-8", LC_MESSAGES, ""); /* set */ 80 test_MB_CUR_MAX(4); 81 test_isalpha(0, 0xe9); /* iso-8859-1 eacute */ 82 83 test_setlocale("C", LC_MESSAGES, "C"); /* set */ 84 test_MB_CUR_MAX(4); 85 test_setlocale("C/fr_FR.UTF-8/C/C/C/C", LC_ALL, NULL); /* check */ 86 87 test_setlocale("C", LC_CTYPE, "C"); /* set */ 88 test_MB_CUR_MAX(1); 89 test_setlocale("C", LC_ALL, NULL); /* check */ 90 91 /* check for errors on checking */ 92 test_setlocale("C", LC_ALL, "C"); /* reset */ 93 test_setlocale(NULL, -1, NULL); 94 test_setlocale(NULL, _LC_LAST, NULL); 95 test_setlocale(NULL, _LC_LAST+0xff, NULL); 96 test_setlocale("C", LC_ALL, NULL); /* check */ 97 98 /* check for errors on setting */ 99 test_setlocale(NULL, -1, ""); 100 test_setlocale(NULL, _LC_LAST, ""); 101 test_setlocale(NULL, _LC_LAST+0xff, ""); 102 test_setlocale("C", LC_ALL, NULL); /* check */ 103 104 /* no codeset, fallback to ASCII */ 105 test_setlocale("C", LC_ALL, "C"); /* reset */ 106 test_setlocale("invalid", LC_CTYPE, "invalid"); /* set */ 107 test_setlocale("invalid", LC_CTYPE, NULL); 108 test_MB_CUR_MAX(1); 109 test_isalpha(0, 0xe9); /* iso-8859-1 eacute */ 110 111 /* with codeset */ 112 test_setlocale("C", LC_ALL, "C"); /* reset */ 113 test_setlocale("invalid.UTF-8", LC_CTYPE, "invalid.UTF-8"); /* set */ 114 test_setlocale("invalid.UTF-8", LC_CTYPE, NULL); 115 test_setlocale("C/invalid.UTF-8/C/C/C/C", LC_ALL, NULL); 116 test_MB_CUR_MAX(4); 117 118 /* with invalid codeset (is an error) */ 119 test_setlocale("C", LC_ALL, "C"); /* reset */ 120 test_setlocale(NULL, LC_CTYPE, "fr_FR.invalid"); /* set */ 121 test_setlocale("C", LC_CTYPE, NULL); 122 test_MB_CUR_MAX(1); 123 124 return (EXIT_SUCCESS); 125 } 126