]> git.sur5r.net Git - cc65/blobdiff - src/ca65/expr.c
New .FEATURE org_per_seg. If enabled, .org/.reloc do only influence the
[cc65] / src / ca65 / expr.c
index 417ca11cc641636fc77423e4e6b655d87b3ae4ac..fc64f29c7e879fd0a14d38057cb0aa919dbb64c0 100644 (file)
@@ -6,8 +6,8 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 1998-2003 Ullrich von Bassewitz                                       */
-/*               Römerstraße 52                                              */
+/* (C) 1998-2007 Ullrich von Bassewitz                                       */
+/*               Roemerstrasse 52                                            */
 /*               D-70794 Filderstadt                                         */
 /* EMail:        uz@cc65.org                                                 */
 /*                                                                           */
@@ -305,8 +305,15 @@ static ExprNode* Symbol (SymEntry* S)
     } else {
         /* Mark the symbol as referenced */
         SymRef (S);
-        /* Create symbol node */
-        return GenSymExpr (S);
+        /* If the symbol is a variable, return just its value, otherwise
+         * return a reference to the symbol.
+         */
+        if (SymIsVar (S)) {
+            return CloneExpr (GetSymExpr (S));
+        } else {
+            /* Create symbol node */
+            return GenSymExpr (S);
+        }
     }
 }
 
