]> git.sur5r.net Git - cc65/commitdiff
Move the segment handling stuff from objcode to a separate module
authorcuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Tue, 21 Oct 2003 20:34:56 +0000 (20:34 +0000)
committercuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Tue, 21 Oct 2003 20:34:56 +0000 (20:34 +0000)
git-svn-id: svn://svn.cc65.org/cc65/trunk@2555 b7a2c559-68d2-44c3-8de9-860c34a00d81

13 files changed:
src/ca65/expr.c
src/ca65/fragment.c
src/ca65/fragment.h
src/ca65/listing.c
src/ca65/main.c
src/ca65/make/gcc.mak
src/ca65/make/watcom.mak
src/ca65/objcode.c
src/ca65/objcode.h
src/ca65/pseudo.c
src/ca65/segment.c [new file with mode: 0644]
src/ca65/segment.h [new file with mode: 0644]
src/ca65/symtab.c

index 616564b16a25798fa5fc1faade4689c836d0def4..5cbd71bdc13bd35eac1c2903b3340ef8008aa288 100644 (file)
 
 /* ca65 */
 #include "error.h"
+#include "expr.h"
 #include "global.h"
 #include "instr.h"
 #include "nexttok.h"
-#include "objcode.h"
+/* #include "objcode.h" */
 #include "objfile.h"
+#include "segment.h"
 #include "symtab.h"
 #include "toklist.h"
 #include "ulabel.h"
-#include "expr.h"
 
 
 
index bd0e704933d53c7daf04db8c1a05b1cacbf5c369..0d5a4b2e51801f9f2cbaeabcb4755bf0b99c6f0e 100644 (file)
@@ -6,9 +6,9 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 1998-2001 Ullrich von Bassewitz                                       */
-/*               Wacholderweg 14                                             */
-/*               D-70597 Stuttgart                                           */
+/* (C) 1998-2003 Ullrich von Bassewitz                                       */
+/*               Römerstrasse 52                                             */
+/*               D-70794 Filderstadt                                         */
 /* EMail:        uz@cc65.org                                                 */
 /*                                                                           */
 /*                                                                           */
 
 
 
+/* common */
+#include "xmalloc.h"
+
+/* ca65 */
 #include "fragment.h"
+#include "lineinfo.h"
+#include "scanner.h"
 
 
 
 /*****************************************************************************/
-/*                             struct Fragment                              */
+/*                                   Code                                    */
 /*****************************************************************************/
 
 
 
-/* List of all fragments */
-Fragment* FragList = 0;
-Fragment* FragLast = 0;
+Fragment* NewFragment (unsigned char Type, unsigned short Len)
+/* Create, initialize and return a new fragment. The fragment will be inserted
+ * into the current segment.
+ */
+{
+    /* Create a new fragment */
+    Fragment* F = xmalloc (sizeof (*F));
+
+    /* Initialize it */
+    F->Next    = 0;
+    F->LineList = 0;
+    F->Pos     = CurPos;
+    F->LI       = UseLineInfo (CurLineInfo);
+    F->Len     = Len;
+    F->Type    = Type;
+
+    /* And return it */
+    return F;
+}
+
 
 
 
index 2235f55d644cd0059d18b0b3d8ba678d70324fc4..a020813af7ebe75787c7ec64813d7a4de510d790 100644 (file)
 
 
 
-/*****************************************************************************/
-/*                                Forwards                                  */
-/*****************************************************************************/
-
-
-
-struct LineInfo;
-
-
-
 /*****************************************************************************/
 /*                             struct Fragment                              */
 /*****************************************************************************/
