]> git.sur5r.net Git - cc65/commitdiff
Added simple expressions for the config file
authorcuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Thu, 28 Jul 2005 19:50:22 +0000 (19:50 +0000)
committercuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Thu, 28 Jul 2005 19:50:22 +0000 (19:50 +0000)
git-svn-id: svn://svn.cc65.org/cc65/trunk@3556 b7a2c559-68d2-44c3-8de9-860c34a00d81

src/ld65/cfgexpr.c [new file with mode: 0644]
src/ld65/cfgexpr.h [new file with mode: 0644]
src/ld65/config.c
src/ld65/make/gcc.mak
src/ld65/make/watcom.mak
src/ld65/scanner.c
src/ld65/scanner.h

diff --git a/src/ld65/cfgexpr.c b/src/ld65/cfgexpr.c
new file mode 100644 (file)
index 0000000..2ed08c6
--- /dev/null
@@ -0,0 +1,340 @@
+/*****************************************************************************/
+/*                                                                           */
+/*                                 cfgexpr.c                                 */
+/*                                                                           */
+/*          Simple expressions for use with in configuration file            */
+/*                                                                           */
+/*                                                                           */
+/*                                                                           */
+/* (C) 2005,      Ullrich von Bassewitz                                      */
+/*                Römerstrasse 52                                            */
+/*                D-70794 Filderstadt                                        */
+/* EMail:         uz@cc65.org                                                */
+/*                                                                           */
+/*                                                                           */
+/* This software is provided 'as-is', without any expressed or implied       */
+/* warranty.  In no event will the authors be held liable for any damages    */
+/* arising from the use of this software.                                    */
+/*                                                                           */
+/* Permission is granted to anyone to use this software for any purpose,     */
+/* including commercial applications, and to alter it and redistribute it    */
+/* freely, subject to the following restrictions:                            */
+/*                                                                           */
+/* 1. The origin of this software must not be misrepresented; you must not   */
+/*    claim that you wrote the original software. If you use this software   */
+/*    in a product, an acknowledgment in the product documentation would be  */
+/*    appreciated but is not required.                                       */
+/* 2. Altered source versions must be plainly marked as such, and must not   */
+/*    be misrepresented as being the original software.                      */
+/* 3. This notice may not be removed or altered from any source              */
+/*    distribution.                                                          */
+/*                                                                           */
+/*****************************************************************************/
+
+
+
+/* common */
+#include "strbuf.h"
+
+/* ld65 */
+#include "cfgexpr.h"
+#include "error.h"
+#include "exports.h"
+#include "scanner.h"
+#include "spool.h"
+
+
+
+/*****************************************************************************/
+/*                                          Data                                    */
+/*****************************************************************************/
+
+
+
+/* Type of a CfgExpr */
+enum {
+    ceEmpty,
+    ceInt,
+    ceString
+};
+
+typedef struct CfgExpr CfgExpr;
+struct CfgExpr {
+    unsigned    Type;           /* Type of the expression */
+    long        IVal;           /* Integer value if it's a string */
+    StrBuf      SVal;           /* String value if it's a string */
+};
+
+#define CFGEXPR_INITIALIZER { ceEmpty, 0, STATIC_STRBUF_INITIALIZER }
+
+
+
+/*****************************************************************************/
+/*                                 Forwards                                  */
+/*****************************************************************************/
+
+
+
+static void Expr (CfgExpr* E);
+/* Full expression */
+
+
+
+/*****************************************************************************/
+/*                              struct CfgExpr                               */
+/*****************************************************************************/
+
+
+
+static void CE_Done (CfgExpr* E)
+/* Cleanup a CfgExpr struct */
+{
+    /* If the type is a string, we must delete the string buffer */
+    if (E->Type == ceString) {
+        DoneStrBuf (&E->SVal);
+    }
+}
+
+
+
+static void CE_AssureInt (const CfgExpr* E)
+/* Make sure, E contains an integer */
+{
+    if (E->Type != ceInt) {
+        CfgError ("Integer type expected");
+    }
+}
+
+
+
+/*****************************************************************************/
+/*                                          Code                                    */
+/*****************************************************************************/
+
+
+
+static void Factor (CfgExpr* E)
+/* Read and return a factor in E */
+{
+    Export* Sym;
+
+
+    switch (CfgTok) {
+
+       case CFGTOK_IDENT:
+           /* An identifier - search an export with the given name */
+            Sym = FindExport (GetStringId (CfgSVal));
+            if (Sym == 0) {
+                CfgError ("Unknown symbol in expression: `%s'", CfgSVal);
+            }
+            /* We can only handle constants */
+            if (!IsConstExport (Sym)) {
+                CfgError ("Value for symbol `%s' is not constant", CfgSVal);
+            }
+
+            /* Use the symbol value */
+            E->IVal = GetExportVal (Sym);
+            E->Type = ceInt;
+
+            /* Skip the symbol name */
+            CfgNextTok ();
+            break;
+
+       case CFGTOK_INTCON:
+            /* An integer constant */
+            E->IVal = CfgIVal;
+            E->Type = ceInt;
+           CfgNextTok ();
+                   break;
+
+       case CFGTOK_STRCON:
+           /* A string constant */
+            SB_CopyStr (&E->SVal, CfgSVal);
+            E->Type = ceString;
+           CfgNextTok ();
+           break;
+
+        case CFGTOK_PLUS:
+            /* Unary plus */
+            CfgNextTok ();
+            Factor (E);
+            CE_AssureInt (E);
+            break;
+
+        case CFGTOK_MINUS:
+            /* Unary minus */
+            CfgNextTok ();
+            Factor (E);
+            CE_AssureInt (E);
+            E->IVal = -E->IVal;
+            break;
+
+               case CFGTOK_LPAR:
+            /* Left parenthesis */
+                   CfgNextTok ();
+                   Expr (E);
+                   CfgConsume (CFGTOK_RPAR, "')' expected");
+                   break;
+
+               default:
+                   CfgError ("Invalid expression: %d", CfgTok);
+                   break;
+    }
+}
+
+
+
+static void Term (CfgExpr* E)
+/* Multiplicative operators: * and / */
+{
+    /* Left operand */
+    Factor (E);
+
+    /* Handle multiplicative operators */
+    while (CfgTok == CFGTOK_MUL || CfgTok == CFGTOK_DIV) {
+
+        CfgExpr RightSide = CFGEXPR_INITIALIZER;
+
+        /* Remember the token */
+        cfgtok_t Tok = CfgTok;
+
+        /* Left side must be an int */
+        CE_AssureInt (E);
+
+        /* Get the right operand and make sure it's an int */
+        Factor (&RightSide);
+        CE_AssureInt (&RightSide);
+
+        /* Handle the operation */
+        switch (Tok) {
+
+            case CFGTOK_MUL:
+                E->IVal *= RightSide.IVal;
+                break;
+
+            case CFGTOK_DIV:
+                if (RightSide.IVal == 0) {
+                    CfgError ("Division by zero");
+                }
+                E->IVal /= RightSide.IVal;
+                break;
+
+            default:
+                Internal ("Unhandled token in Term: %d", Tok);
+        }
+
+        /* Cleanup RightSide (this is not really needed since it may not
+         * contain strings at this point, but call it anyway for clarity.
+         */
+        CE_Done (&RightSide);
+    }
+}
+
+
+
+static void SimpleExpr (CfgExpr* E)
+/* Additive operators: + and - */
+{
+    /* Left operand */
+    Term (E);
+
+    /* Handle additive operators */
+    while (CfgTok == CFGTOK_PLUS || CfgTok == CFGTOK_MINUS) {
+
+        CfgExpr RightSide = CFGEXPR_INITIALIZER;
+
+        /* Remember the token, then skip it */
+        cfgtok_t Tok = CfgTok;
+        CfgNextTok ();
+
+        /* Get the right operand */
+        Term (&RightSide);
+
+        /* Make sure, left and right side are of the same type */
+        if (E->Type != RightSide.Type) {
+            CfgError ("Incompatible types in expression");
+        }
+
+        /* Handle the operation */
+        switch (Tok) {
+
+            case CFGTOK_PLUS:
+                /* Plus is defined for strings and ints */
+                if (E->Type == ceInt) {
+                    E->IVal += RightSide.IVal;
+                } else if (E->Type == ceString) {
+                    SB_Append (&E->SVal, &RightSide.SVal);
+                } else {
+                    Internal ("Unhandled type in '+' operator: %u", E->Type);
+                }
+                break;
+
+            case CFGTOK_MINUS:
+                /* Operands must be ints */
+                CE_AssureInt (E);
+                E->IVal -= RightSide.IVal;
+                break;
+
+            default:
+                Internal ("Unhandled token in SimpleExpr: %d", Tok);
+        }
+
+        /* Cleanup RightSide */
+        CE_Done (&RightSide);
+    }
+}
+
+
+
+static void Expr (CfgExpr* E)
+/* Full expression */
+{
+    SimpleExpr (E);
+}
+
+
+
+long CfgIntExpr (void)
+/* Read an expression, make sure it's an int, and return its value */
+{
+    long Val;
+
+    CfgExpr E = CFGEXPR_INITIALIZER;
+
+    /* Parse the expression */
+    Expr (&E);
+
+    /* Make sure it's an integer */
+    CE_AssureInt (&E);
+
+    /* Get the value */
+    Val = E.IVal;
+
+    /* Cleaup E */
+    CE_Done (&E);
+
+    /* Return the value */
+    return Val;
+}
+
+
+
+long CfgCheckedIntExpr (long Min, long Max)
+/* Read an expression, make sure it's an int and in range, then return its
+ * value.
+ */
+{
+    /* Get the value */
+    long Val = CfgIntExpr ();
+
+    /* Check the range */
+    if (Val < Min || Val > Max) {
+       CfgError ("Range error");
+    }
+
+    /* Return the value */
+    return Val;
+}
+
+
+
diff --git a/src/ld65/cfgexpr.h b/src/ld65/cfgexpr.h
new file mode 100644 (file)
index 0000000..dc6b99b
--- /dev/null
@@ -0,0 +1,61 @@
+/*****************************************************************************/
+/*                                                                           */
+/*                                 cfgexpr.h                                 */
+/*                                                                           */
+/*          Simple expressions for use with in configuration file            */
+/*                                                                           */
+/*                                                                           */
+/*                                                                           */
+/* (C) 2005,      Ullrich von Bassewitz                                      */
+/*                Römerstrasse 52                                            */
+/*                D-70794 Filderstadt                                        */
+/* EMail:         uz@cc65.org                                                */
+/*                                                                           */
+/*                                                                           */
+/* This software is provided 'as-is', without any expressed or implied       */
+/* warranty.  In no event will the authors be held liable for any damages    */
+/* arising from the use of this software.                                    */
+/*                                                                           */
+/* Permission is granted to anyone to use this software for any purpose,     */
+/* including commercial applications, and to alter it and redistribute it    */
+/* freely, subject to the following restrictions:                            */
+/*                                                                           */
+/* 1. The origin of this software must not be misrepresented; you must not   */
+/*    claim that you wrote the original software. If you use this software   */
+/*    in a product, an acknowledgment in the product documentation would be  */
+/*    appreciated but is not required.                                       */
+/* 2. Altered source versions must be plainly marked as such, and must not   */
+/*    be misrepresented as being the original software.                      */
+/* 3. This notice may not be removed or altered from any source              */
+/*    distribution.                                                          */
+/*                                                                           */
+/*****************************************************************************/
+
+
+
+#ifndef CFGEXPR_H
+#define CFGEXPR_H
+
+
+
+/*****************************************************************************/
+/*                                          Code                                    */
+/*****************************************************************************/
+
+
+
+long CfgIntExpr (void);
+/* Read an expression, make sure it's an int, and return its value */
+
+long CfgCheckedIntExpr (long Min, long Max);
+/* Read an expression, make sure it's an int and in range, then return its
+ * value.
+ */
+
+
+
+/* End of cfgexpr.h */
+#endif
+
+
+
index eb7dbdee4ac63181e2e4bb765da31e82c206b1f8..0a4df83e3f04c55be298fef4a1f9b5ddf04fac7d 100644 (file)
@@ -48,6 +48,7 @@
 /* ld65 */
 #include "bin.h"
 #include "binfmt.h"
