fixed problems with parse_float() (fd.o bug 2520)
authorBrian Paul <brian.paul@tungstengraphics.com>
Wed, 16 Feb 2005 15:08:29 +0000 (15:08 +0000)
committerBrian Paul <brian.paul@tungstengraphics.com>
Wed, 16 Feb 2005 15:08:29 +0000 (15:08 +0000)
src/mesa/shader/arbprogparse.c

index 10f0a1b..4e92d50 100644 (file)
@@ -686,39 +686,60 @@ parse_integer (GLubyte ** inst, struct arb_program *Program)
 }
 
 /**
- */
-static GLfloat
-parse_float (GLubyte ** inst, struct arb_program *Program)
+  Accumulate this string of digits, and return them as 
+  a large integer represented in floating point (for range).
+  If scale is not NULL, also accumulates a power-of-ten
+  integer scale factor that represents the number of digits 
+  in the string.
+*/
+static GLdouble
+parse_float_string(GLubyte ** inst, struct arb_program *Program, GLdouble *scale)
 {
-   GLint tmp[5], denom;
-   GLuint leading_zeros =0;
-   GLfloat value = 0;
-
-   tmp[1] = parse_integer (inst, Program);   /* This is the integer portion of the number */
+   GLdouble value = 0.0;
+   GLdouble oscale = 1.0;
 
-   /* Now we grab the fractional portion of the number (the digits after
-       * the .). We can have leading 0's here, which parse_integer will ignore,
-       * so we'll check for those first
-       */
-   while ((**inst == '0') && ( *(*inst+1) != 0))
-   {
-         leading_zeros++;
-         (*inst)++;
+   if (**inst == 0) { /* this string of digits is empty-- do nothing */
+      (*inst)++;
+   }
+   else { /* nonempty string-- parse out the digits */
+      while (isdigit(**inst)) {
+         GLubyte digit = *((*inst)++);
+         value = value * 10.0 + (GLint) (digit - '0');
+         oscale *= 10.0;
+      }
+      assert(**inst == 0); /* integer string should end with 0 */
+      (*inst)++; /* skip over terminating 0 */
+      Program->Position = parse_position(inst); /* skip position (from integer) */
    }
-   tmp[2] = parse_integer (inst, Program);   /* This is the fractional portion of the number */
-   tmp[3] = parse_sign (inst);               /* This is the sign of the exponent */
-   tmp[4] = parse_integer (inst, Program);   /* This is the exponent */
+   if (scale)
+      *scale = oscale;
+   return value;
+}
 
-   value = (GLfloat) tmp[1];
-   denom = 1;
-   while (denom < tmp[2])
-      denom *= 10;
-   denom *= (GLint) _mesa_pow( 10, leading_zeros );
-   value += (GLfloat) tmp[2] / (GLfloat) denom;
+/**
+  Parse an unsigned floating-point number from this stream of tokenized
+  characters.  Example floating-point formats supported:
+     12.34
+     12
+     0.34
+     .34
+     12.34e-4
+ */
+static GLfloat
+parse_float (GLubyte ** inst, struct arb_program *Program)
+{
+   GLint exponent;
+   GLdouble whole, fraction, fracScale = 1.0;
 
-   value *= (GLfloat) _mesa_pow (10, (GLfloat) tmp[3] * (GLfloat) tmp[4]);
+   whole = parse_float_string(inst, Program, 0);
+   fraction = parse_float_string(inst, Program, &fracScale);
+   
+   /* Parse signed exponent */
+   exponent = parse_integer(inst, Program);   /* This is the exponent */
 
-   return value;
+   /* Assemble parts of floating-point number: */
+   return (GLfloat) ((whole + fraction / fracScale) *
+                     _mesa_pow(10.0, (GLfloat) exponent));
 }