@@ -76,6 +66,19 @@ struct Fragment {
 
 
 
+/*****************************************************************************/
+/*                                   Code                                    */
+/*****************************************************************************/
+
+
+
+Fragment* NewFragment (unsigned char Type, unsigned short Len);
+/* Create, initialize and return a new fragment. The fragment will be inserted
+ * into the current segment.
+ */
+
+
+
 /* End of fragment.h */
 #endif
 
index a7d6d3c99c7fd2d5addf9904f033c9bd3204b431..99e8273c3757ea3e762b27ad94186a69e9c7e279 100644 (file)
@@ -48,8 +48,8 @@
 #include "error.h"
 #include "filetab.h"
 #include "global.h"
-#include "objcode.h"
 #include "listing.h"
+#include "segment.h"
 
 
 
index 972a8869ca1229ede2c12d29d5c2d4fc85e5e3da..95452f2c546c0d5884374597b2b5c62ade84f626 100644 (file)
 #include "listing.h"
 #include "macro.h"
 #include "nexttok.h"
-#include "objcode.h"
 #include "objfile.h"
 #include "options.h"
 #include "pseudo.h"
 #include "scanner.h"
+#include "segment.h"
 #include "spool.h"
 #include "symtab.h"
 #include "ulabel.h"
index 424f5476aa936a7ca7be7420e4027f08756aa3c0..053cc26e1e867edf5d80bfbcd92fc2feb32101b3 100644 (file)
@@ -35,6 +35,7 @@ OBJS =  asserts.o       \
         pseudo.o               \
        repeat.o        \
         scanner.o      \
+        segment.o       \
         spool.o         \
         symtab.o       \
                toklist.o       \
index 82f85bde5086f72b857e9a482b1297ce143e1897..61af0f1e97812691d7c2de1dd0dfac52694213c7 100644 (file)
@@ -68,6 +68,7 @@ OBJS =        asserts.obj     \
        pseudo.obj      \
        repeat.obj      \
        scanner.obj     \
+        segment.obj     \
         spool.obj       \
        symtab.obj      \
        toklist.obj     \
index bf61ebfaa3db236f8044b638ea92457729c8da72..2d56f93842e79b461a4d7d5388cb4a018bef9f9e 100644 (file)
 #include <string.h>
 #include <errno.h>
 
-/* common */
-#include "chartype.h"
-#include "check.h"
-#include "fragdefs.h"
-#include "segdefs.h"
-#include "segnames.h"
-#include "xmalloc.h"
-
 /* cc65 */
 #include "error.h"
 #include "fragment.h"
-#include "global.h"
-#include "lineinfo.h"
-#include "listing.h"
 #include "objcode.h"
-#include "objfile.h"
-#include "scanner.h"
-#include "spool.h"
-#include "symtab.h"
-
-
-
-/*****************************************************************************/
-/*                                          Data                                    */
-/*****************************************************************************/
-
-
-
-/* Are we in absolute mode or in relocatable mode? */
-int            RelocMode = 1;
-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 long   FragCount;          /* Number of fragments */
-    unsigned        Num;               /* Segment number */
-    unsigned        Align;             /* Segment alignment */
-    unsigned long   PC;
-    SegDef*         Def;                /* Segment definition (name and type) */
-};
-
-
-#define SEG(segdef, num, prev)      \
-    { prev, 0, 0, 0, num, 0, 0, segdef }
-
-/* Definitions for predefined segments */
-SegDef NullSegDef     = STATIC_SEGDEF_INITIALIZER (SEGNAME_NULL,     SEGTYPE_ABS);
-SegDef ZeropageSegDef = STATIC_SEGDEF_INITIALIZER (SEGNAME_ZEROPAGE, SEGTYPE_ZP);
-SegDef DataSegDef     = STATIC_SEGDEF_INITIALIZER (SEGNAME_DATA,     SEGTYPE_ABS);
-SegDef BssSegDef      = STATIC_SEGDEF_INITIALIZER (SEGNAME_BSS,      SEGTYPE_ABS);
-SegDef RODataSegDef   = STATIC_SEGDEF_INITIALIZER (SEGNAME_RODATA,   SEGTYPE_ABS);
-SegDef CodeSegDef     = STATIC_SEGDEF_INITIALIZER (SEGNAME_CODE,     SEGTYPE_ABS);
-
-/* Predefined segments */
-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;
-
-/* List of all segments */
-static Segment* SegmentList = &CodeSeg;
-static Segment* SegmentLast = &NullSeg;
-
-/* Currently active segment */
-static Segment*        ActiveSeg = &CodeSeg;
-
-
-
-/*****************************************************************************/
-/*                                   Segment management                             */
-/*****************************************************************************/
-
-
-
-static Segment* NewSegment (const char* Name, unsigned SegType)
-/* Create a new segment, insert it into the global list and return it */
-{
-    Segment* S;
-
-    /* Check for too many segments */
-    if (SegmentCount >= 256) {
-       Fatal (FAT_TOO_MANY_SEGMENTS);
-    }
-
-    /* Check the segment name for invalid names */
-    if (!ValidSegName (Name)) {
-       Error (ERR_ILLEGAL_SEGMENT, Name);
-    }
-
-    /* Create a new segment */
-    S = xmalloc (sizeof (*S));
-
-    /* Initialize it */
-    S->List      = 0;
-    S->Root      = 0;
-    S->Last      = 0;
-    S->FragCount = 0;
-    S->Num       = SegmentCount++;
-    S->Align     = 0;
-    S->PC        = 0;
-    S->Def       = NewSegDef (Name, SegType);
-
-    /* Insert it into the segment list */
-    SegmentLast->List = S;
-    SegmentLast = S;
-
-    /* And return it... */
-    return S;
-}
-
-
-
-void UseSeg (const SegDef* D)
-/* Use the segment with the given name */
-{
-    Segment* Seg = SegmentList;
-    while (Seg) {
-               if (strcmp (Seg->Def->Name, D->Name) == 0) {
-           /* We found this segment. Check if the type is identical */
-           if (D->Type != SEGTYPE_DEFAULT && Seg->Def->Type != D->Type) {
-               Error (ERR_SEG_ATTR_MISMATCH);
-               /* Use the new attribute to avoid errors */
-               Seg->Def->Type = D->Type;
-                   }
-                   ActiveSeg = Seg;
-           return;
-       }
-       /* Check next segment */
-       Seg = Seg->List;
-    }
-
-    /* Segment is not in list, create a new one */
-    if (D->Type == SEGTYPE_DEFAULT) {
-        Seg = NewSegment (D->Name, SEGTYPE_ABS);
-    } else {
-        Seg = NewSegment (D->Name, D->Type);
-    }
-    ActiveSeg = Seg;
-}
-
-
-
-unsigned long GetPC (void)
-/* Get the program counter of the current segment */
-{
-    return RelocMode? ActiveSeg->PC : AbsPC;
-}
-
-
-
-void SetAbsPC (unsigned long PC)
-/* Set the program counter in absolute mode */
-{
-    RelocMode = 0;
-    AbsPC = 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 */
-{
-    return ActiveSeg->Num;
-}
-
-
-
-void SegAlign (unsigned Power, int Val)
-/* Align the PC segment to 2^Power. If Val is -1, emit fill fragments (the
- * actual fill value will be determined by the linker), otherwise use the
- * given value.
- */
-{
-    unsigned char Data [4];
-    unsigned long Align = (1UL << Power) - 1;
-    unsigned long NewPC = (ActiveSeg->PC + Align) & ~Align;
-    unsigned long Count = NewPC - ActiveSeg->PC;
-
-    if (Val != -1) {
-       /* User defined fill value */
-       memset (Data, Val, sizeof (Data));
-       while (Count) {
-           if (Count > sizeof (Data)) {
-               EmitData (Data, sizeof (Data));
-               Count -= sizeof (Data);
-           } else {
-               EmitData (Data, Count);
-               Count = 0;
-           }
-       }
-    } else {
-       /* Linker defined fill value */
-       EmitFill (Count);
-    }
-
-    /* Remember the alignment in the header */
-    if (ActiveSeg->Align < Power) {
-       ActiveSeg->Align = Power;
-    }
-}
-
-
-
-int IsZPSeg (void)
-/* Return true if the current segment is a zeropage segment */
-{
-    return (ActiveSeg->Def->Type == SEGTYPE_ZP);
-}
-
-
-
-int IsFarSeg (void)
-/* Return true if the current segment is a far segment */
-{
-    return (ActiveSeg->Def->Type == SEGTYPE_FAR);
-}
-
-
-
-unsigned GetSegType (unsigned SegNum)
-/* Return the type of the segment with the given number */
-{
-    /* Search for the segment */
-    Segment* S = SegmentList;
-    while (S && SegNum) {
-       --SegNum;
-       S = S->List;
-    }
-
-    /* Did we find it? */
-    if (S == 0) {
-       FAIL ("Invalid segment number");
-    }
-
-    /* Return the segment type */
-    return S->Def->Type;
-}
-
-
-
-void SegCheck (void)
-/* Check the segments for range and other errors */
-{
-    Segment* S = SegmentList;
-    while (S) {
-       Fragment* F = S->Root;
-       while (F) {
-                   if (F->Type == FRAG_EXPR || F->Type == FRAG_SEXPR) {
-                       F->V.Expr = FinalizeExpr (F->V.Expr);
-                       if (IsConstExpr (F->V.Expr)) {
-                   /* We are able to evaluate the expression. Get the value
-                    * and check for range errors.
-                    */
-                   unsigned I;
-                   long Val = GetExprVal (F->V.Expr);
-                   int Abs = (F->Type != FRAG_SEXPR);
-
-                   if (F->Len == 1) {
-                       if (Abs) {
-                           /* Absolute value */
-                           if (Val > 255) {
-                               PError (&F->Pos, ERR_RANGE);
-                           }
-                       } else {
-                           /* PC relative value */
-                           if (Val < -128 || Val > 127) {
-                               PError (&F->Pos, ERR_RANGE);
-                           }
-                       }
-                   } else if (F->Len == 2) {
-                       if (Abs) {
-                           /* Absolute value */
-                           if (Val > 65535) {
-                               PError (&F->Pos, ERR_RANGE);
-                           }
-                       } else {
-                           /* PC relative value */
-                           if (Val < -32768 || Val > 32767) {
-                               PError (&F->Pos, ERR_RANGE);
-                           }
-                       }
-                   }
-
-                   /* Convert the fragment into a literal fragment */
-                   for (I = 0; I < F->Len; ++I) {
-                       F->V.Data [I] = Val & 0xFF;
-                       Val >>= 8;
-                   }
-                   F->Type = FRAG_LITERAL;
-               } else {
-                   /* We cannot evaluate the expression now, leave the job for
-                    * the linker. However, we are able to check for explicit
-                    * byte expressions and we will do so.
-                    */
-                   if (F->Type == FRAG_EXPR && F->Len == 1 && !IsByteExpr (F->V.Expr)) {
-                       PError (&F->Pos, ERR_RANGE);
-                   }
-               }
-           }
-           F = F->Next;
-       }
-       S = S->List;
-    }
-}
-
-
-
-void SegDump (void)
-/* Dump the contents of all segments */
-{
-    unsigned X = 0;
-    Segment* S = SegmentList;
-    printf ("\n");
-    while (S) {
-       unsigned I;
-       Fragment* F;
-       int State = -1;
-               printf ("New segment: %s", S->Def->Name);
-       F = S->Root;
-       while (F) {
-           if (F->Type == FRAG_LITERAL) {
-               if (State != 0) {
-                   printf ("\n  Literal:");
-                   X = 15;
-                   State = 0;
-               }
-               for (I = 0; I < F->Len; ++I) {
-                   printf (" %02X", F->V.Data [I]);
-                   X += 3;
-               }
-           } else if (F->Type == FRAG_EXPR || F->Type == FRAG_SEXPR) {
-                       State = 1;
-               printf ("\n  Expression (%u): ", F->Len);
-               DumpExpr (F->V.Expr);
-           } else if (F->Type == FRAG_FILL) {
-               State = 1;
-               printf ("\n  Fill bytes (%u)", F->Len);
-           } else {
-               Internal ("Unknown fragment type: %u", F->Type);
-           }
-                   if (X > 65) {
-               State = -1;
-           }
-           F = F->Next;
-       }
-       printf ("\n  End PC = $%04X\n", (unsigned)(S->PC & 0xFFFF));
-       S = S->List;
-    }
-    printf ("\n");
-}
-
-
-
-static void WriteOneSeg (Segment* Seg)
-/* Write one segment to the object file */
-{
-    Fragment* Frag;
-    unsigned LineInfoIndex;
-    unsigned long DataSize;
-    unsigned long EndPos;
-
-    /* Remember the file position, then write a dummy for the size of the
-     * following data
-     */
-    unsigned long SizePos = ObjGetFilePos ();
-    ObjWrite32 (0);
-
-    /* Write the segment data */
-    ObjWriteVar (GetStringId (Seg->Def->Name)); /* Name of the segment */
-    ObjWrite32 (Seg->PC);                       /* Size */
-    ObjWrite8 (Seg->Align);                     /* Segment alignment */
-    ObjWrite8 (Seg->Def->Type);                 /* Type of the segment */
-    ObjWriteVar (Seg->FragCount);               /* Number of fragments */
-
-    /* Now walk through the fragment list for this segment and write the
-     * fragments.
-     */
-    Frag = Seg->Root;
-    while (Frag) {
-
-       /* Write data depending on the type */
-               switch (Frag->Type) {
-
-           case FRAG_LITERAL:
-               ObjWrite8 (FRAG_LITERAL);
-               ObjWriteVar (Frag->Len);
-               ObjWriteData (Frag->V.Data, Frag->Len);
-               break;
-
-           case FRAG_EXPR:
-               switch (Frag->Len) {
-                   case 1:   ObjWrite8 (FRAG_EXPR8);   break;
-                   case 2:   ObjWrite8 (FRAG_EXPR16);  break;
-                   case 3:   ObjWrite8 (FRAG_EXPR24);  break;
-                   case 4:   ObjWrite8 (FRAG_EXPR32);  break;
-                   default:  Internal ("Invalid fragment size: %u", Frag->Len);
-               }
-               WriteExpr (Frag->V.Expr);
-               break;
-
-           case FRAG_SEXPR:
-               switch (Frag->Len) {
-                   case 1:   ObjWrite8 (FRAG_SEXPR8);  break;
-                   case 2:   ObjWrite8 (FRAG_SEXPR16); break;
-                   case 3:   ObjWrite8 (FRAG_SEXPR24); break;
-                   case 4:   ObjWrite8 (FRAG_SEXPR32); break;
-                   default:  Internal ("Invalid fragment size: %u", Frag->Len);
-               }
-               WriteExpr (Frag->V.Expr);
-               break;
-
-           case FRAG_FILL:
-               ObjWrite8 (FRAG_FILL);
-                       ObjWriteVar (Frag->Len);
-               break;
-
-           default:
-               Internal ("Invalid fragment type: %u", Frag->Type);
-
-       }
-
-               /* Write the file position of this fragment */
-       ObjWritePos (&Frag->Pos);
-
-       /* Write extra line info for this fragment. Zero is considered
-        * "no line info", so add one to the value.
-        */
-       LineInfoIndex = Frag->LI? Frag->LI->Index + 1 : 0;
-       ObjWriteVar (LineInfoIndex);
-
-       /* Next fragment */
-       Frag = Frag->Next;
-    }
-
-    /* Calculate the size of the data, seek back and write it */
-    EndPos = ObjGetFilePos ();          /* Remember where we are */
-    DataSize = EndPos - SizePos - 4;    /* Don't count size itself */
-    ObjSetFilePos (SizePos);            /* Seek back to the size */
-    ObjWrite32 (DataSize);              /* Write the size */
-    ObjSetFilePos (EndPos);             /* Seek back to the end */
-}
-
-
-
-void WriteSegments (void)
-/* Write the segment data to the object file */
-{
-    Segment* Seg;
-
-    /* Tell the object file module that we're about to start the seg list */
-    ObjStartSegments ();
-
-    /* First thing is segment count */
-    ObjWriteVar (SegmentCount);
-
-    /* Now walk through all segments and write them to the object file */
-    Seg = SegmentList;
-    while (Seg) {
-       /* Write one segment */
-       WriteOneSeg (Seg);
-       /* Next segment */
-       Seg = Seg->List;
-    }
-
-    /* Done writing segments */
-    ObjEndSegments ();
-}
+#include "segment.h"
 
 
 
@@ -530,67 +50,10 @@ void WriteSegments (void)
 
 
 
-static void IncPC (unsigned Value)
-/* Increment the PC counter */
-{
-    ActiveSeg->PC += Value;
-    if (!RelocMode) {
-       AbsPC += Value;
-    }
-}
-
-
-
-static Fragment* NewFragment (unsigned char Type, unsigned short Len)
-/* Create, initialize and return a new fragment. The fragment will be inserted
- * into the current segment.
- */
-{
-    Fragment* F;
-
-    /* Create a new fragment */
-    F = xmalloc (sizeof (*F));
-
-    /* Initialize it */
-    F->Next    = 0;
-    F->LineList = 0;
-    F->Pos     = CurPos;
-    F->LI       = UseLineInfo (CurLineInfo);
-    F->Len     = Len;
-    F->Type    = Type;
-
-    /* Insert the fragment into the current segment */
-    if (ActiveSeg->Root) {
-       ActiveSeg->Last->Next = F;
-       ActiveSeg->Last = F;
-    } else {
-       ActiveSeg->Root = ActiveSeg->Last = F;
-    }
-    ++ActiveSeg->FragCount;
-
-    /* Add this fragment to the current listing line */
-    if (LineCur) {
-       if (LineCur->FragList == 0) {
-           LineCur->FragList = F;
-       } else {
-                   LineCur->FragLast->LineList = F;
-       }
-       LineCur->FragLast = F;
-    }
-
-    /* Increment the program counter */
-    IncPC (Len);
-
-    /* And return it */
-    return F;
-}
-
-
-
 void Emit0 (unsigned char OPC)
 /* Emit an instruction with a zero sized operand */
 {
-    Fragment* F = NewFragment (FRAG_LITERAL, 1);
+    Fragment* F = GenFragment (FRAG_LITERAL, 1);
     F->V.Data [0] = OPC;
 }
 
@@ -636,7 +99,7 @@ void Emit3b (unsigned char OPC, ExprNode* Expr, ExprNode* Bank)
 void EmitSigned (ExprNode* Expr, unsigned Size)
 /* Emit a signed expression with the given size */
 {
-    Fragment* F = NewFragment (FRAG_SEXPR, Size);
+    Fragment* F = GenFragment (FRAG_SEXPR, Size);
     F->V.Expr = Expr;
 }
 
@@ -665,7 +128,7 @@ void EmitData (const unsigned char* Data, unsigned Size)
                }
 
        /* Create a new fragment */
