]> git.sur5r.net Git - cc65/blobdiff - src/ca65/expr.c
Error message for negative array sizes.
[cc65] / src / ca65 / expr.c
index 0675a8c7b50c9bb8c968b7ad24f414c8cc687add..0c638c6422fb04a27e3a50f1893d9ed8f43a6343 100644 (file)
@@ -6,7 +6,7 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 1998-2000 Ullrich von Bassewitz                                       */
+/* (C) 1998-2003 Ullrich von Bassewitz                                       */
 /*               Wacholderweg 14                                             */
 /*               D-70597 Stuttgart                                           */
 /* EMail:        uz@musoftware.de                                            */
 
 
 
+#include <string.h>
+#include <time.h>
+
 /* common */
 #include "check.h"
 #include "exprdefs.h"
+#include "print.h"
 #include "tgttrans.h"
 #include "xmalloc.h"
 
@@ -156,7 +160,7 @@ static int FuncBlank (void)
     } else {
        /* Skip any tokens */
        int Braces = 0;
-       while (Tok != TOK_SEP && Tok != TOK_EOF) {
+       while (!TokIsSep (Tok)) {
            if (Tok == TOK_LPAREN) {
                ++Braces;
            } else if (Tok == TOK_RPAREN) {
@@ -196,18 +200,69 @@ static int FuncConst (void)
 static int FuncDefined (void)
 /* Handle the .DEFINED builtin function */
 {
+    static const char* Keys[] = {
+               "ANY",
+       "GLOBAL",
+        "LOCAL",
+    };
+
+    char Name [sizeof (SVal)];
     int Result = 0;
+    int Scope;
 
+    /* First argument is a symbol name */
     if (Tok != TOK_IDENT) {
        Error (ERR_IDENT_EXPECTED);
        if (Tok != TOK_RPAREN) {
            NextTok ();
        }
+        return 0;
+    }
+
+    /* Remember the name, then skip it */
+    strcpy (Name, SVal);
+    NextTok ();
+
+    /* Comma and scope spec may follow */
+    if (Tok == TOK_COMMA) {
+
+        /* Skip the comma */
+        NextTok ();
+
+        /* An identifier must follow */
+        if (Tok != TOK_IDENT) {
+            Error (ERR_IDENT_EXPECTED);
+            return 0;
+        }
+
+        /* Get the scope, then skip it */
+        Scope = GetSubKey (Keys, sizeof (Keys) / sizeof (Keys [0]));
+        NextTok ();
+
+        /* Check if we got a valid keyword */
+        if (Scope < 0) {
+            Error (ERR_ILLEGAL_SCOPE);
+            return 0;
+        }
+
+        /* Map the scope */
+        switch (Scope) {
+            case 0:     Scope = SCOPE_ANY;    break;
+            case 1:     Scope = SCOPE_GLOBAL; break;
+            case 2:     Scope = SCOPE_LOCAL;  break;
+            default:    Internal ("Invalid scope: %d", Scope);
+        }
+
     } else {
-       Result = SymIsDef (SVal);
-       NextTok ();
+
+        /* Any scope */
+        Scope = SCOPE_ANY;
+
     }
 
+    /* Search for the symbol */
+    Result = SymIsDef (SVal, Scope);
+
     /* Done */
     return Result;
 }
@@ -229,7 +284,7 @@ static int DoMatch (enum TC EqualityLevel)
     while (Tok != TOK_COMMA) {
 
        /* We may not end-of-line of end-of-file here */
-       if (Tok == TOK_SEP || Tok == TOK_EOF) {
+       if (TokIsSep (Tok)) {
            Error (ERR_UNEXPECTED_EOL);
            return 0;
        }
@@ -260,7 +315,7 @@ static int DoMatch (enum TC EqualityLevel)
     while (Tok != TOK_RPAREN) {
 
        /* We may not end-of-line of end-of-file here */
-       if (Tok == TOK_SEP || Tok == TOK_EOF) {
+       if (TokIsSep (Tok)) {
            Error (ERR_UNEXPECTED_EOL);
            return 0;
        }
@@ -322,7 +377,7 @@ static int FuncReferenced (void)
            NextTok ();
        }
     } else {
-       Result = SymIsRef (SVal);
+       Result = SymIsRef (SVal, SCOPE_ANY);
        NextTok ();
     }
 
@@ -357,13 +412,15 @@ static int FuncStrAt (void)
     Index = ConstExpression ();
 
     /* Must be a valid index */
-    if (Index >= strlen (Str)) {
+    if (Index >= (long) strlen (Str)) {
        Error (ERR_RANGE);
        return 0;
     }
 
-    /* Return the char, handle as unsigned */
-    return (unsigned char) Str[(size_t)Index];
+    /* Return the char, handle as unsigned. Be sure to translate it into
+     * the target character set.
+     */
+    return (unsigned char) TgtTranslateChar (Str [(size_t)Index]);
 }
 
 
@@ -411,7 +468,7 @@ static int FuncTCount (void)
         * will check for the closing paren, we don't need to print an error
         * here, just bail out.
         */
-       if (Tok == TOK_SEP || Tok == TOK_EOF) {
+       if (TokIsSep (Tok)) {
            break;
        }
 
@@ -494,7 +551,7 @@ static ExprNode* Factor (void)
                Error (ERR_IDENT_EXPECTED);
                N = LiteralExpr (0);    /* Dummy */
            } else {
-               S = SymRefGlobal (SVal);
+               S = SymRef (SVal, SCOPE_GLOBAL);
                if (SymIsConst (S)) {
                    /* Use the literal value instead */
                    N = LiteralExpr (GetSymVal (S));
@@ -509,7 +566,7 @@ static ExprNode* Factor (void)
            break;
 
         case TOK_IDENT:
-           S = SymRef (SVal);
+           S = SymRef (SVal, SCOPE_LOCAL);
            if (SymIsConst (S)) {
                /* Use the literal value instead */
                N = LiteralExpr (GetSymVal (S));
@@ -604,13 +661,23 @@ static ExprNode* Factor (void)
            N = Function (FuncTCount);
            break;
 
+       case TOK_TIME:
+           N = LiteralExpr (time (0));
+           NextTok ();
+           break;
+
        case TOK_XMATCH:
            N = Function (FuncXMatch);
            break;
 
        default:
-           N = LiteralExpr (0);        /* Dummy */
-           Error (ERR_SYNTAX);
+           if (LooseCharTerm && Tok == TOK_STRCON && strlen(SVal) == 1) {
+               /* A character constant */
+               N = LiteralExpr (TgtTranslateChar (SVal[0]));
+           } else {
+               N = LiteralExpr (0);    /* Dummy */
+               Error (ERR_SYNTAX);
+           }
            NextTok ();
            break;
     }
@@ -904,7 +971,7 @@ ExprNode* CurrentPC (void)
     if (RelocMode) {
        /* Create SegmentBase + Offset */
        Left = NewExprNode ();
-       Left->Op = EXPR_SEGMENT;
+       Left->Op = EXPR_SECTION;
        Left->V.SegNum = GetSegNum ();
 
        Root = NewExprNode ();
@@ -944,7 +1011,7 @@ ExprNode* BranchExpr (unsigned Offs)
     /* Create *+Offs */
     if (RelocMode) {
        Left = NewExprNode ();
-       Left->Op = EXPR_SEGMENT;
+       Left->Op = EXPR_SECTION;
        Left->V.SegNum = GetSegNum ();
 
        N = NewExprNode ();
@@ -1027,7 +1094,7 @@ int IsConstExpr (ExprNode* Root)
            case EXPR_SYMBOL:
                Sym = Root->V.Sym;
                if (SymHasUserMark (Sym)) {
-                   if (Verbose) {
+                   if (Verbosity > 0) {
                        DumpExpr (Root);
                    }
                    PError (GetSymPos (Sym), ERR_CIRCULAR_REFERENCE);
@@ -1100,13 +1167,16 @@ static void CheckByteExpr (const ExprNode* N, int* IsByte)
            case EXPR_LEAFNODE:
                switch (N->Op) {
 
-                   case EXPR_SYMBOL:
-                       if (SymIsZP (N->V.Sym)) {
-                           *IsByte = 1;
-                       }
+                   case EXPR_SYMBOL:
+                       if (SymIsZP (N->V.Sym)) {
+                           *IsByte = 1;
+                       } else if (SymHasExpr (N->V.Sym)) {
+                           /* Check if this expression is a byte expression */
+                           *IsByte = IsByteExpr (GetSymExpr (N->V.Sym));
+                       }
                        break;
 
-                   case EXPR_SEGMENT:
+                   case EXPR_SECTION:
                        if (GetSegType (N->V.SegNum) == SEGTYPE_ZP) {
                            *IsByte = 1;
                        }
@@ -1299,7 +1369,7 @@ static ExprNode* RemoveSyms (ExprNode* Expr, int MustClone)
                SymEntry* Sym = Expr->V.Sym;
                if (SymHasUserMark (Sym)) {
                    /* Circular definition */
-                   if (Verbose) {
+                   if (Verbosity) {
                        DumpExpr (Expr);
                    }
                    PError (GetSymPos (Sym), ERR_CIRCULAR_REFERENCE);
@@ -1346,7 +1416,7 @@ static ExprNode* RemoveSyms (ExprNode* Expr, int MustClone)
                Clone->V.Sym = Expr->V.Sym;
                break;
 
-           case EXPR_SEGMENT:
+           case EXPR_SECTION:
                Clone->V.SegNum = Expr->V.SegNum;
                break;
 
@@ -1407,7 +1477,7 @@ static ExprNode* ConstExtract (ExprNode* Expr, long* Val, int Sign)
            return Left;
        } else {
            /* Check for SEG - SEG which is now possible */
-           if (Left->Op == EXPR_SEGMENT && Right->Op == EXPR_SEGMENT &&
+           if (Left->Op == EXPR_SECTION && Right->Op == EXPR_SECTION &&
                Left->V.SegNum == Right->V.SegNum) {
                /* SEG - SEG, remove it completely */
                FreeExprNode (Left);
@@ -1493,7 +1563,7 @@ ExprNode* CloneExpr (ExprNode* Expr)
            Clone->V.Sym = Expr->V.Sym;
            break;
 
-       case EXPR_SEGMENT:
+       case EXPR_SECTION:
            Clone->V.SegNum = Expr->V.SegNum;
            break;
 
@@ -1536,7 +1606,7 @@ void WriteExpr (ExprNode* Expr)
            ObjWrite16 (GetSymIndex (Expr->V.Sym));
            break;
 
-        case EXPR_SEGMENT:
+        case EXPR_SECTION:
            ObjWrite8 (Expr->V.SegNum);
            break;