]> git.sur5r.net Git - cc65/blobdiff - src/ca65/pseudo.c
Allow optional assignments in .export and .exportzp statements.
[cc65] / src / ca65 / pseudo.c
index c0fcfcab846422b6eb77a2479bafc28c0f1fa4ad..e7e5d1a6eaec6edbf568786f1ad9d1dcb385d83d 100644 (file)
@@ -6,10 +6,10 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 1998-2003 Ullrich von Bassewitz                                       */
-/*               Römerstraße 52                                              */
-/*               D-70794 Filderstadt                                         */
-/* EMail:        uz@cc65.org                                                 */
+/* (C) 1998-2007, Ullrich von Bassewitz                                      */
+/*                Roemerstrasse 52                                           */
+/*                D-70794 Filderstadt                                        */
+/* EMail:         uz@cc65.org                                                */
 /*                                                                           */
 /*                                                                           */
 /* This software is provided 'as-is', without any expressed or implied       */
@@ -165,6 +165,33 @@ static void SetBoolOption (unsigned char* Flag)
 
 
 
+static void ExportWithAssign (SymEntry* Sym, unsigned char AddrSize, unsigned Flags)
+/* Allow to assign the value of an export in an .export statement */
+{
+    /* The name and optional address size spec may be followed by an assignment
+     * or equal token.
+     */
+    if (Tok == TOK_ASSIGN || Tok == TOK_EQ) {
+
+        /* Assignment means the symbol is a label */
+        if (Tok == TOK_ASSIGN) {
+            Flags |= SF_LABEL;
+        }
+
+        /* Skip the assignment token */
+        NextTok ();
+
+        /* Define the symbol with the expression following the '=' */
+        SymDef (Sym, Expression(), ADDR_SIZE_DEFAULT, Flags);
+
+    }
+
+    /* Now export the symbol */
+    SymExport (Sym, AddrSize, Flags);
+}
+
+
+
 static void ExportImport (void (*Func) (SymEntry*, unsigned char, unsigned),
                           unsigned char DefAddrSize, unsigned Flags)
 /* Export or import symbols */
@@ -269,7 +296,7 @@ static void DoA16 (void)
        Error ("Command is only valid in 65816 mode");
     } else {
                /* Immidiate mode has two extension bytes */
-       ExtBytes [AMI_IMM_ACCU] = 2;
+       ExtBytes [AM65I_IMM_ACCU] = 2;
     }
 }
 
@@ -282,7 +309,7 @@ static void DoA8 (void)
        Error ("Command is only valid in 65816 mode");
     } else {
        /* Immidiate mode has one extension byte */
-       ExtBytes [AMI_IMM_ACCU] = 1;
+       ExtBytes [AM65I_IMM_ACCU] = 1;
     }
 }
 
@@ -384,8 +411,8 @@ static void DoAssert (void)
         "ERROR"
     };
 
-    int Action;
-
+    int      Action;
+    unsigned Msg;
 
     /* First we have the expression that has to evaluated */
     ExprNode* Expr = Expression ();
@@ -414,15 +441,36 @@ static void DoAssert (void)
             Error ("Illegal assert action specifier");
     }
     NextTok ();
-    ConsumeComma ();
 
-    /* Read the message */
-    if (Tok != TOK_STRCON) {
-       ErrorSkip ("String constant expected");
-    } else {
-        AddAssertion (Expr, Action, GetStringId (SVal));
+    /* We can have an optional message. If no message is present, use
+     * "Assertion failed".
+     */
+    if (Tok == TOK_COMMA) {
+
+        /* Skip the comma */
         NextTok ();
+
+        /* Read the message */
+        if (Tok != TOK_STRCON) {
+            ErrorSkip ("String constant expected");
+            return;
+        }
+
+        /* Translate the message into a string id. We can then skip the input
+         * string.
+         */
+        Msg = GetStringId (SVal);
+        NextTok ();
+
+    } else {
+
+        /* Use "Assertion failed" */
+        Msg = GetStringId ("Assertion failed");
+
     }
+
+    /* Remember the assertion */
+    AddAssertion (Expr, Action, Msg);
 }
 
 
@@ -456,7 +504,7 @@ static void DoByte (void)
        } else {
            EmitByte (Expression ());
        }