@@ -323,31 +330,35 @@ static ExprNode* FuncBankByte (void)
 static ExprNode* FuncBlank (void)
 /* Handle the .BLANK builtin function */
 {
-    int Result = 1;
-
-    /* Assume no tokens if the closing brace follows (this is not correct in
-     * all cases, since the token may be the closing brace, but this will
-     * give a syntax error anyway and may not be handled by .BLANK.
+    /* We have a list of tokens that ends with the closing paren. Skip
+     * the tokens, and count them. Allow optionally curly braces.
      */
-    if (Tok != TOK_RPAREN) {
-       /* Skip any tokens */
-       int Braces = 0;
-       while (!TokIsSep (Tok)) {
-           if (Tok == TOK_LPAREN) {
-               ++Braces;
-           } else if (Tok == TOK_RPAREN) {
-               if (Braces == 0) {
-                   /* Done */
-                   break;
-               } else {
-                   --Braces;
-               }
-           }
-           NextTok ();
+    enum Token Term = GetTokListTerm (TOK_RPAREN);
+    unsigned Count = 0;
+    while (Tok != Term) {
+
+       /* Check for end of line or end of input. Since the calling function
+        * will check for the closing paren, we don't need to print an error
+        * here, just bail out.
+        */
+       if (TokIsSep (Tok)) {
+           break;
        }
-       return 0;
+
+       /* One more token */
+       ++Count;
+
+       /* Skip the token */
+       NextTok ();
     }
-    return GenLiteralExpr (Result);
+
+    /* If the list was enclosed in curly braces, skip the closing brace */
+    if (Term == TOK_RCURLY && Tok == TOK_RCURLY) {
+        NextTok ();
+    }
+
+    /* Return true if the list was empty */
+    return GenLiteralExpr (Count == 0);
 }
 
 
@@ -420,18 +431,19 @@ static ExprNode* DoMatch (enum TC EqualityLevel)
     int Result;
     TokNode* Root = 0;
     TokNode* Last = 0;
-    TokNode* Node = 0;
+    TokNode* Node;
 
     /* A list of tokens follows. Read this list and remember it building a
      * single linked list of tokens including attributes. The list is
-     * terminated by a comma.
+     * either enclosed in curly braces, or terminated by a comma.
      */
-    while (Tok != TOK_COMMA) {
+    enum Token Term = GetTokListTerm (TOK_COMMA);
+    while (Tok != Term) {
 
        /* We may not end-of-line of end-of-file here */
        if (TokIsSep (Tok)) {
            Error ("Unexpected end of line");
-           return 0;
+           return GenLiteral0 ();
        }
 
        /* Get a node with this token */
@@ -449,20 +461,27 @@ static ExprNode* DoMatch (enum TC EqualityLevel)
        NextTok ();
     }
 
-    /* Skip the comma */
+    /* Skip the terminator token*/
     NextTok ();
 
-    /* Read the second list which is terminated by the right parenthesis and
-     * compare each token against the one in the first list.
+    /* If the token list was enclosed in curly braces, we expect a comma */
+    if (Term == TOK_RCURLY) {
+        ConsumeComma ();
+    }
+
+    /* Read the second list which is optionally enclosed in curly braces and
+     * terminated by the right parenthesis. Compare each token against the
+     * one in the first list.
      */
+    Term = GetTokListTerm (TOK_RPAREN);
     Result = 1;
     Node = Root;
-    while (Tok != TOK_RPAREN) {
+    while (Tok != Term) {
 
        /* We may not end-of-line of end-of-file here */
        if (TokIsSep (Tok)) {
            Error ("Unexpected end of line");
-           return 0;
+           return GenLiteral0 ();
        }
 
                /* Compare the tokens if the result is not already known */
@@ -485,6 +504,11 @@ static ExprNode* DoMatch (enum TC EqualityLevel)
        NextTok ();
     }
 
+    /* If the token list was enclosed in curly braces, eat the closing brace */
+    if (Term == TOK_RCURLY) {
+        NextTok ();
+    }
+
     /* Check if there are remaining tokens in the first list */
     if (Node != 0) {
        Result = 0;
@@ -563,7 +587,7 @@ static ExprNode* FuncSizeOf (void)
         if (ParentScope == 0) {
             /* No such scope */
             DoneStrBuf (&ScopeName);
-            return GenLiteralExpr (0);
+            return GenLiteral0 ();
         }
 
         /* If ScopeName is empty, no explicit scope was specified. We have to
@@ -627,8 +651,7 @@ static ExprNode* FuncStrAt (void)
     if (Tok != TOK_STRCON) {
        Error ("String constant expected");
        NextTok ();
-               return 0;
-
+               return GenLiteral0 ();
     }
 
     /* Remember the string and skip it */
@@ -644,7 +667,7 @@ static ExprNode* FuncStrAt (void)
     /* Must be a valid index */
     if (Index >= (long) strlen (Str)) {
        Error ("Range error");
-       return 0;
+       return GenLiteral0 ();
     }
 
     /* Get the char, handle as unsigned. Be sure to translate it into
@@ -692,11 +715,11 @@ static ExprNode* FuncTCount (void)
 /* Handle the .TCOUNT function */
 {
     /* We have a list of tokens that ends with the closing paren. Skip
-     * the tokens, handling nested braces and count them.
+     * the tokens, and count them. Allow optionally curly braces.
      */
-    int      Count  = 0;
-    unsigned Parens = 0;
-    while (Parens != 0 || Tok != TOK_RPAREN) {
+    enum Token Term = GetTokListTerm (TOK_RPAREN);
+    int Count = 0;
+    while (Tok != Term) {
 
        /* Check for end of line or end of input. Since the calling function
         * will check for the closing paren, we don't need to print an error
@@ -709,17 +732,15 @@ static ExprNode* FuncTCount (void)
        /* One more token */
        ++Count;
 
-       /* Keep track of the nesting level */
-       switch (Tok) {
-           case TOK_LPAREN:    ++Parens;       break;
-           case TOK_RPAREN:    --Parens;       break;
-           default:                            break;
-       }
-
        /* Skip the token */
        NextTok ();
     }
 
+    /* If the list was enclosed in curly braces, skip the closing brace */
+    if (Term == TOK_RCURLY && Tok == TOK_RCURLY) {
+        NextTok ();
+    }
+
     /* Return the number of tokens */
     return GenLiteralExpr (Count);
 }
@@ -746,7 +767,7 @@ static ExprNode* Function (ExprNode* (*F) (void))
     if (Tok != TOK_LPAREN) {
        Error ("'(' expected");
        SkipUntilSep ();
-       return GenLiteralExpr (0);
+       return GenLiteral0 ();
     }
     NextTok ();
 
@@ -795,6 +816,11 @@ static ExprNode* Factor (void)
            NextTok ();
            break;
 
+        case TOK_PLUS:
+            NextTok ();
+            N = Factor ();
+            break;
+
        case TOK_MINUS:
            NextTok ();
             L = Factor ();
@@ -926,7 +952,7 @@ static ExprNode* Factor (void)
                /* A character constant */
                N = GenLiteralExpr (TgtTranslateChar (SVal[0]));
            } else {
-               N = GenLiteralExpr (0); /* Dummy */
+               N = GenLiteral0 ();     /* Dummy */
                Error ("Syntax error");
            }
            NextTok ();
@@ -1402,6 +1428,14 @@ ExprNode* GenLiteralExpr (long Val)
 
 
 
+ExprNode* GenLiteral0 (void)
+/* Return an expression tree that encodes the the number zero */
+{
+    return GenLiteralExpr (0);
+}
+
+
+
 ExprNode* GenSymExpr (SymEntry* Sym)
 /* Return an expression node that encodes the given symbol */
 {
@@ -1448,7 +1482,7 @@ ExprNode* GenCurrentPC (void)
 {
     ExprNode* Root;
 
-    if (RelocMode) {
+    if (GetRelocMode ()) {
        /* Create SegmentBase + Offset */
                Root = GenAddExpr (GenSectionExpr (GetCurrentSegNum ()),
                            GenLiteralExpr (GetPC ()));
@@ -1497,7 +1531,7 @@ ExprNode* GenBranchExpr (unsigned Offs)
          * (Val - PC - Offs) - Seg
          */
         Root = GenLiteralExpr (Val - GetPC () - Offs);
-        if (RelocMode) {
+        if (GetRelocMode ()) {
             N = Root;
             Root = NewExprNode (EXPR_MINUS);
             Root->Left  = N;
@@ -1515,7 +1549,7 @@ ExprNode* GenBranchExpr (unsigned Offs)
         Root = NewExprNode (EXPR_MINUS);
         Root->Left  = N;
         Root->Right = GenLiteralExpr (GetPC () + Offs);
-        if (RelocMode) {
+        if (GetRelocMode ()) {
             N = Root;
             Root = NewExprNode (EXPR_MINUS);
             Root->Left  = N;
@@ -1661,11 +1695,11 @@ void WriteExpr (ExprNode* Expr)
 
         case EXPR_LITERAL:
             ObjWrite8 (EXPR_LITERAL);
-           ObjWrite32 (Expr->V.Val);
-           break;
+           ObjWrite32 (Expr->V.Val);
+           break;
 
         case EXPR_SYMBOL:
-           if (SymIsImport (Expr->V.Sym)) {
+           if (SymIsImport (Expr->V.Sym)) {
                 ObjWrite8 (EXPR_SYMBOL);
                 ObjWriteVar (GetSymIndex (Expr->V.Sym));
             } else {
@@ -1694,4 +1728,41 @@ void WriteExpr (ExprNode* Expr)
 
 
 
+void ExprGuessedAddrSize (const ExprNode* Expr, unsigned char AddrSize)
+/* Mark the address size of the given expression tree as guessed. The address
+ * size passed as argument is the one NOT used, because the actual address
+ * size wasn't known. Example: Zero page addressing was not used because symbol
+ * is undefined, and absolute addressing was available.
+ * This function will actually parse the expression tree for undefined symbols,
+ * and mark these symbols accordingly.
+ */
+{
+    /* Accept NULL expressions */
+    if (Expr == 0) {
+        return;
+    }
+
+    /* Check the type code */
+    switch (Expr->Op & EXPR_TYPEMASK) {
+
+        case EXPR_LEAFNODE:
+            if (Expr->Op == EXPR_SYMBOL) {
+                if (!SymIsDef (Expr->V.Sym)) {
+                    /* Symbol is undefined, mark it */
+                    SymGuessedAddrSize (Expr->V.Sym, AddrSize);
+                }
+            }
+            return;
+
+        case EXPR_BINARYNODE:
+            ExprGuessedAddrSize (Expr->Right, AddrSize);
+            /* FALLTHROUGH */
+
+        case EXPR_UNARYNODE:
+            ExprGuessedAddrSize (Expr->Left, AddrSize);
+            break;
+    }
+}
+
+