From a109f475ed362729c6c5aa109cac6ba759e12330 Mon Sep 17 00:00:00 2001 From: bbbradsmith Date: Tue, 2 May 2023 23:49:40 -0400 Subject: [PATCH] Fix broken/incomplete floating point parsing - Fractional digit scale was broken - Base was partially ignored - Exponent sign was ignored - Exponent for hex float is 2 not 10 --- src/cc65/scanner.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/cc65/scanner.c b/src/cc65/scanner.c index 36fd1301b..634ec39bb 100644 --- a/src/cc65/scanner.c +++ b/src/cc65/scanner.c @@ -687,20 +687,21 @@ static void NumericConst (void) /* Check for a fractional part and read it */ if (SB_Peek (&Src) == '.') { - Double Scale; + Double Scale, ScaleDigit; /* Skip the dot */ SB_Skip (&Src); /* Read fractional digits */ - Scale = FP_D_Make (1.0); + ScaleDigit = FP_D_Div (FP_D_Make (1.0), FP_D_FromInt (Base)); + Scale = ScaleDigit; while (IsXDigit (SB_Peek (&Src)) && (DigitVal = HexVal (SB_Peek (&Src))) < Base) { /* Get the value of this digit */ - Double FracVal = FP_D_Div (FP_D_FromInt (DigitVal * Base), Scale); + Double FracVal = FP_D_Mul (FP_D_FromInt (DigitVal), Scale); /* Add it to the float value */ FVal = FP_D_Add (FVal, FracVal); - /* Scale base */ - Scale = FP_D_Mul (Scale, FP_D_FromInt (DigitVal)); + /* Adjust Scale for next digit */ + Scale = FP_D_Mul (Scale, ScaleDigit); /* Skip the digit */ SB_Skip (&Src); } @@ -712,12 +713,15 @@ static void NumericConst (void) unsigned Digits; unsigned Exp; + int Sign; /* Skip the exponent notifier */ SB_Skip (&Src); /* Read an optional sign */ + Sign = 0; if (SB_Peek (&Src) == '-') { + Sign = 1; SB_Skip (&Src); } else if (SB_Peek (&Src) == '+') { SB_Skip (&Src); @@ -747,9 +751,11 @@ static void NumericConst (void) Warning ("Floating constant exponent is too large"); } - /* Scale the exponent and adjust the value accordingly */ + /* Scale the exponent and adjust the value accordingly. + ** Decimal exponents are base 10, hexadecimal exponents are base 2 (C99). + */ if (Exp) { - FVal = FP_D_Mul (FVal, FP_D_Make (pow (10, Exp))); + FVal = FP_D_Mul (FVal, FP_D_Make (pow ((Base == 16) ? 2.0 : 10.0, (Sign ? -1.0 : 1.0) * Exp))); } }