1 /* Test locale support, or attempt to do so. 2 3 Copyright 2001, 2002, 2011, 2014, 2020 Free Software Foundation, Inc. 4 5 This file is part of the GNU MP Library test suite. 6 7 The GNU MP Library test suite is free software; you can redistribute it 8 and/or modify it under the terms of the GNU General Public License as 9 published by the Free Software Foundation; either version 3 of the License, 10 or (at your option) any later version. 11 12 The GNU MP Library test suite is distributed in the hope that it will be 13 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 15 Public License for more details. 16 17 You should have received a copy of the GNU General Public License along with 18 the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */ 19 20 #define _GNU_SOURCE /* for DECIMAL_POINT in glibc langinfo.h */ 21 22 #include "config.h" 23 24 #include <stdio.h> 25 #include <stdlib.h> 26 #include <string.h> 27 28 #if HAVE_NL_TYPES_H 29 #include <nl_types.h> /* for nl_item (on netbsd 1.4.1 at least) */ 30 #endif 31 32 #if HAVE_LANGINFO_H 33 #include <langinfo.h> /* for nl_langinfo */ 34 #endif 35 36 #if HAVE_LOCALE_H 37 #include <locale.h> /* for lconv */ 38 #endif 39 40 #include "gmp-impl.h" 41 #include "tests.h" 42 43 const char *decimal_point; 44 45 /* Replace the libc localeconv with one we can manipulate. */ 46 #if HAVE_LOCALECONV && ! defined __MINGW32__ 47 struct lconv * 48 localeconv (void) 49 #if defined __cplusplus && defined __GLIBC__ 50 throw() 51 #endif 52 { 53 static struct lconv l; 54 l.decimal_point = (char *) decimal_point; 55 return &l; 56 } 57 #endif 58 59 /* Replace the libc nl_langinfo with one we can manipulate. */ 60 #if HAVE_NL_LANGINFO && ! defined __TERMUX__ 61 char * 62 nl_langinfo (nl_item n) 63 #if defined __cplusplus && defined __GLIBC__ 64 throw() 65 #endif 66 { 67 #if defined (DECIMAL_POINT) 68 if (n == DECIMAL_POINT) 69 return (char *) decimal_point; 70 #endif 71 #if defined (RADIXCHAR) 72 if (n == RADIXCHAR) 73 return (char *) decimal_point; 74 #endif 75 return (char *) ""; 76 } 77 #endif 78 79 void 80 check_input (void) 81 { 82 static const char *point[] = { 83 ".", ",", "WU", "STR", "ZTV***" 84 }; 85 86 static const struct { 87 const char *str; 88 double d; 89 } data[] = { 90 91 { "1%s", 1.0 }, 92 { "1%s0", 1.0 }, 93 { "1%s00", 1.0 }, 94 95 { "%s5", 0.5 }, 96 { "0%s5", 0.5 }, 97 { "00%s5", 0.5 }, 98 { "00%s50", 0.5 }, 99 100 { "1%s5", 1.5 }, 101 { "1%s5e1", 15.0 }, 102 }; 103 104 int i, j, neg, ret; 105 char str[128]; 106 mpf_t f; 107 double d; 108 109 mpf_init (f); 110 111 for (i = 0; i < numberof (point); i++) 112 { 113 decimal_point = (const char *) point[i]; 114 115 for (neg = 0; neg <= 1; neg++) 116 { 117 for (j = 0; j < numberof (data); j++) 118 { 119 strcpy (str, neg ? "-" : ""); 120 sprintf (str+strlen(str), data[j].str, decimal_point); 121 122 d = data[j].d; 123 if (neg) 124 d = -d; 125 126 mpf_set_d (f, 123.0); 127 if (mpf_set_str (f, str, 10) != 0) 128 { 129 printf ("mpf_set_str error\n"); 130 printf (" point %s\n", decimal_point); 131 printf (" str %s\n", str); 132 abort (); 133 } 134 if (mpf_cmp_d (f, d) != 0) 135 { 136 printf ("mpf_set_str wrong result\n"); 137 printf (" point %s\n", decimal_point); 138 printf (" str %s\n", str); 139 mpf_trace (" f", f); 140 printf (" d=%g\n", d); 141 abort (); 142 } 143 144 mpf_set_d (f, 123.0); 145 ret = gmp_sscanf (str, "%Ff", f); 146 if (ret != 1) 147 { 148 printf ("gmp_sscanf wrong return value\n"); 149 printf (" point %s\n", decimal_point); 150 printf (" str %s\n", str); 151 printf (" ret %d\n", ret); 152 abort (); 153 } 154 if (mpf_cmp_d (f, d) != 0) 155 { 156 printf ("gmp_sscanf wrong result\n"); 157 printf (" point %s\n", decimal_point); 158 printf (" str %s\n", str); 159 mpf_trace (" f", f); 160 printf (" d=%g\n", d); 161 abort (); 162 } 163 } 164 } 165 } 166 mpf_clear (f); 167 } 168 169 int 170 main (void) 171 { 172 /* The localeconv replacement breaks printf "%lu" on SunOS 4, so we can't 173 print the seed in tests_rand_start(). Nothing random is used in this 174 program though, so just use the memory tests alone. */ 175 tests_memory_start (); 176 177 { 178 mpf_t f; 179 char buf[128]; 180 mpf_init (f); 181 decimal_point = ","; 182 mpf_set_d (f, 1.5); 183 gmp_snprintf (buf, sizeof(buf), "%.1Ff", f); 184 mpf_clear (f); 185 if (strcmp (buf, "1,5") != 0) 186 { 187 printf ("Test skipped, replacing localeconv/nl_langinfo doesn't work\n"); 188 goto done; 189 } 190 } 191 192 check_input (); 193 194 done: 195 tests_memory_end (); 196 exit (0); 197 } 198