]> git.sur5r.net Git - cc65/commitdiff
Added support for floating point constants in the scanner and Primary()
authorcuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Sun, 6 Jun 2004 15:59:44 +0000 (15:59 +0000)
committercuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Sun, 6 Jun 2004 15:59:44 +0000 (15:59 +0000)
git-svn-id: svn://svn.cc65.org/cc65/trunk@3108 b7a2c559-68d2-44c3-8de9-860c34a00d81

src/cc65/expr.c
src/cc65/make/gcc.mak
src/cc65/scanner.c

index 7a3aacde0e6a8a2c3728821c071c7d5bd48b3b21..8c14817de29711466fbd9d8846b7252fb3c42630 100644 (file)
@@ -766,21 +766,31 @@ static void Primary (ExprDesc* E)
 
     /* Character and integer constants. */
     if (CurTok.Tok == TOK_ICONST || CurTok.Tok == TOK_CCONST) {
+       E->IVal  = CurTok.IVal;
        E->Flags = E_LOC_ABS | E_RTYPE_RVAL;
        E->Type  = CurTok.Type;
-       E->IVal  = CurTok.IVal;
        NextToken ();
        return;
     }
 
+    /* Floating point constant */
+    if (CurTok.Tok == TOK_FCONST) {
+        E->FVal  = CurTok.FVal;
+        E->Flags = E_LOC_ABS | E_RTYPE_RVAL;
+        E->Type  = CurTok.Type;
+        printf ("Floating point constant: %f\n", E->FVal);
+        NextToken ();
+        return;
+    }
+
     /* Process parenthesized subexpression by calling the whole parser
      * recursively.
      */
     if (CurTok.Tok == TOK_LPAREN) {
-       NextToken ();
+       NextToken ();
         hie0 (E);
                ConsumeRParen ();
-       return;
+       return;
     }
 
     /* If we run into an identifier in preprocessing mode, we assume that this
@@ -1475,7 +1485,7 @@ static void PreInc (ExprDesc* Expr)
     ED_MakeRValExpr (Expr);
 }
 
-                                         
+
 
 static void PreDec (ExprDesc* Expr)
 /* Handle the predecrement operators */
@@ -1547,7 +1557,7 @@ static void PreDec (ExprDesc* Expr)
 }
 
 
-                                         
+
 static void PostIncDec (ExprDesc* Expr, void (*inc) (unsigned, unsigned long))
 /* Handle i-- and i++ */
 {
index 18219a337a0f8773529af47b1ac825d72716c00e..d5b3d7f429da081e995db8f7aa4fe54e01c16c7a 100644 (file)
@@ -20,7 +20,7 @@ COMMON        = ../common
 CFLAGS = -O2 -g -Wall -W -I$(COMMON) $(CDEFS)
 CC=gcc
 EBIND=emxbind
-LDFLAGS=
+LDFLAGS=-lm
 
 # ------------------------------------------------------------------------------
 # Object files and libraries to link
index 73ce35aed1db9887338b47ef4d4b3a0aacda35fe..1640e5c5cb787a00a25dc6a003b7bcb8f24b1cbe 100644 (file)
@@ -38,6 +38,7 @@
 #include <string.h>
 #include <errno.h>
 #include <ctype.h>
+#include <math.h>
 
 /* common */
 #include "chartype.h"
@@ -391,7 +392,7 @@ static void StringConst (void)
        }
 
        /* Skip closing quote char if there was one */
-       NextChar ();
+       NextChar ();
 
        /* Skip white space, read new input */
        SkipWhite ();
@@ -404,6 +405,252 @@ static void StringConst (void)
 
 
 
