summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrian Paul <[email protected]>2005-02-16 15:08:29 +0000
committerBrian Paul <[email protected]>2005-02-16 15:08:29 +0000
commit1ff8f50f2f9dae5a190d21ef1ba54a70b5984d3b (patch)
tree56c9524fc425a2aa455a937cd822629641d94a94
parent2c28dd892cfb43445d7e54df8b6a8331192f4e99 (diff)
fixed problems with parse_float() (fd.o bug 2520)
-rw-r--r--src/mesa/shader/arbprogparse.c75
1 files changed, 48 insertions, 27 deletions
diff --git a/src/mesa/shader/arbprogparse.c b/src/mesa/shader/arbprogparse.c
index 10f0a1b3244..4e92d5017e3 100644
--- a/src/mesa/shader/arbprogparse.c
+++ b/src/mesa/shader/arbprogparse.c
@@ -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));
}