-       if (Tok != TOK_COMMA) {
+       if (Tok != TOK_COMMA) {
            break;
        } else {
            NextTok ();
@@ -488,7 +536,7 @@ static void DoCharMap (void)
 
     /* Read the index as numerical value */
     Index = ConstExpression ();
-    if (Index < 1 || Index > 255) {
+    if (Index < 0 || Index > 255) {
        /* Value out of range */
                ErrorSkip ("Range error");
        return;
@@ -499,10 +547,10 @@ static void DoCharMap (void)
 
     /* Read the character code */
     Code = ConstExpression ();
-    if (Code < 1 || Code > 255) {
-       /* Value out of range */
+    if (Code < 0 || Code > 255) {
+       /* Value out of range */
                ErrorSkip ("Range error");
-       return;
+       return;
     }
 
     /* Set the character translation */
@@ -525,6 +573,7 @@ static void DoConDes (void)
     static const char* Keys[] = {
                "CONSTRUCTOR",
        "DESTRUCTOR",
+        "INTERRUPTOR",
     };
     char Name [sizeof (SVal)];
     long Type;
@@ -760,7 +809,7 @@ static void DoExitMacro (void)
 static void DoExport (void)
 /* Export a symbol */
 {
-    ExportImport (SymExport, ADDR_SIZE_DEFAULT, SF_NONE);
+    ExportImport (ExportWithAssign, ADDR_SIZE_DEFAULT, SF_NONE);
 }
 
 
@@ -768,7 +817,7 @@ static void DoExport (void)
 static void DoExportZP (void)
 /* Export a zeropage symbol */
 {
-    ExportImport (SymExport, ADDR_SIZE_ZP, SF_NONE);
+    ExportImport (ExportWithAssign, ADDR_SIZE_ZP, SF_NONE);
 }
 
 
@@ -942,7 +991,7 @@ static void DoI16 (void)
        Error ("Command is only valid in 65816 mode");
     } else {
                /* Immidiate mode has two extension bytes */
-       ExtBytes [AMI_IMM_INDEX] = 2;
+       ExtBytes [AM65I_IMM_INDEX] = 2;
     }
 }
 
@@ -955,7 +1004,7 @@ static void DoI8 (void)
        Error ("Command is only valid in 65816 mode");
     } else {
        /* Immidiate mode has one extension byte */
-       ExtBytes [AMI_IMM_INDEX] = 1;
+       ExtBytes [AM65I_IMM_INDEX] = 1;
     }
 }
 
@@ -1084,20 +1133,35 @@ Done:
 static void DoInclude (void)
 /* Include another file */
 {
-    char Name [MAX_STR_LEN+1];
-
     /* Name must follow */
     if (Tok != TOK_STRCON) {
        ErrorSkip ("String constant expected");
     } else {
-       strcpy (Name, SVal);
-       NextTok ();
-       NewInputFile (Name);
+       NewInputFile (SVal);
     }
 }
 
 
 
+static void DoInterruptor (void)
+/* Export a symbol as interruptor */
+{
+    char Name [sizeof (SVal)];
+
+    /* Symbol name follows */
+    if (Tok != TOK_IDENT) {
+       ErrorSkip ("Identifier expected");
+       return;
+    }
+    strcpy (Name, SVal);
+    NextTok ();
+
+    /* Parse the remainder of the line and export the symbol */
+    ConDes (Name, CD_TYPE_INT);
+}
+
+
+
 static void DoInvalid (void)
 /* Handle a token that is invalid here, since it should have been handled on
  * a much lower level of the expression hierarchy. Getting this sort of token
@@ -1165,14 +1229,6 @@ static void DoLocalChar (void)
 static void DoMacPack (void)
 /* Insert a macro package */
 {
-    /* Macro package names */
-    static const char* Keys [] = {
-       "GENERIC",
-               "LONGBRANCH",
-        "CBM",
-        "CPU"
-    };
-
     int Package;
 
     /* We expect an identifier */
@@ -1181,19 +1237,16 @@ static void DoMacPack (void)
        return;
     }
 
-    /* Map the keyword to a number */
-    Package = GetSubKey (Keys, sizeof (Keys) / sizeof (Keys [0]));
+    /* Search for the macro package name */
+    Package = MacPackFind (SVal);
     if (Package < 0) {
        /* Not found */
        ErrorSkip ("Invalid macro package");
        return;
     }
 
-    /* Skip the package name */
-    NextTok ();
-
     /* Insert the package */
-    InsertMacPack (Package);
+    MacPackInsert (Package);
 }
 
 
