xref: /netbsd-src/external/lgpl3/gmp/dist/tests/misc/t-locale.c (revision 1daf83e636cd998f45e5597a8f995a540e2d5b4a)
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