[Mesa-dev] [PATCH] glsl: Fix isinf() for non-C99-compliant compilers.

Paul Berry stereotype441 at gmail.com
Wed Jan 18 12:32:12 PST 2012


Commit ede60bc4670a8d9c14921c77abee1ac57fc0e6bf (glsl: Add isinf() and
isnan() builtins) uses "+INF" in the .ir file to represent infinity.
This worked on C99-compliant compilers, since the s-expression reader
uses strtod() to read numbers, and C99 requires strtod() to understand
"+INF".  However, it didn't work on non-C99-compliant compilers such
as MSVC.

This patch modifies the s-expression reader to explicitly check for
"+INF" rather than relying on strtod() to support it.

This is a candidate for the 8.0 branch.

Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=44767
Tested-by: Morgan Armand <morgan.devel at gmail.com>
---
 src/glsl/s_expression.cpp |   36 ++++++++++++++++++++++--------------
 1 files changed, 22 insertions(+), 14 deletions(-)

diff --git a/src/glsl/s_expression.cpp b/src/glsl/s_expression.cpp
index e704a3b..57de9d3 100644
--- a/src/glsl/s_expression.cpp
+++ b/src/glsl/s_expression.cpp
@@ -23,6 +23,7 @@
  */
 
 #include <assert.h>
+#include <limits>
 #include "s_expression.h"
 
 s_symbol::s_symbol(const char *str, size_t n)
@@ -64,21 +65,28 @@ read_atom(void *ctx, const char *&src, char *&symbol_buffer)
    if (n == 0)
       return NULL; // no atom
 
-   // Check if the atom is a number.
-   char *float_end = NULL;
-   double f = glsl_strtod(src, &float_end);
-   if (float_end != src) {
-      char *int_end = NULL;
-      int i = strtol(src, &int_end, 10);
-      // If strtod matched more characters, it must have a decimal part
-      if (float_end > int_end)
-	 expr = new(ctx) s_float(f);
-      else
-	 expr = new(ctx) s_int(i);
+   // Check for the special symbol '+INF', which means +Infinity.  Note: C99
+   // requires strtod to parse '+INF' as +Infinity, but we still support some
+   // non-C99-compliant compilers (e.g. MSVC).
+   if (n == 4 && strncmp(src, "+INF", 4) == 0) {
+      expr = new(ctx) s_float(std::numeric_limits<float>::infinity());
    } else {
-      // Not a number; return a symbol.
-      symbol_buffer[n] = '\0';
-      expr = new(ctx) s_symbol(symbol_buffer, n);
+      // Check if the atom is a number.
+      char *float_end = NULL;
+      double f = glsl_strtod(src, &float_end);
+      if (float_end != src) {
+         char *int_end = NULL;
+         int i = strtol(src, &int_end, 10);
+         // If strtod matched more characters, it must have a decimal part
+         if (float_end > int_end)
+            expr = new(ctx) s_float(f);
+         else
+            expr = new(ctx) s_int(i);
+      } else {
+         // Not a number; return a symbol.
+         symbol_buffer[n] = '\0';
+         expr = new(ctx) s_symbol(symbol_buffer, n);
+      }
    }
 
    src += n;
-- 
1.7.6.5



More information about the mesa-dev mailing list