-       F = NewFragment (FRAG_LITERAL, Len);
+       F = GenFragment (FRAG_LITERAL, Len);
 
        /* Copy the data */
        memcpy (F->V.Data, Data, Len);
@@ -692,7 +155,7 @@ void EmitByte (ExprNode* Expr)
        Emit0 (Val & 0xFF);
     } else {
        /* Create a new fragment */
-       Fragment* F = NewFragment (FRAG_EXPR, 1);
+       Fragment* F = GenFragment (FRAG_EXPR, 1);
 
        /* Set the data */
        F->V.Expr = Expr;
@@ -715,7 +178,7 @@ void EmitWord (ExprNode* Expr)
        Emit0 ((Val >> 8) & 0xFF);
     } else {
        /* Create a new fragment */
-       Fragment* F = NewFragment (FRAG_EXPR, 2);
+       Fragment* F = GenFragment (FRAG_EXPR, 2);
 
        /* Set the data */
        F->V.Expr = Expr;
@@ -739,7 +202,7 @@ void EmitFarAddr (ExprNode* Expr)
        Emit0 ((Val >> 16) & 0xFF);
     } else {
        /* Create a new fragment */
-       Fragment* F = NewFragment (FRAG_EXPR, 3);
+       Fragment* F = GenFragment (FRAG_EXPR, 3);
 
        /* Set the data */
        F->V.Expr = Expr;
@@ -761,7 +224,7 @@ void EmitDWord (ExprNode* Expr)
        Emit0 ((Val >> 24) & 0xFF);
     } else {
        /* Create a new fragment */
-       Fragment* F = NewFragment (FRAG_EXPR, 4);
+       Fragment* F = GenFragment (FRAG_EXPR, 4);
 
        /* Set the data */
        F->V.Expr = Expr;
@@ -779,7 +242,7 @@ void EmitFill (unsigned long Count)
        Count -= Chunk;
 
        /* Emit one chunk */
-       NewFragment (FRAG_FILL, Chunk);
+       GenFragment (FRAG_FILL, Chunk);
     }
 }
 
