(root)/
grep-3.11/
gnulib-tests/
test-nl_langinfo2.c
       1  /* Test of nl_langinfo replacement.
       2     Copyright (C) 2023 Free Software Foundation, Inc.
       3  
       4     This program is free software: you can redistribute it and/or modify
       5     it under the terms of the GNU General Public License as published by
       6     the Free Software Foundation, either version 3 of the License, or
       7     (at your option) any later version.
       8  
       9     This program is distributed in the hope that it will be useful,
      10     but WITHOUT ANY WARRANTY; without even the implied warranty of
      11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      12     GNU General Public License for more details.
      13  
      14     You should have received a copy of the GNU General Public License
      15     along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
      16  
      17  /* Written by Bruno Haible <bruno@clisp.org>, 2023.  */
      18  
      19  #include <config.h>
      20  
      21  #include <langinfo.h>
      22  
      23  #include <locale.h>
      24  #include <stdlib.h>
      25  #include <string.h>
      26  
      27  #include "c-strcase.h"
      28  #include "c-strcasestr.h"
      29  #include "macros.h"
      30  
      31  int
      32  main (int argc, char *argv[])
      33  {
      34  #if HAVE_WORKING_USELOCALE
      35    /* Check that nl_langinfo() uses the per-thread locale.  */
      36    int pass;
      37    bool skipped_all = true;
      38  
      39    /* Extract a few items from the C locale.  */
      40    /* nl_langinfo items of the LC_CTYPE category */
      41    const char *c_CODESET = nl_langinfo (CODESET);
      42    /* nl_langinfo items of the LC_NUMERIC category */
      43    const char *c_RADIXCHAR = nl_langinfo (RADIXCHAR);
      44    /* nl_langinfo items of the LC_TIME category */
      45    const char *c_T_FMT_AMPM = nl_langinfo (T_FMT_AMPM);
      46    const char *c_AM_STR = nl_langinfo (AM_STR);
      47    const char *c_PM_STR = nl_langinfo (PM_STR);
      48    /* nl_langinfo items of the LC_MONETARY category */
      49    const char *c_CRNCYSTR = nl_langinfo (CRNCYSTR);
      50    /* nl_langinfo items of the LC_MESSAGES category */
      51    const char *c_YESEXPR = nl_langinfo (YESEXPR);
      52  
      53    /* Sanity checks.  */
      54    (void) c_CODESET;
      55    ASSERT (strcmp (c_RADIXCHAR, ".") == 0);
      56    ASSERT (strlen (c_T_FMT_AMPM) > 0);
      57    ASSERT (strlen (c_AM_STR) > 0);
      58    ASSERT (strlen (c_PM_STR) > 0);
      59    ASSERT (strlen (c_CRNCYSTR) <= 1); /* "-", "+", ".", or "" */
      60    ASSERT (c_strcasestr (c_YESEXPR, "y" /* from "yes" */) != NULL);
      61  
      62    for (pass = 1; pass <= 2; pass++)
      63      {
      64        /* pass    locale
      65            1        traditional French locale
      66            2        French UTF-8 locale
      67         */
      68        const char *fr_locale_name =
      69          getenv (pass == 1 ? "LOCALE_FR" : "LOCALE_FR_UTF8");
      70        if (strcmp (fr_locale_name, "none") != 0)
      71          {
      72            /* Use a per-thread locale.  */
      73            locale_t fr_locale = newlocale (LC_ALL_MASK, fr_locale_name, NULL);
      74            if (fr_locale != NULL)
      75              {
      76                uselocale (fr_locale);
      77  
      78                /* Extract a few items from the current locale, and check the
      79                   values.  */
      80  
      81                /* nl_langinfo items of the LC_CTYPE category */
      82                const char *fr_CODESET = nl_langinfo (CODESET);
      83                if (pass == 1)
      84                  ASSERT (strstr (fr_CODESET, "8859") != NULL);
      85                else if (pass == 2)
      86                  ASSERT (c_strcasecmp (fr_CODESET, "UTF-8") == 0
      87                          || c_strcasecmp (fr_CODESET, "UTF8") == 0);
      88  
      89                /* nl_langinfo items of the LC_NUMERIC category */
      90                const char *fr_RADIXCHAR = nl_langinfo (RADIXCHAR);
      91                ASSERT (strcmp (fr_RADIXCHAR, ",") == 0);
      92  
      93                /* nl_langinfo items of the LC_TIME category */
      94                /* macOS and Solaris 11 don't get the LC_TIME values right.
      95                   Poor.  */
      96                #if !((defined __APPLE__ && defined __MACH__) || defined __sun)
      97                const char *fr_T_FMT_AMPM = nl_langinfo (T_FMT_AMPM);
      98                const char *fr_AM_STR = nl_langinfo (AM_STR);
      99                const char *fr_PM_STR = nl_langinfo (PM_STR);
     100                ASSERT (strlen (fr_T_FMT_AMPM) == 0
     101                        || strcmp (fr_T_FMT_AMPM, "%I:%M:%S") == 0);
     102                ASSERT (strlen (fr_AM_STR) == 0);
     103                ASSERT (strlen (fr_PM_STR) == 0);
     104                #endif
     105  
     106                /* nl_langinfo items of the LC_MONETARY category */
     107                /* macOS doesn't get the EUR currency symbol or abbreviation
     108                   right.  Very poor.  */
     109                #if !(defined __APPLE__ && defined __MACH__)
     110                const char *fr_CRNCYSTR = nl_langinfo (CRNCYSTR);
     111                if (pass == 2)
     112                  ASSERT (strlen (fr_CRNCYSTR) >= 1
     113                          && strcmp (fr_CRNCYSTR + 1, "") == 0);
     114                #endif
     115  
     116                /* nl_langinfo items of the LC_MESSAGES category */
     117                const char *fr_YESEXPR = nl_langinfo (YESEXPR);
     118                ASSERT (c_strcasestr (fr_YESEXPR, "o" /* from "oui" */) != NULL);
     119  
     120                skipped_all = false;
     121              }
     122          }
     123      }
     124  
     125    if (skipped_all)
     126      {
     127        fputs ("Skipping test: French locale is not installed\n", stderr);
     128        return 77;
     129      }
     130  
     131    return 0;
     132  #else
     133    fputs ("Skipping test: uselocale() not available\n", stderr);
     134    return 77;
     135  #endif
     136  }