+#include "cfgexpr.h"
 #include "condes.h"
 #include "config.h"
 #include "error.h"
@@ -406,11 +407,11 @@ static void ParseMemory (void)
 {
     static const IdentTok Attributes [] = {
                {   "START",    CFGTOK_START    },
-       {   "SIZE",     CFGTOK_SIZE     },
+       {   "SIZE",     CFGTOK_SIZE     },
         {   "TYPE",     CFGTOK_TYPE     },
         {   "FILE",     CFGTOK_FILE     },
         {   "DEFINE",   CFGTOK_DEFINE   },
-       {   "FILL",     CFGTOK_FILL     },
+       {   "FILL",     CFGTOK_FILL     },
                {   "FILLVAL",  CFGTOK_FILLVAL  },
     };
     static const IdentTok Types [] = {
@@ -444,22 +445,21 @@ static void ParseMemory (void)
 
                case CFGTOK_START:
                    FlagAttr (&M->Attr, MA_START, "START");
-                   CfgAssureInt ();
-                   M->Start = CfgIVal;
+                    M->Start = CfgIntExpr ();
                    break;
 
                case CFGTOK_SIZE:
                    FlagAttr (&M->Attr, MA_SIZE, "SIZE");
-                   CfgAssureInt ();
-                   M->Size = CfgIVal;
+                   M->Size = CfgIntExpr ();
                    break;
 
                case CFGTOK_TYPE:
                    FlagAttr (&M->Attr, MA_TYPE, "TYPE");
                    CfgSpecialToken (Types, ENTRY_COUNT (Types), "Type");
                    if (CfgTok == CFGTOK_RO) {
-                       M->Flags |= MF_RO;
+                       M->Flags |= MF_RO;
                    }
+                    CfgNextTok ();
                    break;
 
                case CFGTOK_FILE:
@@ -467,6 +467,7 @@ static void ParseMemory (void)
                    CfgAssureStr ();
                            /* Get the file entry and insert the memory area */
                    FileInsert (GetFile (GetStringId (CfgSVal)), M);
+                    CfgNextTok ();
                    break;
 
                case CFGTOK_DEFINE:
@@ -476,6 +477,7 @@ static void ParseMemory (void)
                    if (CfgTok == CFGTOK_TRUE) {
                        M->Flags |= MF_DEFINE;
                    }
+                    CfgNextTok ();
                    break;
 
                case CFGTOK_FILL:
@@ -485,13 +487,12 @@ static void ParseMemory (void)
                    if (CfgTok == CFGTOK_TRUE) {
                        M->Flags |= MF_FILL;
                    }
+                    CfgNextTok ();
                    break;
 
                case CFGTOK_FILLVAL:
                    FlagAttr (&M->Attr, MA_FILLVAL, "FILLVAL");
-                   CfgAssureInt ();
-                   CfgRangeCheck (0, 0xFF);
-                   M->FillVal = (unsigned char) CfgIVal;
+                   M->FillVal = (unsigned char) CfgCheckedIntExpr (0, 0xFF);
                    break;
 
                default:
@@ -499,8 +500,7 @@ static void ParseMemory (void)
 
            }
 
-           /* Skip the attribute value and an optional comma */
-           CfgNextTok ();
+           /* Skip an optional comma */
            CfgOptionalComma ();
        }
 
