Home | History | Annotate | Line # | Download | only in misc
t-locale.c revision 1.1.1.3
      1 /* Test locale support, or attempt to do so.
      2 
      3 Copyright 2001, 2002, 2011, 2014 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.h"
     41 #include "gmp-impl.h"
     42 #include "tests.h"
     43 
     44 const char *decimal_point;
     45 
     46 /* Replace the libc localeconv with one we can manipulate. */
     47 #if HAVE_LOCALECONV && ! defined __MINGW32__
     48 struct lconv *
     49 localeconv (void)
     50 #if defined __cplusplus && defined __GLIBC__
     51   throw()
     52 #endif
     53 {
     54   static struct lconv  l;
     55   l.decimal_point = (char *) decimal_point;
     56   return &l;
     57 }
     58 #endif
     59 
     60 /* Replace the libc nl_langinfo with one we can manipulate. */
     61 #if HAVE_NL_LANGINFO
     62 char *
     63 nl_langinfo (nl_item n)
     64 #if defined __cplusplus && defined __GLIBC__
     65   throw()
     66 #endif
     67 {
     68 #if defined (DECIMAL_POINT)
     69   if (n == DECIMAL_POINT)
     70     return (char *) decimal_point;
     71 #endif
     72 #if defined (RADIXCHAR)
     73   if (n == RADIXCHAR)
     74     return (char *) decimal_point;
     75 #endif
     76   return (char *) "";
     77 }
     78 #endif
     79 
     80 void
     81 check_input (void)
     82 {
     83   static const char *point[] = {
     84     ".", ",", "WU", "STR", "ZTV***"
     85   };
     86 
     87   static const struct {
     88     const char  *str;
     89     double      d;
     90   } data[] = {
     91 
     92     { "1%s",   1.0 },
     93     { "1%s0",  1.0 },
     94     { "1%s00", 1.0 },
     95 
     96     { "%s5",    0.5 },
     97     { "0%s5",   0.5 },
     98     { "00%s5",  0.5 },
     99     { "00%s50", 0.5 },
    100 
    101     { "1%s5",    1.5 },
    102     { "1%s5e1", 15.0 },
    103   };
    104 
    105   int     i, j, neg, ret;
    106   char    str[128];
    107   mpf_t   f;
    108   double  d;
    109 
    110   mpf_init (f);
    111 
    112   for (i = 0; i < numberof (point); i++)
    113     {
    114       decimal_point = (const char *) point[i];
    115 
    116       for (neg = 0; neg <= 1; neg++)
    117         {
    118           for (j = 0; j < numberof (data); j++)
    119             {
    120               strcpy (str, neg ? "-" : "");
    121               sprintf (str+strlen(str), data[j].str, decimal_point);
    122 
    123               d = data[j].d;
    124               if (neg)
    125                 d = -d;
    126 
    127               mpf_set_d (f, 123.0);
    128               if (mpf_set_str (f, str, 10) != 0)
    129                 {
    130                   printf ("mpf_set_str error\n");
    131                   printf ("  point  %s\n", decimal_point);
    132                   printf ("  str    %s\n", str);
    133                   abort ();
    134                 }
    135               if (mpf_cmp_d (f, d) != 0)
    136                 {
    137                   printf    ("mpf_set_str wrong result\n");
    138                   printf    ("  point  %s\n", decimal_point);
    139                   printf    ("  str    %s\n", str);
    140                   mpf_trace ("  f", f);
    141                   printf    ("  d=%g\n", d);
    142                   abort ();
    143                 }
    144 
    145               mpf_set_d (f, 123.0);
    146               ret = gmp_sscanf (str, "%Ff", f);
    147               if (ret != 1)
    148                 {
    149                   printf ("gmp_sscanf wrong return value\n");
    150                   printf ("  point  %s\n", decimal_point);
    151                   printf ("  str    %s\n", str);
    152                   printf ("  ret    %d\n", ret);
    153                   abort ();
    154                 }
    155               if (mpf_cmp_d (f, d) != 0)
    156                 {
    157                   printf    ("gmp_sscanf wrong result\n");
    158                   printf    ("  point  %s\n", decimal_point);
    159                   printf    ("  str    %s\n", str);
    160                   mpf_trace ("  f", f);
    161                   printf    ("  d=%g\n", d);
    162                   abort ();
    163                 }
    164             }
    165         }
    166     }
    167   mpf_clear (f);
    168 }
    169 
    170 int
    171 main (void)
    172 {
    173   /* The localeconv replacement breaks printf "%lu" on SunOS 4, so we can't
    174      print the seed in tests_rand_start().  Nothing random is used in this
    175      program though, so just use the memory tests alone.  */
    176   tests_memory_start ();
    177 
    178   {
    179     mpf_t  f;
    180     char   buf[128];
    181     mpf_init (f);
    182     decimal_point = ",";
    183     mpf_set_d (f, 1.5);
    184     gmp_snprintf (buf, sizeof(buf), "%.1Ff", f);
    185     mpf_clear (f);
    186     if (strcmp (buf, "1,5") != 0)
    187       {
    188         printf ("Test skipped, replacing localeconv/nl_langinfo doesn't work\n");
    189         goto done;
    190       }
    191   }
    192 
    193   check_input ();
    194 
    195  done:
    196   tests_memory_end ();
    197   exit (0);
    198 }
    199