]> git.sur5r.net Git - cc65/commitdiff
New .PUSHSEG and .POPSEG commands
authorcuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Thu, 28 Nov 2002 17:42:16 +0000 (17:42 +0000)
committercuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Thu, 28 Nov 2002 17:42:16 +0000 (17:42 +0000)
git-svn-id: svn://svn.cc65.org/cc65/trunk@1671 b7a2c559-68d2-44c3-8de9-860c34a00d81

src/ca65/error.c
src/ca65/error.h
src/ca65/main.c
src/ca65/objcode.c
src/ca65/objcode.h
src/ca65/pseudo.c
src/ca65/pseudo.h
src/ca65/scanner.c
src/ca65/scanner.h

index 2145818aa014e61b162e5a3c6d950996cda4a58c..f8f0eabfa953e43a6e51262a0784aa17ad9f074c 100644 (file)
@@ -184,6 +184,9 @@ void ErrorMsg (const FilePos* Pos, unsigned ErrNum, va_list ap)
                "Conditional assembly branch was never closed",
        "Lexical level was not terminated correctly",
        "Segment attribute mismatch",
+        "Segment stack overflow",
+        "Segment stack is empty",
+        "Segment stack is not empty at end of assembly",
        "CPU not supported",
        "Counter underflow",
        "Undefined label",
index 043931253b5980d8c2b52fb2838d952e8c4d6de1..c6c9a772d2ef1b9a573b7d011a940c3c0e101887 100644 (file)
 
 
 /*****************************************************************************/
