Home | History | Annotate | Line # | Download | only in misc
t-locale.c revision 1.1.1.5
      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