@@ -1222,7 +1275,7 @@ static void DoOrg (void)
        Error ("Range error");
        return;
     }
-    SetAbsPC (PC);
+    EnterAbsoluteMode (PC);
 }
 
 
@@ -1307,11 +1360,13 @@ static void DoProc (void)
 
     if (Tok == TOK_IDENT) {
 
+        SymEntry* Sym;
+
        /* The new scope has a name. Remember it. */
         strcpy (Name, SVal);
 
         /* Search for the symbol, generate a new one if needed */
-       SymEntry* Sym = SymFind (CurrentScope, Name, SYM_ALLOC_NEW);
+               Sym = SymFind (CurrentScope, Name, SYM_ALLOC_NEW);
 
         /* Skip the scope name */
         NextTok ();
@@ -1363,7 +1418,7 @@ static void DoPushSeg (void)
 static void DoReloc (void)
 /* Enter relocatable mode */
 {
-    RelocMode = 1;
+    EnterRelocMode ();
 }
 
 
@@ -1479,12 +1534,16 @@ static void DoSetCPU (void)
     if (Tok != TOK_STRCON) {
        ErrorSkip ("String constant expected");
     } else {
-        /* Try to find the CPU, then skip the identifier */
+        /* Try to find the CPU */
         cpu_t CPU = FindCPU (SVal);
-        NextTok ();
 
         /* Switch to the new CPU */
         SetCPU (CPU);
+
+        /* Skip the identifier. If the CPU switch was successful, the scanner
+         * will treat the input now correctly for the new CPU.
+         */
+        NextTok ();
     }
 }
 
@@ -1673,6 +1732,7 @@ static CtrlDesc CtrlCmdTab [] = {
     { ccNone,          DoUnexpected    },      /* .HIWORD */
     { ccNone,          DoI16           },
     { ccNone,          DoI8            },
+    { ccNone,           DoUnexpected    },      /* .IDENT */
     { ccKeepToken,     DoConditionals  },      /* .IF */
     { ccKeepToken,     DoConditionals  },      /* .IFBLANK */
     { ccKeepToken,     DoConditionals  },      /* .IFCONST */
@@ -1690,6 +1750,7 @@ static CtrlDesc CtrlCmdTab [] = {
     { ccNone,          DoImportZP      },
     { ccNone,          DoIncBin        },
     { ccNone,          DoInclude       },
+    { ccNone,           DoInterruptor   },
     { ccNone,          DoInvalid       },      /* .LEFT */
     { ccNone,          DoLineCont      },
     { ccNone,          DoList          },
@@ -1722,9 +1783,11 @@ static CtrlDesc CtrlCmdTab [] = {
     { ccNone,          DoROData        },
     { ccNone,           DoScope         },
     { ccNone,          DoSegment       },
+    { ccNone,           DoUnexpected    },      /* .SET */
     { ccNone,                  DoSetCPU        },
     { ccNone,           DoUnexpected    },      /* .SIZEOF */
     { ccNone,          DoSmart         },
+    { ccNone,           DoUnexpected    },      /* .SPRINTF */
     { ccNone,          DoUnexpected    },      /* .STRAT */
     { ccNone,                  DoUnexpected    },      /* .STRING */
     { ccNone,          DoUnexpected    },      /* .STRLEN */
@@ -1760,7 +1823,7 @@ void HandlePseudo (void)
     /* Safety check */
     if (PSEUDO_COUNT != (TOK_LASTPSEUDO - TOK_FIRSTPSEUDO + 1)) {
        Internal ("Pseudo mismatch: PSEUDO_COUNT = %u, actual count = %u\n",
-                 PSEUDO_COUNT, TOK_LASTPSEUDO - TOK_FIRSTPSEUDO + 1);
+                         (unsigned) PSEUDO_COUNT, TOK_LASTPSEUDO - TOK_FIRSTPSEUDO + 1);
     }
     CHECK (Index < PSEUDO_COUNT);