+static void NumericConst (void)
+/* Parse a numeric constant */
+{
+    unsigned Base;              /* Temporary number base */
+    unsigned Prefix;            /* Base according to prefix */
+    StrBuf   S;
+    int      IsFloat;
+    char     C;
+    unsigned DigitVal;
+    unsigned long IVal;         /* Value */
+
+    /* Check for a leading hex or octal prefix and determine the possible
+     * integer types.
+     */
+    if (CurC == '0') {
+        /* Gobble 0 and examine next char */
+        NextChar ();
+        if (toupper (CurC) == 'X') {
+            Base = Prefix = 16;
+            NextChar ();       /* gobble "x" */
+        } else {
+            Base = 10;          /* Assume 10 for now - see below */
+            Prefix = 8;         /* Actual prefix says octal */
+        }
+    } else {
+        Base  = Prefix = 10;
+    }
+
+    /* Because floating point numbers don't have octal prefixes (a number
+     * with a leading zero is decimal), we first have to read the number
+     * before converting it, so we can determine if it's a float or an
+     * integer.
+     */
+    InitStrBuf (&S);
+    while (IsXDigit (CurC) && HexVal (CurC) < Base) {
+        SB_AppendChar (&S, CurC);
+        NextChar ();
+    }
+    SB_Terminate (&S);
+
+    /* The following character tells us if we have an integer or floating
+     * point constant.
+     */
+    IsFloat = (CurC == '.' ||
+               (Base == 10 && toupper (CurC) == 'E') ||
+               (Base == 16 && toupper (CurC) == 'P'));
+
+    /* If we don't have a floating point type, an octal prefix results in an
+     * octal base.
+     */
+    if (!IsFloat && Prefix == 8) {
+        Base = 8;
+    }
+
+    /* Since we do now know the correct base, convert the remembered input
+     * into a number.
+     */
+    SB_Reset (&S);
+    IVal = 0;
+    while ((C = SB_Get (&S)) != '\0') {
+        DigitVal = HexVal (C);
+        if (DigitVal >= Base) {
+            Error ("Numeric constant contains digits beyond the radix");
+        }
+        IVal = (IVal * Base) + DigitVal;
+    }
+
+    /* We don't need the string buffer any longer */
+    DoneStrBuf (&S);
+
+    /* Distinguish between integer and floating point constants */
+    if (!IsFloat) {
+
+        unsigned Types;
+        int      HaveSuffix;
+
+        /* Check for a suffix and determine the possible types */
+        HaveSuffix = 1;
+        if (toupper (CurC) == 'U') {
+            /* Unsigned type */
+            NextChar ();
+            if (toupper (CurC) != 'L') {
+                Types = IT_UINT | IT_ULONG;
+            } else {
+                NextChar ();
+                Types = IT_ULONG;
+            }
+        } else if (toupper (CurC) == 'L') {
+            /* Long type */
+            NextChar ();
+            if (toupper (CurC) != 'U') {
+                Types = IT_LONG | IT_ULONG;
+            } else {
+                NextChar ();
+                Types = IT_ULONG;
+            }
+        } else {
+            HaveSuffix = 0;
+            if (Prefix == 10) {
+                /* Decimal constants are of any type but uint */
+                Types = IT_INT | IT_LONG | IT_ULONG;
+            } else {
+                /* Octal or hex constants are of any type */
+                Types = IT_INT | IT_UINT | IT_LONG | IT_ULONG;
+            }
+        }
+
+        /* Check the range to determine the type */
+        if (IVal > 0x7FFF) {
+            /* Out of range for int */
+            Types &= ~IT_INT;
+            /* If the value is in the range 0x8000..0xFFFF, unsigned int is not
+             * allowed, and we don't have a type specifying suffix, emit a
+             * warning, because the constant is of type long.
+             */
+            if (IVal <= 0xFFFF && (Types & IT_UINT) == 0 && !HaveSuffix) {
+                Warning ("Constant is long");
+            }
+        }
+        if (IVal > 0xFFFF) {
+            /* Out of range for unsigned int */
+            Types &= ~IT_UINT;
+        }
+        if (IVal > 0x7FFFFFFF) {
+            /* Out of range for long int */
+            Types &= ~IT_LONG;
+        }
+
+        /* Now set the type string to the smallest type in types */
+        if (Types & IT_INT) {
+            NextTok.Type = type_int;
+        } else if (Types & IT_UINT) {
+            NextTok.Type = type_uint;
+        } else if (Types & IT_LONG) {
+            NextTok.Type = type_long;
+        } else {
+            NextTok.Type = type_ulong;
+        }
+
+        /* Set the value and the token */
+        NextTok.IVal = IVal;
+        NextTok.Tok  = TOK_ICONST;
+
+    } else {
+
+        /* Float constant */
+        double FVal = IVal;             /* Convert to float */
+
+        /* Check for a fractional part and read it */
+        if (CurC == '.') {
+
+            unsigned Digits;
+            unsigned long Frac;
+            unsigned long Scale;
+
+            /* Skip the dot */
+            NextChar ();
+
+            /* Read fractional digits. Since we support only 32 bit floats
+             * with a maximum of 7 fractional digits, we read the fractional
+             * part as integer with up to 8 digits and drop the remainder.
+             * This avoids an overflow of Frac and Scale.
+             */
+            Digits = 0;
+            Frac   = 0;
+            Scale  = 1;
+            while (IsXDigit (CurC) && (DigitVal = HexVal (CurC)) < Base) {
+                if (Digits < 8) {
+                    Frac = Frac * Base + DigitVal;
+                    ++Digits;
+                    Scale *= Base;
+                }
+                NextChar ();
+            }
+
+            /* Scale the fractional part and add it */
+            if (Frac) {
+                FVal += ((double) Frac) / ((double) Scale);
+            }
+        }
+
+        /* Check for an exponent and read it */
+        if ((Base == 16 && toupper (CurC) == 'F') ||
+            (Base == 10 && toupper (CurC) == 'E')) {
+
+            int Sign;
+            unsigned Digits;
+            unsigned Exp;
+
+            /* Skip the exponent notifier */
+            NextChar ();
+
+            /* Read an optional sign */
+            Sign = 1;
+            if (CurC == '-') {
+                Sign = -1;
+                NextChar ();
+            }
+
+            /* Read exponent digits. Since we support only 32 bit floats
+             * with a maximum exponent of +-/127, we read the exponent
+             * part as integer with up to 3 digits and drop the remainder.
+             * This avoids an overflow of Exp. The exponent is always
+             * decimal, even for hex float consts.
+             */
+            Digits = 0;
+            Exp    = 0;
+            while (IsDigit (CurC)) {
+                if (++Digits <= 3) {
+                    Exp = Exp * 10 + HexVal (CurC);
+                }
+                NextChar ();
+            }
+
+            /* Check for errors: We must have exponent digits, and not more
+             * than three.
+             */
+            if (Digits == 0) {
+                Error ("Floating constant exponent has no digits");
+            } else if (Digits > 3) {
+                Warning ("Floating constant exponent is too large");
+            }
+
+            /* Scale the exponent and adjust the value accordingly */
+            if (Exp) {
+                FVal *= pow (10, Exp);
+            }
+        }
+
+        /* Check for a suffix and determine the type of the constant */
+        if (toupper (CurC) == 'F') {
+            NextChar ();
+            NextTok.Type = type_float;
+        } else {
+            NextTok.Type = type_double;
+        }
+
+        /* Set the value and the token */
+        NextTok.FVal = FVal;
+        NextTok.Tok  = TOK_FCONST;
+
+    }
+}
+
+
+
 void NextToken (void)
 /* Get next token from input stream */
 {
@@ -442,108 +689,8 @@ void NextToken (void)
 
     /* Determine the next token from the lookahead */
     if (IsDigit (CurC)) {
-
        /* A number */
-       int HaveSuffix;         /* True if we have a type suffix */
-       unsigned types;         /* Possible types */
-       unsigned Base;
-        unsigned DigitVal;
-       unsigned long k;        /* Value */
-
-       k     = 0;
-       Base  = 10;
-       types = IT_INT | IT_LONG | IT_ULONG;
-
-               if (CurC == '0') {
-           /* Octal or hex constants may also be of type unsigned int */
-           types = IT_INT | IT_UINT | IT_LONG | IT_ULONG;
-           /* gobble 0 and examin next char */
-           NextChar ();
-           if (toupper (CurC) == 'X') {
-               Base = 16;
-               NextTok.Type = type_uint;
-                       NextChar ();    /* gobble "x" */
-           } else {
-               Base = 8;
-           }
-       }
-        while (IsXDigit (CurC) && (DigitVal = HexVal (CurC)) < Base) {
-            k = k * Base + DigitVal;
-            NextChar ();
-        }
-        /* Check for errorneous digits */
-        if (Base == 8 && IsDigit (CurC)) {
-            Error ("Numeric constant contains digits beyond the radix");
-            /* Do error recovery */
-            do {
-                NextChar ();
-            } while (IsDigit (CurC));
-        } else if (Base != 16 && IsXDigit (CurC)) {
-            Error ("Nondigits in number and not hexadecimal");
-            do {
-                NextChar ();
-            } while (IsXDigit (CurC));
-        }
-
-       /* Check for a suffix */
-       HaveSuffix = 1;
-       if (CurC == 'u' || CurC == 'U') {
-           /* Unsigned type */
-           NextChar ();
-           if (toupper (CurC) != 'L') {
-               types = IT_UINT | IT_ULONG;
-           } else {
-               NextChar ();
-               types = IT_ULONG;
-           }
-       } else if (CurC == 'l' || CurC == 'L') {
-           /* Long type */
-                   NextChar ();
-           if (toupper (CurC) != 'U') {
-               types = IT_LONG | IT_ULONG;
-           } else {
-               NextChar ();
-               types = IT_ULONG;
-           }
-       } else {
-           HaveSuffix = 0;
-       }
-
-       /* Check the range to determine the type */
-               if (k > 0x7FFF) {
-           /* Out of range for int */
-           types &= ~IT_INT;
-           /* If the value is in the range 0x8000..0xFFFF, unsigned int is not
-            * allowed, and we don't have a type specifying suffix, emit a
-            * warning.
-            */
-                   if (k <= 0xFFFF && (types & IT_UINT) == 0 && !HaveSuffix) {
-               Warning ("Constant is long");
-           }
-       }
-       if (k > 0xFFFF) {
-           /* Out of range for unsigned int */
-           types &= ~IT_UINT;
-       }
-       if (k > 0x7FFFFFFF) {
-           /* Out of range for long int */
-           types &= ~IT_LONG;
-       }
-
-       /* Now set the type string to the smallest type in types */
-       if (types & IT_INT) {
-           NextTok.Type = type_int;
-       } else if (types & IT_UINT) {
-           NextTok.Type = type_uint;
-       } else if (types & IT_LONG) {
-           NextTok.Type = type_long;
-       } else {
-           NextTok.Type = type_ulong;
-       }
-
-       /* Set the value and the token */
-       NextTok.IVal = k;
-       NextTok.Tok  = TOK_ICONST;
+        NumericConst ();
        return;
     }
 
@@ -677,18 +824,22 @@ void NextToken (void)
            }
            break;
 
-       case '.':
-           NextChar ();
-                   if (CurC == '.') {
-               NextChar ();
-               if (CurC == '.') {
-                   SetTok (TOK_ELLIPSIS);
-               } else {
-                   UnknownChar (CurC);
-               }
-           } else {
-               NextTok.Tok = TOK_DOT;
-           }
+       case '.':     
+            if (IsDigit (NextC)) {
+                NumericConst ();
+            } else {
+                NextChar ();
+                if (CurC == '.') {
+                    NextChar ();
+                    if (CurC == '.') {
+                        SetTok (TOK_ELLIPSIS);
+                    } else {
+                        UnknownChar (CurC);
+                    }
+                } else {
+                    NextTok.Tok = TOK_DOT;
+                }
+            }
            break;
 
        case '/':