@@ -641,6 +641,7 @@ static void ParseSegments (void)
     };
 
     unsigned Count;
+    long     Val;
 
     /* The MEMORY section must preceed the SEGMENTS section */
     if ((SectionsEncountered & SE_MEMORY) == 0) {
@@ -674,22 +675,20 @@ static void ParseSegments (void)
            switch (AttrTok) {
 
                case CFGTOK_ALIGN:
-                   CfgAssureInt ();
                    FlagAttr (&S->Attr, SA_ALIGN, "ALIGN");
-                   CfgRangeCheck (1, 0x10000);
-                   S->Align = BitFind (CfgIVal);
-                   if ((0x01UL << S->Align) != CfgIVal) {
+                   Val = CfgCheckedIntExpr (1, 0x10000);
+                   S->Align = BitFind (Val);
+                   if ((0x01L << S->Align) != Val) {
                        CfgError ("Alignment must be a power of 2");
                    }
                    S->Flags |= SF_ALIGN;
                    break;
 
                 case CFGTOK_ALIGN_LOAD:
-                   CfgAssureInt ();
                    FlagAttr (&S->Attr, SA_ALIGN_LOAD, "ALIGN_LOAD");
-                   CfgRangeCheck (1, 0x10000);
-                           S->AlignLoad = BitFind (CfgIVal);
-                   if ((0x01UL << S->AlignLoad) != CfgIVal) {
+                   Val = CfgCheckedIntExpr (1, 0x10000);
+                           S->AlignLoad = BitFind (Val);
+                   if ((0x01L << S->AlignLoad) != Val) {
                        CfgError ("Alignment must be a power of 2");
                    }
                    S->Flags |= SF_ALIGN_LOAD;
@@ -702,18 +701,18 @@ static void ParseSegments (void)
                    if (CfgTok == CFGTOK_TRUE) {
                        S->Flags |= SF_DEFINE;
                    }
+                    CfgNextTok ();
                    break;
 
                case CFGTOK_LOAD:
                    FlagAttr (&S->Attr, SA_LOAD, "LOAD");
                    S->Load = CfgGetMemory (GetStringId (CfgSVal));
+                    CfgNextTok ();
                    break;
 
                case CFGTOK_OFFSET:
-                   CfgAssureInt ();
                    FlagAttr (&S->Attr, SA_OFFSET, "OFFSET");
-                   CfgRangeCheck (1, 0x1000000);
-                   S->Addr   = CfgIVal;
+                   S->Addr   = CfgCheckedIntExpr (1, 0x1000000);
                    S->Flags |= SF_OFFSET;
                    break;
 
@@ -723,18 +722,18 @@ static void ParseSegments (void)
                    if (CfgTok == CFGTOK_TRUE) {
                        S->Flags |= SF_OPTIONAL;
                    }
+                    CfgNextTok ();
                    break;
 
                case CFGTOK_RUN:
                    FlagAttr (&S->Attr, SA_RUN, "RUN");
                    S->Run = CfgGetMemory (GetStringId (CfgSVal));
+                    CfgNextTok ();
                    break;
 
                case CFGTOK_START:
-                   CfgAssureInt ();
                    FlagAttr (&S->Attr, SA_START, "START");
-                   CfgRangeCheck (1, 0x1000000);
-                   S->Addr   = CfgIVal;
+                   S->Addr   = CfgCheckedIntExpr (1, 0x1000000);
                    S->Flags |= SF_START;
                    break;
 
@@ -748,6 +747,7 @@ static void ParseSegments (void)
                        case CFGTOK_ZP:    S->Flags |= (SF_BSS | SF_ZP);    break;
                        default:           Internal ("Unexpected token: %d", CfgTok);
                    }
+                    CfgNextTok ();
                    break;
 
                default:
@@ -755,8 +755,7 @@ static void ParseSegments (void)
 
            }
 
-           /* Skip the attribute value and an optional comma */
-           CfgNextTok ();
+           /* Skip an optional comma */
            CfgOptionalComma ();
        }
 
@@ -921,6 +920,8 @@ static void ParseO65 (void)
                }
                /* Insert the symbol into the table */
                O65SetExport (O65FmtDesc, CfgSValId);
