root/maint/gnulib/lib/c-strtod.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. c_locale
  2. C_STRTOD

   1 /* Convert string to double, using the C locale.
   2 
   3    Copyright (C) 2003-2004, 2006, 2009-2021 Free Software Foundation, Inc.
   4 
   5    This program is free software: you can redistribute it and/or modify
   6    it under the terms of the GNU General Public License as published by
   7    the Free Software Foundation; either version 3 of the License, or
   8    (at your option) any later version.
   9 
  10    This program is distributed in the hope that it will be useful,
  11    but WITHOUT ANY WARRANTY; without even the implied warranty of
  12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13    GNU General Public License for more details.
  14 
  15    You should have received a copy of the GNU General Public License
  16    along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
  17 
  18 /* Written by Paul Eggert.  */
  19 
  20 #include <config.h>
  21 
  22 #include "c-strtod.h"
  23 
  24 #include <errno.h>
  25 #include <locale.h>
  26 #include <stdlib.h>
  27 #include <string.h>
  28 
  29 #if LONG
  30 # define C_STRTOD c_strtold
  31 # define DOUBLE long double
  32 # define STRTOD_L strtold_l
  33 # define HAVE_GOOD_STRTOD_L (HAVE_STRTOLD_L && !GNULIB_defined_strtold_function)
  34 # define STRTOD strtold
  35 #else
  36 # define C_STRTOD c_strtod
  37 # define DOUBLE double
  38 # define STRTOD_L strtod_l
  39 # define HAVE_GOOD_STRTOD_L (HAVE_STRTOD_L && !GNULIB_defined_strtod_function)
  40 # define STRTOD strtod
  41 #endif
  42 
  43 #if defined LC_ALL_MASK \
  44     && ((LONG ? HAVE_GOOD_STRTOLD_L : HAVE_GOOD_STRTOD_L) \
  45         || HAVE_WORKING_USELOCALE)
  46 
  47 /* Cache for the C locale object.
  48    Marked volatile so that different threads see the same value
  49    (avoids locking).  */
  50 static volatile locale_t c_locale_cache;
  51 
  52 /* Return the C locale object, or (locale_t) 0 with errno set
  53    if it cannot be created.  */
  54 static locale_t
  55 c_locale (void)
     /* [previous][next][first][last][top][bottom][index][help] */
  56 {
  57   if (!c_locale_cache)
  58     c_locale_cache = newlocale (LC_ALL_MASK, "C", (locale_t) 0);
  59   return c_locale_cache;
  60 }
  61 
  62 #endif
  63 
  64 DOUBLE
  65 C_STRTOD (char const *nptr, char **endptr)
     /* [previous][next][first][last][top][bottom][index][help] */
  66 {
  67   DOUBLE r;
  68 
  69 #if defined LC_ALL_MASK \
  70     && ((LONG ? HAVE_GOOD_STRTOLD_L : HAVE_GOOD_STRTOD_L) \
  71         || HAVE_WORKING_USELOCALE)
  72 
  73   locale_t locale = c_locale ();
  74   if (!locale)
  75     {
  76       if (endptr)
  77         *endptr = (char *) nptr;
  78       return 0; /* errno is set here */
  79     }
  80 
  81 # if (LONG ? HAVE_GOOD_STRTOLD_L : HAVE_GOOD_STRTOD_L)
  82 
  83   r = STRTOD_L (nptr, endptr, locale);
  84 
  85 # else /* HAVE_WORKING_USELOCALE */
  86 
  87   locale_t old_locale = uselocale (locale);
  88   if (old_locale == (locale_t)0)
  89     {
  90       if (endptr)
  91         *endptr = (char *) nptr;
  92       return 0; /* errno is set here */
  93     }
  94 
  95   r = STRTOD (nptr, endptr);
  96 
  97   int saved_errno = errno;
  98   if (uselocale (old_locale) == (locale_t)0)
  99     /* We can't switch back to the old locale.  The thread is hosed.  */
 100     abort ();
 101   errno = saved_errno;
 102 
 103 # endif
 104 
 105 #else
 106 
 107   char *saved_locale = setlocale (LC_NUMERIC, NULL);
 108 
 109   if (saved_locale)
 110     {
 111       saved_locale = strdup (saved_locale);
 112       if (saved_locale == NULL)
 113         {
 114           if (endptr)
 115             *endptr = (char *) nptr;
 116           return 0; /* errno is set here */
 117         }
 118       setlocale (LC_NUMERIC, "C");
 119     }
 120 
 121   r = STRTOD (nptr, endptr);
 122 
 123   if (saved_locale)
 124     {
 125       int saved_errno = errno;
 126 
 127       setlocale (LC_NUMERIC, saved_locale);
 128       free (saved_locale);
 129       errno = saved_errno;
 130     }
 131 
 132 #endif
 133 
 134   return r;
 135 }

/* [previous][next][first][last][top][bottom][index][help] */