(root)/
gmp-6.3.0/
tests/
misc/
t-locale.c
       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  }