+                /* Eat the identifier token */
+                CfgNextTok ();
                break;
 
            case CFGTOK_IMPORT:
@@ -943,6 +944,8 @@ static void ParseO65 (void)
                }
                /* Insert the symbol into the table */
                O65SetImport (O65FmtDesc, CfgSValId);
+                /* Eat the identifier token */
+                CfgNextTok ();
                break;
 
            case CFGTOK_TYPE:
@@ -963,6 +966,8 @@ static void ParseO65 (void)
                    default:
                        CfgError ("Unexpected type token");
                }
+                /* Eat the attribute token */
+                CfgNextTok ();
                break;
 
            case CFGTOK_OS:
@@ -984,24 +989,21 @@ static void ParseO65 (void)
                         default:              CfgError ("Unexpected OS token");
                     }
                 }
+                CfgNextTok ();
                break;
 
             case CFGTOK_ID:
                 /* Cannot have this attribute twice */
                 FlagAttr (&AttrFlags, atID, "ID");
                 /* We're expecting a number in the 0..$FFFF range*/
-                CfgAssureInt ();
-                CfgRangeCheck (0, 0xFFFF);
-                ModuleId = (unsigned) CfgIVal;
+                ModuleId = (unsigned) CfgCheckedIntExpr (0, 0xFFFF);
                 break;
 
             case CFGTOK_VERSION:
                 /* Cannot have this attribute twice */
                 FlagAttr (&AttrFlags, atVersion, "VERSION");
                 /* We're expecting a number in byte range */
