David Rose 16 years ago
parent
commit
8f96a87460

+ 1 - 1
dtool/pptempl/Template.unix.pp

@@ -122,7 +122,7 @@
 
 
 // And $[frameworks] is the set of OSX-style frameworks we will link with.
 // And $[frameworks] is the set of OSX-style frameworks we will link with.
 #defer frameworks $[unique $[get_frameworks]]
 #defer frameworks $[unique $[get_frameworks]]
-#defer bin_frameworks $[unique $[all_libs $[get_frameworks],$[complete_local_libs]]]
+#defer bin_frameworks $[unique $[get_frameworks] $[all_libs $[get_frameworks],$[complete_local_libs]]]
 //#defer bin_frameworks $[unique $[get_frameworks]]
 //#defer bin_frameworks $[unique $[get_frameworks]]
 
 
 // This is the set of files we might copy into *.prebuilt, if we have
 // This is the set of files we might copy into *.prebuilt, if we have

+ 2 - 1
dtool/src/cppparser/cppPreprocessor.cxx

@@ -25,6 +25,7 @@
 #include "cppCommentBlock.h"
 #include "cppCommentBlock.h"
 #include "cppBison.h"
 #include "cppBison.h"
 #include "indent.h"
 #include "indent.h"
+#include "pstrtod.h"
 
 
 #include <assert.h>
 #include <assert.h>
 #include <ctype.h>
 #include <ctype.h>
@@ -1915,7 +1916,7 @@ get_number(int c, int c2) {
 
 
     _last_c = c;
     _last_c = c;
     YYSTYPE result;
     YYSTYPE result;
-    result.u.real = strtod(num.c_str(), (char **)NULL);
+    result.u.real = pstrtod(num.c_str(), (char **)NULL);
     return CPPToken(REAL, first_line, first_col, first_file, num, result);
     return CPPToken(REAL, first_line, first_col, first_file, num, result);
   }
   }
 
 

+ 9 - 0
dtool/src/dtoolbase/Sources.pp

@@ -29,6 +29,7 @@
     nearly_zero.h \
     nearly_zero.h \
     neverFreeMemory.h neverFreeMemory.I \
     neverFreeMemory.h neverFreeMemory.I \
     numeric_types.h \
     numeric_types.h \
+    pstrtod.h \
     register_type.I register_type.h \
     register_type.I register_type.h \
     selectThreadImpl.h \
     selectThreadImpl.h \
     stl_compares.I stl_compares.h \
     stl_compares.I stl_compares.h \
@@ -56,6 +57,7 @@
     mutexWin32Impl.cxx \
     mutexWin32Impl.cxx \
     mutexSpinlockImpl.cxx \
     mutexSpinlockImpl.cxx \
     neverFreeMemory.cxx \
     neverFreeMemory.cxx \
+    pstrtod.cxx \
     register_type.cxx \
     register_type.cxx \
     typeHandle.cxx \
     typeHandle.cxx \
     typeRegistry.cxx typeRegistryNode.cxx \
     typeRegistry.cxx typeRegistryNode.cxx \
@@ -83,6 +85,7 @@
     nearly_zero.h \
     nearly_zero.h \
     neverFreeMemory.h neverFreeMemory.I \
     neverFreeMemory.h neverFreeMemory.I \
     numeric_types.h \
     numeric_types.h \
+    pstrtod.h \
     register_type.I register_type.h \
     register_type.I register_type.h \
     selectThreadImpl.h \
     selectThreadImpl.h \
     stl_compares.I stl_compares.h \
     stl_compares.I stl_compares.h \
@@ -95,3 +98,9 @@
     lookup3.h
     lookup3.h
 
 
 #end lib_target
 #end lib_target
+
+#begin test_bin_target
+  #define TARGET test_strtod
+  #define SOURCES test_strtod.cxx pstrtod.cxx pstrtod.h
+
+#end test_bin_target

+ 1 - 0
dtool/src/dtoolbase/dtoolbase_composite2.cxx

@@ -2,6 +2,7 @@
 #include "mutexWin32Impl.cxx"
 #include "mutexWin32Impl.cxx"
 #include "mutexSpinlockImpl.cxx"
 #include "mutexSpinlockImpl.cxx"
 #include "neverFreeMemory.cxx"
 #include "neverFreeMemory.cxx"
+#include "pstrtod.cxx"
 #include "register_type.cxx"
 #include "register_type.cxx"
 #include "typeHandle.cxx"
 #include "typeHandle.cxx"
 #include "typeRegistry.cxx"
 #include "typeRegistry.cxx"

+ 179 - 0
dtool/src/dtoolbase/pstrtod.cxx