index ddfbc4154e17f242cc42d97cff6902a591d8af60..d3f88ea5c49a541ecdfc1e5ac9285fce377a2277 100644 (file)
@@ -6,9 +6,9 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 1998-2001 Ullrich von Bassewitz                                       */
-/*               Wacholderweg 14                                             */
-/*               D-70597 Stuttgart                                           */
+/* (C) 1998-2003 Ullrich von Bassewitz                                       */
+/*               Römerstrasse 52                                             */
+/*               D-70794 Filderstadt                                         */
 /* EMail:        uz@cc65.org                                                 */
 /*                                                                           */
 /*                                                                           */
 
 
 
-/* common */
-#include "segdefs.h"
-
 /* ca65 */
 #include "expr.h"
 
 
 
-/*****************************************************************************/
-/*                                  Data                                    */
-/*****************************************************************************/
-
-
-
-/* Are we in absolute mode or in relocatable mode? */
-extern int     RelocMode;
-
-/* Definitions for predefined segments */
-extern SegDef NullSegDef;
-extern SegDef ZeropageSegDef;
-extern SegDef DataSegDef;
-extern SegDef BssSegDef;
-extern SegDef RODataSegDef;
-extern SegDef CodeSegDef;
-
-
-
-/*****************************************************************************/
-/*                           Segment management                             */
-/*****************************************************************************/
-
-
-
-void UseSeg (const SegDef* D);
-/* Use the given segment */
-
-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 */
-
-void SegAlign (unsigned Power, int Val);
-/* Align the PC segment to 2^Power. If Val is -1, emit fill fragments (the
- * actual fill value will be determined by the linker), otherwise use the
- * given value.
- */
-
-int IsZPSeg (void);
-/* Return true if the current segment is a zeropage segment */
-
-int IsFarSeg (void);
-/* Return true if the current segment is a far segment */
-
-unsigned GetSegType (unsigned SegNum);
-/* Return the type of the segment with the given number */
-
-unsigned long GetPC (void);
-/* Get the program counter of the current segment */
-
-void SetAbsPC (unsigned long AbsPC);
-/* Set the program counter in absolute mode */
-
-void SegCheck (void);
-/* Check the segments for range and other errors */
-
-void SegDump (void);
-/* Dump the contents of all segments */
-
-void WriteSegments (void);
-/* Write the segment data to the object file */
-
-
-
 /*****************************************************************************/
 /*                                          Code                                    */
 /*****************************************************************************/