-                CfgAssureInt ();
-                CfgRangeCheck (0, 0xFF);
-                Version = (unsigned) CfgIVal;
+                Version = (unsigned) CfgCheckedIntExpr (0, 0xFF);
                 break;
 
            default:
@@ -1009,8 +1011,7 @@ static void ParseO65 (void)
 
        }
 
-       /* Skip the attribute value and an optional comma */
-       CfgNextTok ();
+       /* Skip an optional comma */
        CfgOptionalComma ();
     }
 
@@ -1267,11 +1268,8 @@ static void ParseStartAddress (void)
            case CFGTOK_DEFAULT:
                /* Don't allow this twice */
                FlagAttr (&AttrFlags, atDefault, "DEFAULT");
-               /* We expect a number */
-               CfgAssureInt ();
-                CfgRangeCheck (0, 0xFFFFFF);
-               /* Remember the value for later */
-                DefStartAddr = CfgIVal;
+               /* We expect a numeric expression */
+                DefStartAddr = CfgCheckedIntExpr (0, 0xFFFFFF);
                break;
 
            default:
@@ -1279,9 +1277,6 @@ static void ParseStartAddress (void)
 
        }
 
-               /* Skip the attribute value */
-       CfgNextTok ();
-
        /* Semicolon ends the ConDes decl, otherwise accept an optional comma */
        if (CfgTok == CFGTOK_SEMI) {
            break;
@@ -1376,16 +1371,16 @@ static void ParseSymbols (void)
             /* Allow an optional assignment */
             CfgOptionalAssign ();
 
-            /* Make sure the next token is an integer, read and skip it */
-            CfgAssureInt ();
-            Val = CfgIVal;
-            CfgNextTok ();
+            /* Make sure the next token is an integer expression, read and
+             * skip it.
+             */
+            Val = CfgIntExpr ();
 
         } else {
 
             /* Bitmask to remember the attributes we got already */
             enum {
-                atNone         = 0x0000,
+                atNone         = 0x0000,
                 atValue         = 0x0001,
                 atWeak          = 0x0002
             };
@@ -1403,8 +1398,10 @@ static void ParseSymbols (void)
                 CfgSpecialToken (Attributes, ENTRY_COUNT (Attributes), "Attribute");
                 AttrTok = CfgTok;
 
-                /* An optional assignment follows */
+                /* Skip the attribute name */
                 CfgNextTok ();
+
+                /* An optional assignment follows */
                 CfgOptionalAssign ();
 
                 /* Check which attribute was given */
@@ -1413,10 +1410,8 @@ static void ParseSymbols (void)
                     case CFGTOK_VALUE:
                         /* Don't allow this twice */
                         FlagAttr (&AttrFlags, atValue, "VALUE");
-                        /* We expect a number */
-                        CfgAssureInt ();
-                        /* Remember the value for later */
-                        Val = CfgIVal;
+                        /* We expect a numeric expression */
+                        Val = CfgIntExpr ();
                         break;
 
                     case CFGTOK_WEAK:
@@ -1424,6 +1419,7 @@ static void ParseSymbols (void)
                         FlagAttr (&AttrFlags, atWeak, "WEAK");
                         CfgBoolToken ();
                         Weak = (CfgTok == CFGTOK_TRUE);
+                        CfgNextTok ();
                         break;
 
                     default:
@@ -1431,9 +1427,6 @@ static void ParseSymbols (void)
 
                 }
 
