diff --git a/src/liboslcomp/oslcomp.cpp b/src/liboslcomp/oslcomp.cpp index 84be90e1d..ba6b28d9b 100644 --- a/src/liboslcomp/oslcomp.cpp +++ b/src/liboslcomp/oslcomp.cpp @@ -651,6 +651,7 @@ OSLCompilerImpl::compile_buffer (string_view sourcecode, m_output_filename = ""; std::ostringstream oso_output; + oso_output.imbue (std::locale::classic()); // force C locale ASSERT (m_osofile == NULL); m_osofile = &oso_output; diff --git a/src/liboslcomp/osllex.l b/src/liboslcomp/osllex.l index cbd8c9815..2f88558a5 100644 --- a/src/liboslcomp/osllex.l +++ b/src/liboslcomp/osllex.l @@ -98,6 +98,7 @@ CPLUSCOMMENT \/\/.*\n #include #include +#include #include "oslcomp_pvt.h" using namespace OSL; @@ -351,13 +352,26 @@ bool OSLCompilerImpl::osl_parse_buffer (const std::string &preprocessed_buffer) { // Thread safety with the lexer/parser - static OIIO::mutex oslcompiler_mutex; - OIIO::lock_guard lock (oslcompiler_mutex); + static std::mutex oslcompiler_mutex; + std::lock_guard lock (oslcompiler_mutex); + +#ifndef OIIO_STRUTIL_HAS_STOF + // Force classic "C" locale for correct '.' decimal parsing. + // N.B. This is not safe in a multi-threaded program where another + // application thread is expecting the native locale to work properly. + // This is not necessary for versions of OIIO that have Strutil::stof, + // and we can remove it entirely when OIIO 1.9 is the minimum. + std::locale oldlocale = std::locale::global (std::locale::classic()); +#endif + osl_switch_to_buffer (osl_scan_string (preprocessed_buffer.c_str())); oslcompiler = this; oslparse (); bool parseerr = error_encountered(); osl_delete_buffer (YY_CURRENT_BUFFER); +#ifndef OIIO_STRUTIL_HAS_STOF + std::locale::global (oldlocale); // Restore the original locale. +#endif return parseerr; } diff --git a/src/liboslexec/instance.cpp b/src/liboslexec/instance.cpp index b424100d4..dec46186c 100644 --- a/src/liboslexec/instance.cpp +++ b/src/liboslexec/instance.cpp @@ -805,6 +805,7 @@ std::string ShaderGroup::serialize () const { std::ostringstream out; + out.imbue (std::locale::classic()); // force C locale out.precision (9); lock_guard lock (m_mutex); for (int i = 0, nl = nlayers(); i < nl; ++i) { diff --git a/src/liboslexec/osolex.l b/src/liboslexec/osolex.l index ea1504e1c..0504c9ddc 100644 --- a/src/liboslexec/osolex.l +++ b/src/liboslexec/osolex.l @@ -243,7 +243,7 @@ namespace pvt { // OSL::pvt OSOReader * OSOReader::osoreader = NULL; -static OIIO::mutex osoread_mutex; +static std::mutex osoread_mutex; @@ -252,7 +252,13 @@ OSOReader::parse_file (const std::string &filename) { // The lexer/parser isn't thread-safe, so make sure Only one thread // can actually be reading a .oso file at a time. - OIIO::lock_guard guard (osoread_mutex); + std::lock_guard guard (osoread_mutex); + + // Force classic "C" locale for correct '.' decimal parsing. + // N.B. This is not safe in a multi-threaded program where another + // application thread is expecting the native locale to work properly. + std::locale oldlocale; // save the previous native locale + std::locale::global (std::locale::classic()); osoin = OIIO::Filesystem::fopen (filename, "r"); if (! osoin) { @@ -271,6 +277,7 @@ OSOReader::parse_file (const std::string &filename) } oso_delete_buffer (YY_CURRENT_BUFFER); fclose (osoin); + std::locale::global (oldlocale); // Restore the original locale. return ok; } @@ -281,7 +288,16 @@ OSOReader::parse_memory (const std::string &buffer) { // The lexer/parser isn't thread-safe, so make sure Only one thread // can actually be reading a .oso file at a time. - OIIO::lock_guard guard (osoread_mutex); + std::lock_guard guard (osoread_mutex); + +#ifndef OIIO_STRUTIL_HAS_STOF + // Force classic "C" locale for correct '.' decimal parsing. + // N.B. This is not safe in a multi-threaded program where another + // application thread is expecting the native locale to work properly. + // This is not necessary for versions of OIIO that have Strutil::stof, + // and we can remove it entirely when OIIO 1.9 is the minimum. + std::locale oldlocale = std::locale::global (std::locale::classic()); +#endif oso_switch_to_buffer (oso_scan_string (buffer.c_str())); osoreader = this; @@ -292,6 +308,9 @@ OSOReader::parse_memory (const std::string &buffer) m_err.error ("Failed parse of preloaded OSO code"); } oso_delete_buffer (YY_CURRENT_BUFFER); +#ifndef OIIO_STRUTIL_HAS_STOF + std::locale::global (oldlocale); // Restore the original locale. +#endif return ok; } diff --git a/src/liboslexec/runtimeoptimize.cpp b/src/liboslexec/runtimeoptimize.cpp index e52784909..3c1aaae4d 100644 --- a/src/liboslexec/runtimeoptimize.cpp +++ b/src/liboslexec/runtimeoptimize.cpp @@ -807,6 +807,7 @@ OSOProcessorBase::const_value_as_string (const Symbol &A) TypeDesc type (A.typespec().simpletype()); int n = type.numelements() * type.aggregate; std::ostringstream s; + s.imbue (std::locale::classic()); // force C locale if (type.basetype == TypeDesc::FLOAT) { for (int i = 0; i < n; ++i) s << (i ? "," : "") << ((const float *)A.data())[i]; diff --git a/src/liboslexec/shadingsys.cpp b/src/liboslexec/shadingsys.cpp index 36f330556..b4dae1a38 100644 --- a/src/liboslexec/shadingsys.cpp +++ b/src/liboslexec/shadingsys.cpp @@ -1596,6 +1596,7 @@ ShadingSystemImpl::getstats (int level) const if (level <= 0) return ""; std::ostringstream out; + out.imbue (std::locale::classic()); // force C locale out << "OSL ShadingSystem statistics (" << (void*)this; out << ") ver " << OSL_LIBRARY_VERSION_STRING << ", LLVM " << OSL_LLVM_FULL_VERSION << "\n"; diff --git a/src/oslc/oslcmain.cpp b/src/oslc/oslcmain.cpp index 9a77e2525..95dd99122 100644 --- a/src/oslc/oslcmain.cpp +++ b/src/oslc/oslcmain.cpp @@ -112,6 +112,10 @@ static OSLC_ErrorHandler default_oslc_error_handler; int main (int argc, const char *argv[]) { + // Globally force classic "C" locale, and turn off all formatting + // internationalization, for the entire oslc application. + std::locale::global (std::locale::classic()); + OIIO::Filesystem::convert_native_arguments (argc, (const char **)argv); std::vector args; diff --git a/src/oslinfo/oslinfo.cpp b/src/oslinfo/oslinfo.cpp index 845cf42da..d6d069f83 100644 --- a/src/oslinfo/oslinfo.cpp +++ b/src/oslinfo/oslinfo.cpp @@ -237,6 +237,10 @@ input_file (int argc, const char *argv[]) int main (int argc, char *argv[]) { + // Globally force classic "C" locale, and turn off all formatting + // internationalization, for the entire oslinfo application. + std::locale::global (std::locale::classic()); + OIIO::Filesystem::convert_native_arguments (argc, (const char **)argv); OIIO::ArgParse ap (argc, (const char **)argv);