Back to index

nagios-plugins  1.4.16
c-strtod.c
Go to the documentation of this file.
00001 /* Convert string to double, using the C locale.
00002 
00003    Copyright (C) 2003-2004, 2006, 2009-2010 Free Software Foundation, Inc.
00004 
00005    This program is free software: you can redistribute it and/or modify
00006    it under the terms of the GNU General Public License as published by
00007    the Free Software Foundation; either version 3 of the License, or
00008    (at your option) any later version.
00009 
00010    This program is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013    GNU General Public License for more details.
00014 
00015    You should have received a copy of the GNU General Public License
00016    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
00017 
00018 /* Written by Paul Eggert.  */
00019 
00020 #include <config.h>
00021 
00022 #include "c-strtod.h"
00023 
00024 #include <errno.h>
00025 #include <locale.h>
00026 #include <stdlib.h>
00027 #include <string.h>
00028 
00029 #if LONG
00030 # define C_STRTOD c_strtold
00031 # define DOUBLE long double
00032 # define STRTOD_L strtold_l
00033 #else
00034 # define C_STRTOD c_strtod
00035 # define DOUBLE double
00036 # define STRTOD_L strtod_l
00037 #endif
00038 
00039 /* c_strtold falls back on strtod if strtold doesn't conform to C99.  */
00040 #if LONG && HAVE_C99_STRTOLD
00041 # define STRTOD strtold
00042 #else
00043 # define STRTOD strtod
00044 #endif
00045 
00046 #ifdef LC_ALL_MASK
00047 
00048 /* Cache for the C locale object.
00049    Marked volatile so that different threads see the same value
00050    (avoids locking).  */
00051 static volatile locale_t c_locale_cache;
00052 
00053 /* Return the C locale object, or (locale_t) 0 with errno set
00054    if it cannot be created.  */
00055 static inline locale_t
00056 c_locale (void)
00057 {
00058   if (!c_locale_cache)
00059     c_locale_cache = newlocale (LC_ALL_MASK, "C", (locale_t) 0);
00060   return c_locale_cache;
00061 }
00062 
00063 #endif
00064 
00065 DOUBLE
00066 C_STRTOD (char const *nptr, char **endptr)
00067 {
00068   DOUBLE r;
00069 
00070 #ifdef LC_ALL_MASK
00071 
00072   locale_t locale = c_locale ();
00073   if (!locale)
00074     {
00075       if (endptr)
00076         *endptr = (char *) nptr;
00077       return 0; /* errno is set here */
00078     }
00079 
00080   r = STRTOD_L (nptr, endptr, locale);
00081 
00082 #else
00083 
00084   char *saved_locale = setlocale (LC_NUMERIC, NULL);
00085 
00086   if (saved_locale)
00087     {
00088       saved_locale = strdup (saved_locale);
00089       if (saved_locale == NULL)
00090         {
00091           if (endptr)
00092             *endptr = (char *) nptr;
00093           return 0; /* errno is set here */
00094         }
00095       setlocale (LC_NUMERIC, "C");
00096     }
00097 
00098   r = STRTOD (nptr, endptr);
00099 
00100   if (saved_locale)
00101     {
00102       int saved_errno = errno;
00103 
00104       setlocale (LC_NUMERIC, saved_locale);
00105       free (saved_locale);
00106       errno = saved_errno;
00107     }
00108 
00109 #endif
00110 
00111   return r;
00112 }