1 /*****************************************************************************/
5 /* Simple expressions for use with in configuration file */
9 /* (C) 2005-2011, Ullrich von Bassewitz */
10 /* Roemerstrasse 52 */
11 /* D-70794 Filderstadt */
12 /* EMail: uz@cc65.org */
15 /* This software is provided 'as-is', without any expressed or implied */
16 /* warranty. In no event will the authors be held liable for any damages */
17 /* arising from the use of this software. */
19 /* Permission is granted to anyone to use this software for any purpose, */
20 /* including commercial applications, and to alter it and redistribute it */
21 /* freely, subject to the following restrictions: */
23 /* 1. The origin of this software must not be misrepresented; you must not */
24 /* claim that you wrote the original software. If you use this software */
25 /* in a product, an acknowledgment in the product documentation would be */
26 /* appreciated but is not required. */
27 /* 2. Altered source versions must be plainly marked as such, and must not */
28 /* be misrepresented as being the original software. */
29 /* 3. This notice may not be removed or altered from any source */
32 /*****************************************************************************/
51 /*****************************************************************************/
53 /*****************************************************************************/
57 static ExprNode* Factor (void)
58 /* Read and return a factor */
60 ExprNode* N = 0; /* Initialize to avoid compiler warnings */
68 /* Get the name as an id */
69 Name = GetStrBufId (&CfgSVal);
71 /* Check if we know the symbol already */
72 E = FindExport (Name);
73 if (E != 0 && IsConstExport (E)) {
74 N = LiteralExpr (GetExportVal (E), 0);
76 N = NewExprNode (0, EXPR_SYMBOL);
77 N->V.Imp = InsertImport (GenImport (Name, ADDR_SIZE_ABS));
78 CollAppend (&N->V.Imp->RefLines, GenLineInfo (&CfgErrorPos));
81 /* Skip the symbol name */
86 /* An integer constant */
87 N = LiteralExpr (CfgIVal, 0);
100 N = NewExprNode (0, EXPR_UNARY_MINUS);
105 /* Left parenthesis */
108 CfgConsume (CFGTOK_RPAR, "')' expected");
112 CfgError (&CfgErrorPos, "Invalid expression: %d", CfgTok);
116 /* Return the new expression node */
122 static ExprNode* Term (void)
123 /* Multiplicative operators: * and / */
125 /* Read left hand side */
126 ExprNode* Root = Factor ();
128 /* Handle multiplicative operators */
129 while (CfgTok == CFGTOK_MUL || CfgTok == CFGTOK_DIV) {
135 /* Remember the token, then skip it */
136 cfgtok_t Tok = CfgTok;
139 /* Move root to left side, then read right side */
143 /* Handle the operation */
145 case CFGTOK_MUL: Op = EXPR_MUL; break;
146 case CFGTOK_DIV: Op = EXPR_DIV; break;
147 default: Internal ("Unhandled token in Term: %d", Tok);
149 Root = NewExprNode (0, Op);
154 /* Return the expression tree we've created */
160 static ExprNode* SimpleExpr (void)
161 /* Additive operators: + and - */
163 /* Read left hand side */
164 ExprNode* Root = Term ();
166 /* Handle additive operators */
167 while (CfgTok == CFGTOK_PLUS || CfgTok == CFGTOK_MINUS) {
173 /* Remember the token, then skip it */
174 cfgtok_t Tok = CfgTok;
177 /* Move root to left side, then read right side */
181 /* Handle the operation */
183 case CFGTOK_PLUS: Op = EXPR_PLUS; break;
184 case CFGTOK_MINUS: Op = EXPR_MINUS; break;
185 default: Internal ("Unhandled token in SimpleExpr: %d", Tok);
187 Root = NewExprNode (0, Op);
192 /* Return the expression tree we've created */
198 ExprNode* CfgExpr (void)
199 /* Full expression */
201 return SimpleExpr ();
206 long CfgConstExpr (void)
207 /* Read an integer expression, make sure its constant and return its value */
211 /* Parse the expression */
212 ExprNode* Expr = CfgExpr ();
214 /* Check that it's const */
215 if (!IsConstExpr (Expr)) {
216 CfgError (&CfgErrorPos, "Constant expression expected");
220 Val = GetExprVal (Expr);
225 /* Return the value */
231 long CfgCheckedConstExpr (long Min, long Max)
232 /* Read an expression, make sure it's an int and in range, then return its
237 long Val = CfgConstExpr ();
239 /* Check the range */
240 if (Val < Min || Val > Max) {
241 CfgError (&CfgErrorPos, "Range error");
244 /* Return the value */