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