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 *
localeconv(void)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 *
nl_langinfo(nl_item n)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
check_input(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
main(void)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