-/*                                  Data                                    */
+/*                                  Data                                    */
 /*****************************************************************************/
 
 
 
 /* Warning numbers */
 enum Warnings {
-    WARN_NONE,                         /* No warning */
+    WARN_NONE,                         /* No warning */
     WARN_MASK_ERROR,
     WARN_SYM_NOT_REFERENCED,
     WARN_IMPORT_NOT_REFERENCED,
@@ -125,6 +125,9 @@ enum Errors {
     ERR_OPEN_IF,
     ERR_OPEN_PROC,
     ERR_SEG_ATTR_MISMATCH,
+    ERR_SEGSTACK_OVERFLOW,
+    ERR_SEGSTACK_EMPTY,
+    ERR_SEGSTACK_NOT_EMPTY,
     ERR_CPU_NOT_SUPPORTED,
     ERR_COUNTER_UNDERFLOW,
     ERR_UNDEFINED_LABEL,
index 5f7f2ca282505b3f1ffac7c1e112343bc286c0b2..4fac8117cf07ea782a9f9cb368d90e1618d18701 100644 (file)
@@ -621,6 +621,11 @@ int main (int argc, char* argv [])
     /* Assemble the input */
     Assemble ();
 
+    /* If we didn't have any errors, check the segment stack */
+    if (ErrorCount == 0) {
+        SegStackCheck ();
+    }
+
     /* If we didn't have any errors, check the unnamed labels */
     if (ErrorCount == 0) {
         ULabCheck ();
index ccdec540df46d4f31def5a0fc3f1e2d5ab9c5221..f4429c6ffd0369ffa1b2a88cfc960f85018218ae 100644 (file)
@@ -70,36 +70,33 @@ unsigned long       AbsPC     = 0;          /* PC if in absolute mode */
 typedef struct Segment Segment;
 struct Segment {
     Segment*               List;               /* List of all segments */
-    Fragment*              Root;               /* Root of fragment list */
-    Fragment*              Last;               /* Pointer to last fragment */
-    unsigned char   Align;             /* Segment alignment */
-    unsigned char   SegType;                   /* True if zero page segment */
+    Fragment*              Root;               /* Root of fragment list */
+    Fragment*              Last;               /* Pointer to last fragment */
+    unsigned        Num;               /* Segment number */
+    unsigned        Align;             /* Segment alignment */
     unsigned long   PC;
-    unsigned               Num;                /* Segment number */
-    char*                  Name;               /* Segment name */
+    SegDef*         Def;                /* Segment definition (name and type) */
 };
 
 
+#define SEG(segdef, num, prev)      \
+    { prev, 0, 0, num, 0, 0, segdef }
+
+/* Definitions for predefined segments */
+SegDef NullSegDef     = STATIC_SEGDEF_INITIALIZER ("NULL",     SEGTYPE_ABS);
+SegDef ZeropageSegDef = STATIC_SEGDEF_INITIALIZER ("ZEROPAGE", SEGTYPE_ZP);
+SegDef DataSegDef     = STATIC_SEGDEF_INITIALIZER ("DATA",     SEGTYPE_ABS);
+SegDef BssSegDef      = STATIC_SEGDEF_INITIALIZER ("BSS",      SEGTYPE_ABS);
+SegDef RODataSegDef   = STATIC_SEGDEF_INITIALIZER ("RODATA",   SEGTYPE_ABS);
+SegDef CodeSegDef     = STATIC_SEGDEF_INITIALIZER ("CODE",     SEGTYPE_ABS);
 
 /* Predefined segments */
-static Segment NullSeg = {
-    0, 0, 0, 0, SEGTYPE_ABS, 0, 5, "NULL"
-};
-static Segment ZeropageSeg = {
-    &NullSeg, 0, 0, 0, SEGTYPE_ZP, 0, 4, "ZEROPAGE"
-};
-static Segment DataSeg = {
-    &ZeropageSeg, 0, 0, 0, SEGTYPE_ABS, 0, 3, "DATA"
-};
-static Segment BssSeg = {
-    &DataSeg, 0, 0, 0, SEGTYPE_ABS, 0, 2, "BSS"
-};
-static Segment RODataSeg = {
-    &BssSeg, 0, 0, 0, SEGTYPE_ABS, 0, 1, "RODATA"
-};
-static Segment CodeSeg = {
-    &RODataSeg, 0, 0, 0, SEGTYPE_ABS, 0, 0, "CODE"
-};
+static Segment NullSeg     = SEG (&NullSegDef,     5, NULL);
+static Segment ZeropageSeg = SEG (&ZeropageSegDef, 4, &NullSeg);
+static Segment DataSeg     = SEG (&DataSegDef,     3, &ZeropageSeg);
+static Segment BssSeg      = SEG (&BssSegDef,      2, &DataSeg);
+static Segment RODataSeg   = SEG (&RODataSegDef,   1, &BssSeg);
+static Segment CodeSeg     = SEG (&CodeSegDef,     0, &RODataSeg);
 
 /* Number of segments */
 static unsigned SegmentCount = 6;
@@ -123,7 +120,6 @@ static Segment* NewSegment (const char* Name, unsigned SegType)
 /* Create a new segment, insert it into the global list and return it */
 {
     Segment* S;
-    const char* N;
 
     /* Check for too many segments */
     if (SegmentCount >= 256) {
@@ -131,30 +127,21 @@ static Segment* NewSegment (const char* Name, unsigned SegType)
     }
 
     /* Check the segment name for invalid names */
-    N = Name;
-    if ((*N != '_' && !IsAlpha (*N)) || strlen (Name) > 80) {
+    if (!ValidSegName (Name)) {
        Error (ERR_ILLEGAL_SEGMENT, Name);
     }
-    do {
-       if (*N != '_' && !IsAlNum (*N)) {
-           Error (ERR_ILLEGAL_SEGMENT, Name);
-           break;
-       }
-       ++N;
-    } while (*N);
 
     /* Create a new segment */
     S = xmalloc (sizeof (*S));
 
     /* Initialize it */
-    S->List    = 0;
-    S->Root    = 0;
-    S->Last    = 0;
-    S->Align   = 0;
-    S->SegType = SegType;
-    S->PC      = 0;
-    S->Num     = SegmentCount++;
-    S->Name    = xstrdup (Name);
+    S->List   = 0;
+    S->Root   = 0;
+    S->Last   = 0;
+    S->Num    = SegmentCount++;
+    S->Align  = 0;
+    S->PC     = 0;
+    S->Def    = NewSegDef (Name, SegType);
 
     /* Insert it into the segment list */
     SegmentLast->List = S;
@@ -166,65 +153,17 @@ static Segment* NewSegment (const char* Name, unsigned SegType)
 
 
 
-void UseCodeSeg (void)
-/* Use the code segment */
-{
-    ActiveSeg = &CodeSeg;
-}
-
-
-
-void UseRODataSeg (void)
-/* Use the r/o data segment */
-{
-    ActiveSeg = &RODataSeg;
-}
-
-
-
-void UseDataSeg (void)
-/* Use the data segment */
-{
-    ActiveSeg = &DataSeg;
-}
-
-
-
-void UseBssSeg (void)
-/* Use the BSS segment */
-{
-    ActiveSeg = &BssSeg;
-}
-
-
-
-void UseZeropageSeg (void)
-/* Use the zero page segment */
-{
-    ActiveSeg = &ZeropageSeg;
-}
-
-
-
-void UseNullSeg (void)
-/* Use the null segment */
-{
-    ActiveSeg = &NullSeg;
-}
-
-
-
-void UseSeg (const char* Name, unsigned SegType)
+void UseSeg (const SegDef* D)
 /* Use the segment with the given name */
 {
     Segment* Seg = SegmentList;
     while (Seg) {
-       if (strcmp (Seg->Name, Name) == 0) {
+               if (strcmp (Seg->Def->Name, D->Name) == 0) {
            /* We found this segment. Check if the type is identical */
-           if (SegType != SEGTYPE_DEFAULT && Seg->SegType != SegType) {
+           if (D->Type != SEGTYPE_DEFAULT && Seg->Def->Type != D->Type) {
                Error (ERR_SEG_ATTR_MISMATCH);
                /* Use the new attribute to avoid errors */
-               Seg->SegType = SegType;
+               Seg->Def->Type = D->Type;
                    }
                    ActiveSeg = Seg;
            return;
@@ -234,10 +173,11 @@ void UseSeg (const char* Name, unsigned SegType)
     }
 
     /* Segment is not in list, create a new one */
-    if (SegType == SEGTYPE_DEFAULT) {
-       SegType = SEGTYPE_ABS;
+    if (D->Type == SEGTYPE_DEFAULT) {
+        Seg = NewSegment (D->Name, SEGTYPE_ABS);
+    } else {
+        Seg = NewSegment (D->Name, D->Type);
     }
-    Seg = NewSegment (Name, SegType);
     ActiveSeg = Seg;
 }
 
@@ -260,6 +200,14 @@ void SetAbsPC (unsigned long PC)
 
 
 
+const SegDef* GetCurrentSeg (void)
+/* Get a pointer to the segment defininition of the current segment */
+{
+    return ActiveSeg->Def;
+}
+
+
+
 unsigned GetSegNum (void)
 /* Get the number of the current segment */
 {
@@ -307,7 +255,7 @@ void SegAlign (unsigned Power, int Val)
 int IsZPSeg (void)
 /* Return true if the current segment is a zeropage segment */
 {
-    return (ActiveSeg->SegType == SEGTYPE_ZP);
+    return (ActiveSeg->Def->Type == SEGTYPE_ZP);
 }
 
 
@@ -315,7 +263,7 @@ int IsZPSeg (void)
 int IsFarSeg (void)
 /* Return true if the current segment is a far segment */
 {
-    return (ActiveSeg->SegType == SEGTYPE_FAR);
+    return (ActiveSeg->Def->Type == SEGTYPE_FAR);
 }
 
 
@@ -336,7 +284,7 @@ unsigned GetSegType (unsigned SegNum)
     }
 
     /* Return the segment type */
-    return S->SegType;
+    return S->Def->Type;
 }
 
 
@@ -418,7 +366,7 @@ void SegDump (void)
        unsigned I;
        Fragment* F;
        int State = -1;
-               printf ("New segment: %s", S->Name);
+               printf ("New segment: %s", S->Def->Name);
        F = S->Root;
        while (F) {
            if (F->Type == FRAG_LITERAL) {
@@ -461,10 +409,10 @@ static void WriteOneSeg (Segment* Seg)
     unsigned LineInfoIndex;
 
     /* Write the segment name followed by the byte count in this segment */
-    ObjWriteStr (Seg->Name);
+    ObjWriteStr (Seg->Def->Name);
     ObjWrite32 (Seg->PC);
     ObjWrite8 (Seg->Align);
-    ObjWrite8 (Seg->SegType);
+    ObjWrite8 (Seg->Def->Type);
 
     /* Now walk through the fragment list for this segment and write the
      * fragments.
index 0dc3744abb9c45f504fccabaf2b00660873ca198..96fa50100c024df7eda8c28856d92864ccba0db2 100644 (file)
 /* Are we in absolute mode or in relocatable mode? */
 extern int     RelocMode;
 
+/* Definitions for predefined segments */
+SegDef NullSegDef;
+SegDef ZeropageSegDef;
+SegDef DataSegDef;
+SegDef BssSegDef;
+SegDef RODataSegDef;
+SegDef CodeSegDef;
+
 
 
 /*****************************************************************************/
@@ -63,26 +71,11 @@ extern int  RelocMode;
 
 
 
-void UseCodeSeg (void);
-/* Use the code segment */
-
-void UseRODataSeg (void);
-/* Use the r/o data segment */
-
-void UseDataSeg (void);
-/* Use the data segment */
-
-void UseBssSeg (void);
-/* Use the BSS segment */
-
-void UseZeropageSeg (void);
-/* Use the zero page segment */
-
-void UseNullSeg (void);
-/* Use the null segment */
+void UseSeg (const SegDef* D);
+/* Use the given segment */
 
-void UseSeg (const char* Name, unsigned SegType);
-/* Use the segment with the given name */
+const SegDef* GetCurrentSeg (void);
+/* Get a pointer to the segment defininition of the current segment */
 
 unsigned GetSegNum (void);
 /* Get the number of the current segment */
index f1ed0a139cb3d380decd145222572ad094f55683..2a25be6fab126b2074b1371b1075ff555d61b736 100644 (file)
@@ -42,7 +42,7 @@
 /* common */
 #include "bitops.h"
 #include "cddefs.h"
-#include "check.h"
+#include "coll.h"
 #include "symdefs.h"
 #include "tgttrans.h"
 
 /* Keyword we're about to handle */
 static char Keyword [sizeof (SVal)+1] = ".";
 
+/* Segment stack */
+#define MAX_PUSHED_SEGMENTS     16
+static Collection SegStack = STATIC_COLLECTION_INITIALIZER;
+
 
 
 /*****************************************************************************/
@@ -331,7 +335,7 @@ static void DoAutoImport (void)
 static void DoBss (void)
 /* Switch to the BSS segment */
 {
-    UseBssSeg ();
+    UseSeg (&BssSegDef);
 }
 
 
@@ -407,7 +411,7 @@ static void DoCharMap (void)
 static void DoCode (void)
 /* Switch to the code segment */
 {
-    UseCodeSeg ();
+    UseSeg (&CodeSegDef);
 }
 
 
@@ -485,7 +489,7 @@ static void DoConstructor (void)
 static void DoData (void)
 /* Switch to the data segment */
 {
-    UseDataSeg ();
+    UseSeg (&DataSegDef);
 }
 
 
@@ -1059,7 +1063,7 @@ static void DoMacro (void)
 static void DoNull (void)
 /* Switch to the NULL segment */
 {
-    UseNullSeg ();
+    UseSeg (&NullSegDef);
 }
 
 
@@ -1126,6 +1130,29 @@ static void DoPageLength (void)
 
 
 
+static void DoPopSeg (void)
+/* Pop an old segment from the segment stack */
+{
+    SegDef* Def;
+
+    /* Must have a segment on the stack */
+    if (CollCount (&SegStack) == 0) {
+        ErrorSkip (ERR_SEGSTACK_EMPTY);
+        return;
+    }
+
+    /* Pop the last element */
+    Def = CollPop (&SegStack);
+
+    /* Restore this segment */
+    UseSeg (Def);
+
+    /* Delete the segment definition */
+    FreeSegDef (Def);
+}
+
+
+
 static void DoProc (void)
 /* Start a new lexical scope */
 {
@@ -1139,6 +1166,21 @@ static void DoProc (void)
 
 
 
+static void DoPushSeg (void)
+/* Push the current segment onto the segment stack */
+{
+    /* Can only push a limited size of segments */
+    if (CollCount (&SegStack) >= MAX_PUSHED_SEGMENTS) {
+        ErrorSkip (ERR_SEGSTACK_OVERFLOW);
+        return;
+    }
+
+    /* Get the current segment and push it */
+    CollAppend (&SegStack, DupSegDef (GetCurrentSeg ()));
+}
+
+
+
 static void DoReloc (void)
 /* Enter relocatable mode */
 {
@@ -1191,7 +1233,7 @@ static void DoRes (void)
 static void DoROData (void)
 /* Switch to the r/o data segment */
 {
-    UseRODataSeg ();
+    UseSeg (&RODataSegDef);
 }
 
 
@@ -1205,7 +1247,7 @@ static void DoSegment (void)
        "FAR", "LONG"
     };
     char Name [sizeof (SVal)];
-    int SegType;
+    SegDef Def = { Name, SEGTYPE_DEFAULT };
 
     if (Tok != TOK_STRCON) {
        ErrorSkip (ERR_STRCON_EXPECTED);
@@ -1216,7 +1258,6 @@ static void DoSegment (void)
        NextTok ();
 
        /* Check for an optional segment attribute */
-       SegType = SEGTYPE_DEFAULT;
        if (Tok == TOK_COMMA) {
            NextTok ();
            if (Tok != TOK_IDENT) {
@@ -1228,18 +1269,18 @@ static void DoSegment (void)
                    case 0:
                    case 1:
                        /* Zeropage */
-                       SegType = SEGTYPE_ZP;
+                       Def.Type = SEGTYPE_ZP;
                        break;
 
                    case 2:
                        /* Absolute */
-                       SegType = SEGTYPE_ABS;
+                       Def.Type = SEGTYPE_ABS;
                        break;
 
                    case 3:
                    case 4:
                        /* Far */
-                       SegType = SEGTYPE_FAR;
+                       Def.Type = SEGTYPE_FAR;
                        break;
 
                    default:
@@ -1250,7 +1291,7 @@ static void DoSegment (void)
        }
 
        /* Set the segment */
-       UseSeg (Name, SegType);
+       UseSeg (&Def);
     }
 }
 
@@ -1312,7 +1353,7 @@ static void DoWord (void)
 static void DoZeropage (void)
 /* Switch to the zeropage segment */
 {
-    UseZeropageSeg ();
+    UseSeg (&ZeropageSegDef);
 }
 
 
@@ -1416,7 +1457,9 @@ static CtrlDesc CtrlCmdTab [] = {
     { ccNone,                  DoPageLength    },
     { ccNone,          DoUnexpected    },      /* .PARAMCOUNT */
     { ccNone,          DoPC02          },
+    { ccNone,           DoPopSeg        },
     { ccNone,          DoProc          },
+    { ccNone,           DoPushSeg       },
     { ccNone,          DoUnexpected    },      /* .REFERENCED */
     { ccNone,          DoReloc         },
     { ccNone,          DoRepeat        },
@@ -1440,7 +1483,7 @@ static CtrlDesc CtrlCmdTab [] = {
 
 
 /*****************************************************************************/
-/*                                          Code                                    */
+/*                                          Code                                    */
 /*****************************************************************************/
 
 
@@ -1483,3 +1526,13 @@ void HandlePseudo (void)
 
 
 
+void SegStackCheck (void)
+/* Check if the segment stack is empty at end of assembly */
+{
+    if (CollCount (&SegStack) != 0) {
+        Error (ERR_SEGSTACK_NOT_EMPTY);
+    }
+}
+
+
+
index 5f67b6e9a5bd420a0bbdac162a368859aa586551..b9ebd3164e60f41baca69aefef19017a91d96e6b 100644 (file)
@@ -6,10 +6,10 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 1998     Ullrich von Bassewitz                                        */
-/*              Wacholderweg 14                                              */
-/*              D-70597 Stuttgart                                            */
-/* EMail:       uz@musoftware.de                                             */
+/* (C) 1998-2002 Ullrich von Bassewitz                                       */
+/*               Wacholderweg 14                                             */
+/*               D-70597 Stuttgart                                           */
+/* EMail:        uz@musoftware.de                                            */
 /*                                                                           */
 /*                                                                           */
 /* This software is provided 'as-is', without any expressed or implied       */
@@ -64,6 +64,9 @@ int TokIsPseudo (unsigned Tok);
 void HandlePseudo (void);
 /* Handle a pseudo instruction */
 
+void SegStackCheck (void);
+/* Check if the segment stack is empty at end of assembly */
+
 
 
 /* End of pseudo.h */
index 8ccc1f6a6f31233f219c5447bce575fb60944ea5..537c35ec49da4b86d6c8ef676736d87393adc07c 100644 (file)
@@ -211,7 +211,9 @@ struct DotKeyword {
     { ".PAGELENGTH",   TOK_PAGELENGTH  },
     { ".PARAMCOUNT",   TOK_PARAMCOUNT  },
     { ".PC02",                 TOK_PC02        },
+    { ".POPSEG",       TOK_POPSEG      },
     { ".PROC",                 TOK_PROC        },
+    { ".PUSHSEG",              TOK_PUSHSEG     },
     { ".REF",          TOK_REFERENCED  },
     { ".REFERENCED",   TOK_REFERENCED  },
     { ".RELOC",                TOK_RELOC       },
index 720748937f247fcaacf8aa7fbaf3ab70003ea5d4..eb214ab09570ac137ae6664496d51f246996150f 100644 (file)
@@ -186,8 +186,10 @@ enum Token {
     TOK_P816,
     TOK_PAGELENGTH,
     TOK_PARAMCOUNT,
-    TOK_PC02,
+    TOK_PC02,   
+    TOK_POPSEG,
     TOK_PROC,
+    TOK_PUSHSEG,
     TOK_REFERENCED,
     TOK_RELOC,
     TOK_REPEAT,