index 20dfe2e0cf57357b0786fcf4e61a778b15da1868..e1b284757722350073215db29cd913b356edcde4 100644 (file)
@@ -66,6 +66,7 @@
 #include "options.h"
 #include "pseudo.h"
 #include "repeat.h"
+#include "segment.h"
 #include "spool.h"
 #include "symtab.h"
 
diff --git a/src/ca65/segment.c b/src/ca65/segment.c
new file mode 100644 (file)
index 0000000..3e50d96
--- /dev/null
@@ -0,0 +1,559 @@
+/*****************************************************************************/
+/*                                                                           */
+/*                                segment.c                                 */
+/*                                                                           */
+/*                   Segments for the ca65 macroassembler                    */
+/*                                                                           */
+/*                                                                           */
+/*                                                                           */
+/* (C) 1998-2003 Ullrich von Bassewitz                                       */
+/*               Römerstrasse 52                                             */
+/*               D-70794 Filderstadt                                         */
+/* EMail:        uz@cc65.org                                                 */
+/*                                                                           */
+/*                                                                           */
+/* This software is provided 'as-is', without any expressed or implied       */
+/* warranty.  In no event will the authors be held liable for any damages    */
+/* arising from the use of this software.                                    */
+/*                                                                           */
+/* Permission is granted to anyone to use this software for any purpose,     */
+/* including commercial applications, and to alter it and redistribute it    */
+/* freely, subject to the following restrictions:                            */
+/*                                                                           */
+/* 1. The origin of this software must not be misrepresented; you must not   */
+/*    claim that you wrote the original software. If you use this software   */
+/*    in a product, an acknowledgment in the product documentation would be  */
+/*    appreciated but is not required.                                       */
+/* 2. Altered source versions must be plainly marked as such, and must not   */
+/*    be misrepresented as being the original software.                      */
+/* 3. This notice may not be removed or altered from any source              */
+/*    distribution.                                                          */
+/*                                                                           */
+/*****************************************************************************/
+
+
+
+#include <string.h>
+#include <errno.h>
+
+/* common */
+#include "segnames.h"
+#include "xmalloc.h"
+
+/* cc65 */
+#include "error.h"
+#include "fragment.h"
+#include "global.h"
+#include "lineinfo.h"
+#include "listing.h"
+#include "objcode.h"
+#include "objfile.h"
+#include "segment.h"
+#include "spool.h"
+#include "symtab.h"
+
+
+
+/*****************************************************************************/
+/*                                          Data                                    */
+/*****************************************************************************/
+
+
+
+/* Are we in absolute mode or in relocatable mode? */
+int            RelocMode = 1;
+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 long   FragCount;          /* Number of fragments */
+    unsigned        Num;               /* Segment number */
+    unsigned        Align;             /* Segment alignment */
+    unsigned long   PC;
+    SegDef*         Def;                /* Segment definition (name and type) */
+};
+
+
+#define SEG(segdef, num, prev)      \
+    { prev, 0, 0, 0, num, 0, 0, segdef }
+
+/* Definitions for predefined segments */
+SegDef NullSegDef     = STATIC_SEGDEF_INITIALIZER (SEGNAME_NULL,     SEGTYPE_ABS);
+SegDef ZeropageSegDef = STATIC_SEGDEF_INITIALIZER (SEGNAME_ZEROPAGE, SEGTYPE_ZP);
+SegDef DataSegDef     = STATIC_SEGDEF_INITIALIZER (SEGNAME_DATA,     SEGTYPE_ABS);
+SegDef BssSegDef      = STATIC_SEGDEF_INITIALIZER (SEGNAME_BSS,      SEGTYPE_ABS);
+SegDef RODataSegDef   = STATIC_SEGDEF_INITIALIZER (SEGNAME_RODATA,   SEGTYPE_ABS);
+SegDef CodeSegDef     = STATIC_SEGDEF_INITIALIZER (SEGNAME_CODE,     SEGTYPE_ABS);
+
+/* Predefined segments */
+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;
+
+/* List of all segments */
+static Segment* SegmentList = &CodeSeg;
+static Segment* SegmentLast = &NullSeg;
+
+/* Currently active segment */
+static Segment*        ActiveSeg = &CodeSeg;
+
+
+
+/*****************************************************************************/
+/*                                          Code                                    */
+/*****************************************************************************/
+
+
+
+static Segment* NewSegment (const char* Name, unsigned SegType)
+/* Create a new segment, insert it into the global list and return it */
+{
+    Segment* S;
+
+    /* Check for too many segments */
+    if (SegmentCount >= 256) {
+       Fatal (FAT_TOO_MANY_SEGMENTS);
+    }
+
+    /* Check the segment name for invalid names */
+    if (!ValidSegName (Name)) {
+       Error (ERR_ILLEGAL_SEGMENT, Name);
+    }
+
+    /* Create a new segment */
+    S = xmalloc (sizeof (*S));
+
+    /* Initialize it */
+    S->List      = 0;
+    S->Root      = 0;
+    S->Last      = 0;
+    S->FragCount = 0;
+    S->Num       = SegmentCount++;
+    S->Align     = 0;
+    S->PC        = 0;
+    S->Def       = NewSegDef (Name, SegType);
+
+    /* Insert it into the segment list */
+    SegmentLast->List = S;
+    SegmentLast = S;
+
+    /* And return it... */
+    return S;
+}
+
+
+
+Fragment* GenFragment (unsigned char Type, unsigned short Len)
+/* Generate a new fragment, add it to the current segment and return it. */
+{
+    /* Create the new fragment */
+    Fragment* F = NewFragment (Type, Len);
+
+    /* Insert the fragment into the current segment */
+    if (ActiveSeg->Root) {
+       ActiveSeg->Last->Next = F;
+       ActiveSeg->Last = F;
+    } else {
+       ActiveSeg->Root = ActiveSeg->Last = F;
+    }
+    ++ActiveSeg->FragCount;
+
+    /* Add this fragment to the current listing line */
+    if (LineCur) {
+       if (LineCur->FragList == 0) {
+           LineCur->FragList = F;
+       } else {
+                   LineCur->FragLast->LineList = F;
+       }
+       LineCur->FragLast = F;
+    }
+
+    /* Increment the program counter */
+    ActiveSeg->PC += F->Len;
+    if (!RelocMode) {
+       AbsPC += F->Len;
+    }
+
+    /* Return the fragment */
+    return F;
+}
+
+
+
+void UseSeg (const SegDef* D)
+/* Use the segment with the given name */
+{
+    Segment* Seg = SegmentList;
+    while (Seg) {
+               if (strcmp (Seg->Def->Name, D->Name) == 0) {
+           /* We found this segment. Check if the type is identical */
+           if (D->Type != SEGTYPE_DEFAULT && Seg->Def->Type != D->Type) {
+               Error (ERR_SEG_ATTR_MISMATCH);
+               /* Use the new attribute to avoid errors */
+               Seg->Def->Type = D->Type;
+                   }
+                   ActiveSeg = Seg;
+           return;
+       }
+       /* Check next segment */
+       Seg = Seg->List;
+    }
+
+    /* Segment is not in list, create a new one */
+    if (D->Type == SEGTYPE_DEFAULT) {
+        Seg = NewSegment (D->Name, SEGTYPE_ABS);
+    } else {
+        Seg = NewSegment (D->Name, D->Type);
+    }
+    ActiveSeg = Seg;
+}
+
+
+
+unsigned long GetPC (void)
+/* Get the program counter of the current segment */
+{
+    return RelocMode? ActiveSeg->PC : AbsPC;
+}
+
+
+
+void SetAbsPC (unsigned long PC)
+/* Set the program counter in absolute mode */
+{
+    RelocMode = 0;
+    AbsPC = 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 */
+{
+    return ActiveSeg->Num;
+}
+
+
+
+void SegAlign (unsigned Power, int Val)
+/* Align the PC segment to 2^Power. If Val is -1, emit fill fragments (the
+ * actual fill value will be determined by the linker), otherwise use the
+ * given value.
+ */
+{
+    unsigned char Data [4];
+    unsigned long Align = (1UL << Power) - 1;
+    unsigned long NewPC = (ActiveSeg->PC + Align) & ~Align;
+    unsigned long Count = NewPC - ActiveSeg->PC;
+
+    if (Val != -1) {
+       /* User defined fill value */
+       memset (Data, Val, sizeof (Data));
+       while (Count) {
+           if (Count > sizeof (Data)) {
+               EmitData (Data, sizeof (Data));
+               Count -= sizeof (Data);
+           } else {
+               EmitData (Data, Count);
+               Count = 0;
+           }
+       }
+    } else {
+       /* Linker defined fill value */
+       EmitFill (Count);
+    }
+
+    /* Remember the alignment in the header */
+    if (ActiveSeg->Align < Power) {
+       ActiveSeg->Align = Power;
+    }
+}
+
+
+
+int IsZPSeg (void)
+/* Return true if the current segment is a zeropage segment */
+{
+    return (ActiveSeg->Def->Type == SEGTYPE_ZP);
+}
+
+
+
+int IsFarSeg (void)
+/* Return true if the current segment is a far segment */
+{
+    return (ActiveSeg->Def->Type == SEGTYPE_FAR);
+}
+
+
+
+unsigned GetSegType (unsigned SegNum)
+/* Return the type of the segment with the given number */
+{
+    /* Search for the segment */
+    Segment* S = SegmentList;
+    while (S && SegNum) {
+       --SegNum;
+       S = S->List;
+    }
+
+    /* Did we find it? */
+    if (S == 0) {
+       FAIL ("Invalid segment number");
+    }
+
+    /* Return the segment type */
+    return S->Def->Type;
+}
+
+
+
+void SegCheck (void)
+/* Check the segments for range and other errors */
+{
+    Segment* S = SegmentList;
+    while (S) {
+       Fragment* F = S->Root;
+       while (F) {
+                   if (F->Type == FRAG_EXPR || F->Type == FRAG_SEXPR) {
+                       F->V.Expr = FinalizeExpr (F->V.Expr);
+                       if (IsConstExpr (F->V.Expr)) {
+                   /* We are able to evaluate the expression. Get the value
+                    * and check for range errors.
+                    */
+                   unsigned I;
+                   long Val = GetExprVal (F->V.Expr);
+                   int Abs = (F->Type != FRAG_SEXPR);
+
+                   if (F->Len == 1) {
+                       if (Abs) {
+                           /* Absolute value */
+                           if (Val > 255) {
+                               PError (&F->Pos, ERR_RANGE);
+                           }
+                       } else {
+                           /* PC relative value */
+                           if (Val < -128 || Val > 127) {
+                               PError (&F->Pos, ERR_RANGE);
+                           }
+                       }
+                   } else if (F->Len == 2) {
+                       if (Abs) {
+                           /* Absolute value */
+                           if (Val > 65535) {
+                               PError (&F->Pos, ERR_RANGE);
+                           }
+                       } else {
+                           /* PC relative value */
+                           if (Val < -32768 || Val > 32767) {
+                               PError (&F->Pos, ERR_RANGE);
+                           }
+                       }
+                   }
+
+                   /* Convert the fragment into a literal fragment */
+                   for (I = 0; I < F->Len; ++I) {
+                       F->V.Data [I] = Val & 0xFF;
+                       Val >>= 8;
+                   }
+                   F->Type = FRAG_LITERAL;
+               } else {
+                   /* We cannot evaluate the expression now, leave the job for
+                    * the linker. However, we are able to check for explicit
+                    * byte expressions and we will do so.
+                    */
+                   if (F->Type == FRAG_EXPR && F->Len == 1 && !IsByteExpr (F->V.Expr)) {
+                       PError (&F->Pos, ERR_RANGE);
+                   }
+               }
+           }
+           F = F->Next;
+       }
+       S = S->List;
+    }
+}
+
+
+
+void SegDump (void)
+/* Dump the contents of all segments */
+{
+    unsigned X = 0;
+    Segment* S = SegmentList;
+    printf ("\n");
+    while (S) {
+       unsigned I;
+       Fragment* F;
+       int State = -1;
+               printf ("New segment: %s", S->Def->Name);
+       F = S->Root;
+       while (F) {
+           if (F->Type == FRAG_LITERAL) {
+               if (State != 0) {
+                   printf ("\n  Literal:");
+                   X = 15;
+                   State = 0;
+               }
+               for (I = 0; I < F->Len; ++I) {
+                   printf (" %02X", F->V.Data [I]);
+                   X += 3;
+               }
+           } else if (F->Type == FRAG_EXPR || F->Type == FRAG_SEXPR) {
+                       State = 1;
+               printf ("\n  Expression (%u): ", F->Len);
+               DumpExpr (F->V.Expr);
+           } else if (F->Type == FRAG_FILL) {
+               State = 1;
+               printf ("\n  Fill bytes (%u)", F->Len);
+           } else {
+               Internal ("Unknown fragment type: %u", F->Type);
+           }
+                   if (X > 65) {
+               State = -1;
+           }
+           F = F->Next;
+       }
+       printf ("\n  End PC = $%04X\n", (unsigned)(S->PC & 0xFFFF));
+       S = S->List;
+    }
+    printf ("\n");
+}
+
+
+
+static void WriteOneSeg (Segment* Seg)
+/* Write one segment to the object file */
+{
+    Fragment* Frag;
+    unsigned LineInfoIndex;
+    unsigned long DataSize;
+    unsigned long EndPos;
+
+    /* Remember the file position, then write a dummy for the size of the
+     * following data
+     */
+    unsigned long SizePos = ObjGetFilePos ();
+    ObjWrite32 (0);
+
+    /* Write the segment data */
+    ObjWriteVar (GetStringId (Seg->Def->Name)); /* Name of the segment */
+    ObjWrite32 (Seg->PC);                       /* Size */
+    ObjWrite8 (Seg->Align);                     /* Segment alignment */
+    ObjWrite8 (Seg->Def->Type);                 /* Type of the segment */
+    ObjWriteVar (Seg->FragCount);               /* Number of fragments */
+
+    /* Now walk through the fragment list for this segment and write the
+     * fragments.
+     */
+    Frag = Seg->Root;
+    while (Frag) {
+
+       /* Write data depending on the type */
+               switch (Frag->Type) {
+
+           case FRAG_LITERAL:
+               ObjWrite8 (FRAG_LITERAL);
+               ObjWriteVar (Frag->Len);
+               ObjWriteData (Frag->V.Data, Frag->Len);
+               break;
+
+           case FRAG_EXPR:
+               switch (Frag->Len) {
+                   case 1:   ObjWrite8 (FRAG_EXPR8);   break;
+                   case 2:   ObjWrite8 (FRAG_EXPR16);  break;
+                   case 3:   ObjWrite8 (FRAG_EXPR24);  break;
+                   case 4:   ObjWrite8 (FRAG_EXPR32);  break;
+                   default:  Internal ("Invalid fragment size: %u", Frag->Len);
+               }
+               WriteExpr (Frag->V.Expr);
+               break;
+
+           case FRAG_SEXPR:
+               switch (Frag->Len) {
+                   case 1:   ObjWrite8 (FRAG_SEXPR8);  break;
+                   case 2:   ObjWrite8 (FRAG_SEXPR16); break;
+                   case 3:   ObjWrite8 (FRAG_SEXPR24); break;
+                   case 4:   ObjWrite8 (FRAG_SEXPR32); break;
+                   default:  Internal ("Invalid fragment size: %u", Frag->Len);
+               }
+               WriteExpr (Frag->V.Expr);
+               break;
+
+           case FRAG_FILL:
+               ObjWrite8 (FRAG_FILL);
+                       ObjWriteVar (Frag->Len);
+               break;
+
+           default:
+               Internal ("Invalid fragment type: %u", Frag->Type);
+
+       }
+
+               /* Write the file position of this fragment */
+       ObjWritePos (&Frag->Pos);
+
+       /* Write extra line info for this fragment. Zero is considered
+        * "no line info", so add one to the value.
+        */
+       LineInfoIndex = Frag->LI? Frag->LI->Index + 1 : 0;
+       ObjWriteVar (LineInfoIndex);
+
+       /* Next fragment */
+       Frag = Frag->Next;
+    }
+
+    /* Calculate the size of the data, seek back and write it */
+    EndPos = ObjGetFilePos ();          /* Remember where we are */
+    DataSize = EndPos - SizePos - 4;    /* Don't count size itself */
+    ObjSetFilePos (SizePos);            /* Seek back to the size */
+    ObjWrite32 (DataSize);              /* Write the size */
+    ObjSetFilePos (EndPos);             /* Seek back to the end */
+}
+
+
+
+void WriteSegments (void)
+/* Write the segment data to the object file */
+{
+    Segment* Seg;
+
+    /* Tell the object file module that we're about to start the seg list */
+    ObjStartSegments ();
+
+    /* First thing is segment count */
+    ObjWriteVar (SegmentCount);
+
+    /* Now walk through all segments and write them to the object file */
+    Seg = SegmentList;
+    while (Seg) {
+       /* Write one segment */
+       WriteOneSeg (Seg);
+       /* Next segment */
+       Seg = Seg->List;
+    }
+
+    /* Done writing segments */
+    ObjEndSegments ();
+}
+
+
+
diff --git a/src/ca65/segment.h b/src/ca65/segment.h
new file mode 100644 (file)
index 0000000..1d6ce79
--- /dev/null
@@ -0,0 +1,124 @@
+/*****************************************************************************/
+/*                                                                           */
+/*                                segment.h                                 */
+/*                                                                           */
+/*                   Segments for the ca65 macroassembler                    */
+/*                                                                           */
+/*                                                                           */
+/*                                                                           */
+/* (C) 1998-2003 Ullrich von Bassewitz                                       */
+/*               Römerstrasse 52                                             */
+/*               D-70794 Filderstadt                                         */
+/* EMail:        uz@cc65.org                                                 */
+/*                                                                           */
+/*                                                                           */
+/* This software is provided 'as-is', without any expressed or implied       */
+/* warranty.  In no event will the authors be held liable for any damages    */
+/* arising from the use of this software.                                    */
+/*                                                                           */
+/* Permission is granted to anyone to use this software for any purpose,     */
+/* including commercial applications, and to alter it and redistribute it    */
+/* freely, subject to the following restrictions:                            */
+/*                                                                           */
+/* 1. The origin of this software must not be misrepresented; you must not   */
+/*    claim that you wrote the original software. If you use this software   */
+/*    in a product, an acknowledgment in the product documentation would be  */
+/*    appreciated but is not required.                                       */
+/* 2. Altered source versions must be plainly marked as such, and must not   */
+/*    be misrepresented as being the original software.                      */
+/* 3. This notice may not be removed or altered from any source              */
+/*    distribution.                                                          */
+/*                                                                           */
+/*****************************************************************************/
+
+
+
+#ifndef SEGMENT_H
+#define SEGMENT_H
+
+
+
+/* common */
+#include "fragdefs.h"
+#include "segdefs.h"
+
+/* ca65 */
+#include "fragment.h"
+
+
+
+/*****************************************************************************/
+/*                                  Data                                    */
+/*****************************************************************************/
+
+
+
+/* Are we in absolute mode or in relocatable mode? */
+extern int     RelocMode;
+
+/* Definitions for predefined segments */
+extern SegDef NullSegDef;
+extern SegDef ZeropageSegDef;
+extern SegDef DataSegDef;
+extern SegDef BssSegDef;
+extern SegDef RODataSegDef;
+extern SegDef CodeSegDef;
+
+
+
+/*****************************************************************************/
+/*                                          Code                                    */
+/*****************************************************************************/
+
+
+
+Fragment* GenFragment (unsigned char Type, unsigned short Len);
+/* Generate a new fragment, add it to the current segment and return it. */
+
+void UseSeg (const SegDef* D);
+/* Use the given segment */
+
+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 */
+
+void SegAlign (unsigned Power, int Val);
+/* Align the PC segment to 2^Power. If Val is -1, emit fill fragments (the
+ * actual fill value will be determined by the linker), otherwise use the
+ * given value.
+ */
+
+int IsZPSeg (void);
+/* Return true if the current segment is a zeropage segment */
+
+int IsFarSeg (void);
+/* Return true if the current segment is a far segment */
+
+unsigned GetSegType (unsigned SegNum);
+/* Return the type of the segment with the given number */
+
+unsigned long GetPC (void);
+/* Get the program counter of the current segment */
+
+void SetAbsPC (unsigned long AbsPC);
+/* Set the program counter in absolute mode */
+
+void SegCheck (void);
+/* Check the segments for range and other errors */
+
+void SegDump (void);
+/* Dump the contents of all segments */
+
+void WriteSegments (void);
+/* Write the segment data to the object file */
+
+
+
+/* End of segment.h */
+
+#endif
+
+
+
index 09837720c1f77001ead904efd8376eedb50f1fd1..fa3d4847bfebcb29fb4def625f91dc374bef2b88 100644 (file)
@@ -70,6 +70,7 @@
 #define SF_ABS         0x0040          /* Declared as absolute symbol */
 #define SF_LABEL        0x0080          /* Used as a label */
 #define SF_FORCED       0x0100          /* Forced import, SF_IMPORT also set */
+#define SF_FINALIZED    0x0200          /* Symbol is finalized */
 #define SF_INDEXED     0x0800          /* Index is valid */
 #define SF_CONST       0x1000          /* The symbol has a constant value */
 #define SF_MULTDEF             0x2000          /* Multiply defined symbol */
@@ -369,8 +370,7 @@ void SymEnterLevel (void)
                RootTab = SymTab = NewSymTable (MAIN_HASHTAB_SIZE);
     } else {
                /* Create a local symbol table */
-               SymTable* LocalSyms;
-       LocalSyms = NewSymTable (SUB_HASHTAB_SIZE);
+               SymTable* LocalSyms = NewSymTable (SUB_HASHTAB_SIZE);
        LocalSyms->BackLink = SymTab;
                SymTab = LocalSyms;
     }
@@ -820,12 +820,13 @@ void SymFinalize (SymEntry* S)
 {
     /* Resolve trampoline entries */
     if (S->Flags & SF_TRAMPOLINE) {
-       S = S->V.Sym;
+       S = S->V.Sym;
     }
 
     /* Check if we have an expression */
-    if (SymHasExpr (S)) {
+    if ((S->Flags & SF_FINALIZED) == 0 && SymHasExpr (S)) {
        S->V.Expr = FinalizeExpr (S->V.Expr);
+        S->Flags |= SF_FINALIZED;
     }
 }