-                /* Skip the attribute value */
-                CfgNextTok ();
-
                 /* Semicolon ends the decl, otherwise accept an optional comma */
                 if (CfgTok == CFGTOK_SEMI) {
                     break;
index ab4f20fd8b03e089532f5924ef33744613edea76..c8112c61ebfd597ebc816f7c93de5f5de9c190fb 100644 (file)
@@ -24,6 +24,7 @@ CVT=cfg/cvt-cfg.pl
 OBJS =         asserts.o       \
         bin.o          \
        binfmt.o        \
+        cfgexpr.o       \
        condes.o        \
        config.o        \
         dbgfile.o       \
index 6246441bb498c7fc934cc8f357eaf5520bca8c8a..c288ed5fcd32fe4de53583262049ba5da5283236 100644 (file)
@@ -63,6 +63,7 @@ endif
 OBJS = asserts.obj     \
         bin.obj                \
        binfmt.obj      \
+        cfgexpr.obj     \
        condes.obj      \
        config.obj      \
         dbgfile.obj     \
index 8767c368c04076d60818e55d481ce5f6e283f19b..d67e6327da51a212ab01217124ee40f55e507239 100644 (file)
@@ -225,6 +225,36 @@ Again:
     /* Other characters */
     switch (C) {
 
+        case '-':
+            NextChar ();
+            CfgTok = CFGTOK_MINUS;
+            break;
+
+        case '+':
+            NextChar ();
+            CfgTok = CFGTOK_PLUS;
+            break;
+
+        case '*':
+            NextChar ();
+            CfgTok = CFGTOK_MUL;
+            break;
+
+        case '/':
+            NextChar ();
+            CfgTok = CFGTOK_DIV;
+            break;
+
+       case '(':
+           NextChar ();
+           CfgTok = CFGTOK_LPAR;
+           break;
+
+       case ')':
+           NextChar ();
+           CfgTok = CFGTOK_RPAR;
+           break;
+
        case '{':
            NextChar ();
            CfgTok = CFGTOK_LCURLY;
index 9f2efa4d8e28dc4dc5574fc28fcf54780091ed8d..f7f6caca5645b9833a9037780d3d8b47746a95b9 100644 (file)
 /* Config file tokens */
 typedef enum {
     CFGTOK_NONE,
-    CFGTOK_INTCON,
-    CFGTOK_STRCON,
-    CFGTOK_IDENT,
+    CFGTOK_INTCON,              /* Integer constant */
+    CFGTOK_STRCON,              /* String constant */
+    CFGTOK_IDENT,               /* Identifier */
+    CFGTOK_PLUS,
+    CFGTOK_MINUS,
+    CFGTOK_MUL,
+    CFGTOK_DIV,
+    CFGTOK_LPAR,
+    CFGTOK_RPAR,
     CFGTOK_LCURLY,
     CFGTOK_RCURLY,
     CFGTOK_SEMI,