@@ -0,0 +1,179 @@
+// Filename: pstrtod.cxx
+// Created by:  drose (13Jun09)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) Carnegie Mellon University.  All rights reserved.
+//
+// All use of this software is subject to the terms of the revised BSD
+// license.  You should have received a copy of this license along
+// with this source code in a file named "LICENSE."
+//
+////////////////////////////////////////////////////////////////////
+
+#include "pstrtod.h"
+
+#include <ctype.h>
+#include <math.h>
+
+////////////////////////////////////////////////////////////////////
+//     Function: pstrnicmp
+//  Description: This case-insenstive string compare function is used
+//               by pstrtod, below.
+////////////////////////////////////////////////////////////////////
+static int
+pstrnicmp(const char *s1, const char *s2, size_t n) {
+  if (n == 0) {
+    // Trivial equivalence.
+    return 0;
+  }
+  while (tolower(*s1) == tolower(*s2)) {
+    --n;
+    if ((*s1) == '\0' || n == 0) {
+      // They reached the end of the string together.
+      return 0;
+    }
+    ++s1;
+    ++s2;
+  }
+
+  // There's a difference somewhere.
+  return (int)(unsigned char)(*s1) - (int)(unsigned char)(*s2);
+}
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: pstrtod
+//  Description: This function re-implements strtod, to avoid the
+//               problems that occur when the LC_NUMERIC locale gets
+//               set to anything other than "C".  Regardless of the
+//               user's locale, we need to be able to parse
+//               floating-point numbers internally understanding a "."
+//               as the decimal point.
+////////////////////////////////////////////////////////////////////
+double
+pstrtod(const char *nptr, char **endptr) {
+  // First, skip whitespace.
+  const char *p = nptr;
+  while (isspace(*p)) {
+    ++p;
+  }
+
+  // Skip an optional leading sign.
+  char sign = '+';
+  if (*p == '+' || *p == '-') {
+    sign = *p;
+    ++p;
+  }
+
+  double value = 0.0;
+  
+  if (pstrnicmp(p, "infinity", 8) == 0) {
+    value = INFINITY;
+    p += 8;
+  } else if (pstrnicmp(p, "inf", 3) == 0) {
+    value = INFINITY;
+    p += 3;
+  } else if (pstrnicmp(p, "nan", 3) == 0) {
+    value = NAN;
+    p += 3;
+    if (pstrnicmp(p, "0x", 2) == 0) {
+      // The NaN code also appears in the string.  Use it.
+      static const size_t nan_code_size = 32;
+      char nan_code[nan_code_size + 1];
+      nan_code[0] = '0';
+      nan_code[1] = 'x';
+      const char *q = p + 2;
+      int ni = 2;
+      while (isdigit(*q) || (tolower(*q) >= 'a' && tolower(*q) <= 'f')) {
+        if (ni < nan_code_size) {
+          nan_code[ni] = *q;
+          ++ni;
+        }
+        ++q;
+      }
+      nan_code[ni] = '\0';
+      value = nan(nan_code);
+      p = q;
+    }
+
+  } else {
+
+    // Start reading decimal digits to the left of the decimal point.
+    bool found_digits = false;
+    while (isdigit(*p)) {
+      value = (value * 10.0) + (*p - '0');
+      found_digits = true;
+      ++p;
+    }
+
+    if (*p == '.') {
+      ++p;
+      // Read decimal digits to the right of the decimal point.
+      double multiplicand = 0.1;
+      while (isdigit(*p)) {
+        value += (*p - '0') * multiplicand;
+        ++p;
+        found_digits = true;
+        multiplicand *= 0.1;
+      }
+    }
+
+    if (!found_digits) {
+      // Not a valid float.
+      if (endptr != NULL) {
+        *endptr = (char *)nptr;
+      }
+      return 0.0;
+    }
+
+    if (tolower(*p) == 'e') {
+      // There's an exponent.
+      ++p;
+
+      char esign = '+';
+      if (*p == '+' || *p == '-') {
+        esign = *p;
+        ++p;
+      }
+
+      // Start reading decimal digits to the left of the decimal point.
+      double evalue = 0.0;
+      while (isdigit(*p)) {
+        evalue = (evalue * 10.0) + (*p - '0');
+        ++p;
+      }
+
+      if (esign == '-') {
+        value /= pow(evalue, 10.0);
+      } else {
+        value *= pow(evalue, 10.0);
+      }
+    }        
+  }
+
+  if (sign == '-') {
+    value = -value;
+  }
+  
+  if (endptr != NULL) {
+    *endptr = (char *)p;
+  }
+  return value;
+}
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: patof
+//  Description: This function re-implements atof, to avoid the
+//               problems that occur when the LC_NUMERIC locale gets
+//               set to anything other than "C".  Regardless of the
+//               user's locale, we need to be able to parse
+//               floating-point numbers internally understanding a "."
+//               as the decimal point.
+////////////////////////////////////////////////////////////////////
+double
+patof(const char *str) {
+  return pstrtod(str, (char **)NULL);
+}

+ 34 - 0
dtool/src/dtoolbase/pstrtod.h

@@ -0,0 +1,34 @@
+// Filename: pstrtod.h
+// Created by:  drose (13Jun09)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) Carnegie Mellon University.  All rights reserved.
+//
+// All use of this software is subject to the terms of the revised BSD
+// license.  You should have received a copy of this license along
+// with this source code in a file named "LICENSE."
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef PSTRTOD_H
+#define PSTRTOD_H
+
+#include "dtoolbase.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+EXPCL_DTOOL double
+pstrtod(const char *nptr, char **endptr);
+
+EXPCL_DTOOL double
+patof(const char *str);
+
+#ifdef __cplusplus
+};  /* end of extern "C" */
+#endif
+
+#endif

+ 36 - 0
dtool/src/dtoolbase/test_strtod.cxx

@@ -0,0 +1,36 @@
+// Filename: test_strtod.cxx
+// Created by:  drose (14Jun09)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) Carnegie Mellon University.  All rights reserved.
+//
+// All use of this software is subject to the terms of the revised BSD
+// license.  You should have received a copy of this license along
+// with this source code in a file named "LICENSE."
+//
+////////////////////////////////////////////////////////////////////
+
+#include "pstrtod.h"
+
+#ifndef _WIN32
+#include <locale.h>
+#endif
+
+int
+main(int argc, char *argv[]) {
+#ifndef _WIN32
+  setlocale(LC_ALL, "");
+#endif
+
+  for (int i = 1; i < argc; ++i) {
+    char *endptr = NULL;
+    double result = pstrtod(argv[i], &endptr);
+    cerr << "pstrtod - " << argv[i] << " : " << result << " : " << endptr << "\n";
+    result = strtod(argv[i], &endptr);
+    cerr << "strtod - " << argv[i] << " : " << result << " : " << endptr << "\n";
+  }
+
+  return 0;
+}