]> git.sur5r.net Git - cc65/commitdiff
Started to generalize line info handling. Remove separate FilePos fields and
authoruz <uz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Mon, 24 Jan 2011 22:38:22 +0000 (22:38 +0000)
committeruz <uz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Mon, 24 Jan 2011 22:38:22 +0000 (22:38 +0000)
try to manage all and everything with LineInfos.

git-svn-id: svn://svn.cc65.org/cc65/trunk@4914 b7a2c559-68d2-44c3-8de9-860c34a00d81

src/ca65/asserts.c
src/ca65/dbginfo.c
src/ca65/dbginfo.h
src/ca65/error.c
src/ca65/error.h
src/ca65/fragment.c
src/ca65/fragment.h
src/ca65/lineinfo.c
src/ca65/lineinfo.h
src/ca65/main.c
src/ca65/segment.c

index 126231c0687254bf7f89b482b073d5194e4809c3..84b2621c700b4daa7bfe17a276ebc30bcd298683 100644 (file)
@@ -41,8 +41,8 @@
 #include "asserts.h"
 #include "error.h"
 #include "expr.h"
+#include "lineinfo.h"
 #include "objfile.h"
-#include "scanner.h"
 #include "spool.h"
 
 
@@ -59,7 +59,7 @@ struct Assertion {
     ExprNode*       Expr;       /* Expression to evaluate */
     AssertAction    Action;     /* Action to take */
     unsigned        Msg;        /* Message to print (if any) */
-    FilePos         Pos;        /* File position of assertion */
+    Collection      LI;         /* Line infos for the assertion */
 };
 
 /* Collection with all assertions for a module */
@@ -83,7 +83,8 @@ static Assertion* NewAssertion (ExprNode* Expr, AssertAction Action, unsigned Ms
     A->Expr     = Expr;
     A->Action   = Action;
     A->Msg      = Msg;
-    A->Pos      = CurTok.Pos;
+    A->LI       = EmptyCollection;
+    GetFullLineInfo (&A->LI);
 
     /* Return the new struct */
     return A;
@@ -128,11 +129,11 @@ void CheckAssertions (void)
             switch (A->Action) {
 
                 case ASSERT_ACT_WARN:
-                    PWarning (&A->Pos, 0, "%s", Msg);
+                    LIWarning (&A->LI, 0, "%s", Msg);
                     break;
 
                 case ASSERT_ACT_ERROR:
-                    PError (&A->Pos, "%s", Msg);
+                    LIError (&A->LI, "%s", Msg);
                     break;
 
                 default:
@@ -169,7 +170,7 @@ void WriteAssertions (void)
         WriteExpr (A->Expr);
         ObjWriteVar ((unsigned) A->Action);
         ObjWriteVar (A->Msg);
-        ObjWritePos (&A->Pos);
+        WriteLineInfo (&A->LI);
     }
 
     /* Done writing the assertions */
@@ -179,4 +180,4 @@ void WriteAssertions (void)
 
 
 
-                         
+
index fc80539b49b303ea48bddaff6eeb2aa4f44ce2b4..15745b3fdff98af972f6c02953e7c64364113122 100644 (file)
 
 
 
+/*****************************************************************************/
+/*                                   Data                                    */
+/*****************************************************************************/
+
+
+
+/* The line info slot used */
+static unsigned LineInfoSlot;
+
+
+
 /*****************************************************************************/
 /*                                          Code                                    */
 /*****************************************************************************/
@@ -103,7 +114,7 @@ void DbgInfoLine (void)
      * follow, the last line info is terminated.
      */
     if (CurTok.Tok == TOK_SEP) {
-       ClearLineInfo ();
+       ClearLineInfo (LineInfoSlot);
        return;
     }
 
@@ -133,7 +144,7 @@ void DbgInfoLine (void)
     }
 
     /* Remember the line info */
-    GenLineInfo (Index, LineNum, 0);
+    GenLineInfo (LineInfoSlot, Index, LineNum, 0);
 }
 
 
@@ -146,5 +157,3 @@ void DbgInfoSym (void)
 
 
 
-
-
index 9f0ce3ed571a5ad250fb074b18961c3682826dd4..30fd7ed5636e3a70960b7d517f85f5f7cdb512ba 100644 (file)
@@ -6,10 +6,10 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 2000-2001 Ullrich von Bassewitz                                       */
-/*               Wacholderweg 14                                             */
-/*               D-70597 Stuttgart                                           */
-/* EMail:        uz@cc65.org                                                 */
+/* (C) 2000-2011, Ullrich von Bassewitz                                      */
+/*                Roemerstrasse 52                                           */
+/*                D-70794 Filderstadt                                        */
+/* EMail:         uz@cc65.org                                                */
 /*                                                                           */
 /*                                                                           */
 /* This software is provided 'as-is', without any expressed or implied       */
index 9c4ce1ede378a03a847fb28d52bf4e53373158c9..67bf2909251ae795a185689f9750c47f72da52fc 100644 (file)
@@ -43,6 +43,7 @@
 /* ca65 */
 #include "error.h"
 #include "filetab.h"
+#include "lineinfo.h"
 #include "nexttok.h"
 
 
@@ -62,6 +63,32 @@ unsigned WarningCount        = 0;
 
 
 
+/*****************************************************************************/
+/*                             Helper functions                              */
+/*****************************************************************************/
+
+
+
+static int FindAsmEntry (const Collection* LineInfos)
+/* Return the last entry of type LI_TYPE_ASM in the given line infos. If none
+ * was found, return -1.
+ */
+{
+    unsigned I = CollCount (LineInfos);
+    while (I > 0) {
+        const LineInfo* LI = CollConstAt (LineInfos, --I);
+        if ((LI->Type & LI_MASK_TYPE) == LI_TYPE_ASM) {
+            /* Found */
+            return (int) I;
+        }
+    }
+
+    /* Not found */
+    return -1;
+}
+
+
+
 /*****************************************************************************/
 /*                                Warnings                                  */
 /*****************************************************************************/
@@ -111,6 +138,29 @@ void PWarning (const FilePos* Pos, unsigned Level, const char* Format, ...)
 
 
 
+void LIWarning (const Collection* LineInfos, unsigned Level, const char* Format, ...)
+/* Print warning message using the given line infos */
+{
+    const LineInfo* LI;
+    va_list ap;
+
+    /* Search backwards in LI for the first entry of type LI_TYPE_ASM. */
+    int I = FindAsmEntry (LineInfos);
+
+    /* We must have such an entry */
+    CHECK (I >= 0);
+
+    /* Get the position for this entry */
+    LI = CollConstAt (LineInfos, I);
+
+    /* Output a warning for this position */
+    va_start (ap, Format);
+    WarningMsg (&LI->Pos, Level, Format, ap);
+    va_end (ap);
+}
+
+
+
 /*****************************************************************************/
 /*                                 Errors                                   */
 /*****************************************************************************/
@@ -157,6 +207,29 @@ void PError (const FilePos* Pos, const char* Format, ...)
 
 
 
+void LIError (const Collection* LineInfos, const char* Format, ...)
+/* Print an error message using the given line infos. */
+{
+    const LineInfo* LI;
+    va_list ap;
+
+    /* Search backwards in LI for the first entry of type LI_TYPE_ASM. */
+    int I = FindAsmEntry (LineInfos);
+
+    /* We must have such an entry */
+    CHECK (I >= 0);
+
+    /* Get the position for this entry */
+    LI = CollConstAt (LineInfos, I);
+
+    /* Output an error for this position */
+    va_start (ap, Format);
+    ErrorMsg (&LI->Pos, Format, ap);
+    va_end (ap);
+}
+
+
+
 void ErrorSkip (const char* Format, ...)
 /* Print an error message and skip the rest of the line */
 {
index b14b471bd4fd04983ba1d11c4c9bb33464998df6..de0e53ac52a7e7a2a7b741ab62793b7b14ea7685 100644 (file)
@@ -6,10 +6,10 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 1998-2008 Ullrich von Bassewitz                                       */
-/*               Roemerstrasse 52                                            */
-/*               D-70794 Filderstadt                                         */
-/* EMail:        uz@cc65.org                                                 */
+/* (C) 1998-2011, Ullrich von Bassewitz                                      */
+/*                Roemerstrasse 52                                           */
+/*                D-70794 Filderstadt                                        */
+/* EMail:         uz@cc65.org                                                */
 /*                                                                           */
 /*                                                                           */
 /* This software is provided 'as-is', without any expressed or implied       */
 
 /* common */
 #include "attrib.h"
+#include "coll.h"
 #include "filepos.h"
 
 
 
 /*****************************************************************************/
-/*                                  Data                                    */
+/*                                  Data                                    */
 /*****************************************************************************/
 
 
@@ -71,12 +72,18 @@ void Warning (unsigned Level, const char* Format, ...) attribute ((format (print
 void PWarning (const FilePos* Pos, unsigned Level, const char* Format, ...) attribute ((format (printf, 3, 4)));
 /* Print warning message giving an explicit file and position. */
 
+void LIWarning (const Collection* LineInfos, unsigned Level, const char* Format, ...) attribute ((format (printf, 3, 4)));
+/* Print warning message using the given line infos */
+
 void Error (const char* Format, ...) attribute ((format (printf, 1, 2)));
 /* Print an error message */
 
 void PError (const FilePos* Pos, const char* Format, ...) attribute ((format (printf, 2, 3)));
 /* Print an error message giving an explicit file and position. */
 
+void LIError (const Collection* LineInfos, const char* Format, ...) attribute ((format (printf, 2, 3)));
+/* Print an error message using the given line infos. */
+
 void ErrorSkip (const char* Format, ...) attribute ((format (printf, 1, 2)));
 /* Print an error message and skip the rest of the line */
 
index 6ee4dad8b3c493b2e87f28dfd6aaae969a1fa47c..059371e77374c24cbfa2138b340b0a0b411f47b4 100644 (file)
@@ -38,8 +38,6 @@
 
 /* ca65 */
 #include "fragment.h"
-#include "lineinfo.h"
-#include "scanner.h"
 
 
 
@@ -60,8 +58,8 @@ Fragment* NewFragment (unsigned char Type, unsigned short Len)
     /* Initialize it */
     F->Next    = 0;
     F->LineList = 0;
-    F->Pos     = CurTok.Pos;
-    F->LI       = UseLineInfo (CurLineInfo);
+    F->LI       = EmptyCollection;
+    GetFullLineInfo (&F->LI);
     F->Len     = Len;
     F->Type    = Type;
 
@@ -71,4 +69,3 @@ Fragment* NewFragment (unsigned char Type, unsigned short Len)
 
 
 
-
index 863b4740c1966d76f9ee37aaa2f4f57c368bff3b..2db86f48ae779c69d7dfdec867d014b5e4218b2a 100644 (file)
@@ -6,10 +6,10 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 1998-2003 Ullrich von Bassewitz                                       */
-/*               Römerstrasse 52                                             */
-/*               D-70794 Filderstadt                                         */
-/* EMail:        uz@cc65.org                                                 */
+/* (C) 1998-2011, Ullrich von Bassewitz                                      */
+/*                Roemerstrasse 52                                           */
+/*                D-70794 Filderstadt                                        */
+/* EMail:         uz@cc65.org                                                */
 /*                                                                           */
 /*                                                                           */
 /* This software is provided 'as-is', without any expressed or implied       */
 
 /* common */
 #include "exprdefs.h"
-#include "filepos.h"
+#include "coll.h"
+
+/* ca65 */
+#include "lineinfo.h"
 
 
 
 /*****************************************************************************/
-/*                             struct Fragment                              */
+/*                             struct Fragment                              */
 /*****************************************************************************/
 
 
 
 typedef struct Fragment Fragment;
 struct Fragment {
-    Fragment*                  Next;           /* Pointer to next fragment in segment */
-    Fragment*          LineList;       /* List of fragments for one src line */
-    FilePos                    Pos;            /* File position for this fragment */
-    struct LineInfo*    LI;             /* Extra line info */
-    unsigned short     Len;            /* Length for this fragment */
-    unsigned char      Type;           /* Fragment type */
+    Fragment*                  Next;       /* Pointer to next fragment in segment */
+    Fragment*          LineList;   /* List of fragments for one src line */
+    Collection          LI;         /* Line info for this fragment */
+    unsigned short     Len;        /* Length for this fragment */
+    unsigned char      Type;       /* Fragment type */
     union {
-               unsigned char   Data[4];        /* Literal values */
-               ExprNode*       Expr;           /* Expression */
+               unsigned char   Data[4];    /* Literal values */
+               ExprNode*       Expr;       /* Expression */
     } V;
 };
 
index 2e674b719939a8a7989ce974fb3f9026e024f379..92d7612a59c7d5aba319d2f58dfd5f616ba6455d 100644 (file)
 
 
 
+#include <string.h>
+#include <limits.h>
+
 /* common */
 #include "coll.h"
 #include "xmalloc.h"
 
 /* ca65 */
-#include "objfile.h"
+#include "global.h"
 #include "lineinfo.h"
+#include "objfile.h"
 
 
 
 /*****************************************************************************/
-/*                                  Data                                    */
+/*                                  Data                                    */
 /*****************************************************************************/
 
 
 
+/* An invalid line info index */
+#define INV_LINEINFO_INDEX      UINT_MAX
+
 /* Collection containing all line infos */
-Collection LineInfoColl = STATIC_COLLECTION_INITIALIZER;
-unsigned  LineInfoValid = 0;              /* Valid, that is, used entries */
+static Collection LineInfoColl = STATIC_COLLECTION_INITIALIZER;
 
-/* Static pointer to last line info or NULL if not active */
-LineInfo* CurLineInfo   = 0;
+/* Number of valid (=used) line infos in LineInfoColl */
+static unsigned UsedLineInfoCount;
+
+/* Entry in CurLineInfo */
+typedef struct LineInfoSlot LineInfoSlot;
+struct LineInfoSlot {
+    unsigned    Type;
+    LineInfo*   Info;
+};
+
+/* Dynamically allocated array of LineInfoSlots */
+static LineInfoSlot* CurLineInfo;
+static unsigned AllocatedSlots;
+static unsigned UsedSlots;
 
 
 
 /*****************************************************************************/
-/*                                          Code                                    */
+/*                              struct LineInfo                              */
 /*****************************************************************************/
 
 
 
-static LineInfo* NewLineInfo (unsigned File, unsigned long Line, unsigned Col)
+static LineInfo* NewLineInfo (unsigned Type, unsigned File,
+                              unsigned long Line, unsigned Col)
 /* Create and return a new line info. Usage will be zero. */
 {
     /* Allocate memory */
@@ -82,13 +101,11 @@ static LineInfo* NewLineInfo (unsigned File, unsigned long Line, unsigned Col)
 
     /* Initialize the fields */
     LI->Usage    = 0;
-    LI->Index    = 0;           /* Currently invalid */
+    LI->Type     = Type;
+    LI->Index    = INV_LINEINFO_INDEX;
+    LI->Pos.Name = File;
     LI->Pos.Line = Line;
     LI->Pos.Col  = Col;
-    LI->Pos.Name = File;
-
-    /* Insert this structure into the collection */
-    CollAppend (&LineInfoColl, LI);
 
     /* Return the new struct */
     return LI;
@@ -96,41 +113,188 @@ static LineInfo* NewLineInfo (unsigned File, unsigned long Line, unsigned Col)
 
 
 
-LineInfo* UseLineInfo (LineInfo* LI)
-/* Increase the reference count of the given line info and return it. The
- * function will gracefully accept NULL pointers and do nothing in this case.
+static void FreeLineInfo (LineInfo* LI)
+/* "Free" line info. If the usage counter is non zero, move it to the
+ * collection that contains all line infos, otherwise delete it.
+ * The function handles a NULL pointer transparently.
  */
 {
     if (LI) {
-       if (LI->Usage++ == 0) {
-           /* One more valid line info */
-           ++LineInfoValid;
-       }
+        if (LI->Usage > 0) {
+            CollAppend (&LineInfoColl, LI);
+        } else {
+            xfree (LI);
+        }
     }
-    return LI;
 }
 
 
 
-void GenLineInfo (unsigned FileIndex, unsigned long LineNum, unsigned ColNum)
-/* Generate a new line info */
+/*****************************************************************************/
+/*                                          Code                                    */
+/*****************************************************************************/
+
+
+
+void InitLineInfo (void)
+/* Initialize the line infos */
+{
+    /* Allocate 8 slots */
+    AllocatedSlots = 8;
+    CurLineInfo = xmalloc (AllocatedSlots * sizeof (LineInfoSlot));
+
+    /* Initalize the predefined slots */
+    UsedSlots = 2;
+    CurLineInfo[LI_SLOT_ASM].Type = LI_TYPE_ASM;
+    CurLineInfo[LI_SLOT_ASM].Info = 0;
+    CurLineInfo[LI_SLOT_EXT].Type = LI_TYPE_EXT; 
+    CurLineInfo[LI_SLOT_EXT].Info = 0;
+}
+
+
+
+unsigned AllocLineInfoSlot (unsigned Type)
+/* Allocate a line info slot of the given type and return the slot index */
+{
+    /* Grow the array if necessary */
+    if (UsedSlots >= AllocatedSlots) {
+        LineInfoSlot* NewLineInfo;
+        AllocatedSlots *= 2;
+        NewLineInfo = xmalloc (AllocatedSlots * sizeof (LineInfoSlot));
+        memcpy (NewLineInfo, CurLineInfo, UsedSlots * sizeof (LineInfoSlot));
+        xfree (CurLineInfo);
+        CurLineInfo = NewLineInfo;
+    }
+
+    /* Array is now big enough, add the new data */
+    CurLineInfo[UsedSlots].Type = Type;
+    CurLineInfo[UsedSlots].Info = 0;
+
+    /* Increment the count and return the index of the new slot */
+    return UsedSlots++;
+}
+
+
+
+void FreeLineInfoSlot (unsigned Slot)
+/* Free the line info in the given slot. Note: Alloc/Free must be used in
+ * FIFO order.
+ */
+{
+    /* Check the parameter */
+    PRECONDITION (Slot == UsedSlots - 1);
+
+    /* Free the last entry */
+    FreeLineInfo (CurLineInfo[Slot].Info);
+    --UsedSlots;
+}
+
+
+
+void GenLineInfo (unsigned Slot, unsigned File, unsigned long Line, unsigned Col)
+/* Generate a new line info in the given slot */
+{
+    /* Get a pointer to the slot */
+    LineInfoSlot* S = CurLineInfo + Slot;
+
+    /* Check if we already have data */
+    if (S->Info) {
+        /* Generate new data only if it is different from the existing. */
+        if (S->Info->Pos.Col == Col &&
+            S->Info->Pos.Line == Line &&
+            S->Info->Pos.Name == File) {
+            /* Already there */
+            return;
+        }
+
+        /* We have data, but it's not identical. If it is in use, copy it to
+         * line info collection, otherwise delete it.
+         */
+        FreeLineInfo (S->Info);
+
+    }
+
+    /* Allocate new data */
+    S->Info = NewLineInfo (S->Type, File, Line, Col);
+}
+
+
+
+void ClearLineInfo (unsigned Slot)
+/* Clear the line info in the given slot */
+{
+    /* Get a pointer to the slot */
+    LineInfoSlot* S = CurLineInfo + Slot;
+
+    /* Free the struct and zero the pointer */
+    FreeLineInfo (S->Info);
+    S->Info = 0;
+}
+
+
+
+LineInfo* GetLineInfo (unsigned Slot)
+/* Get the line info from the given slot */
 {
-    /* Create a new line info and make it current */
-    CurLineInfo = NewLineInfo (FileIndex, LineNum, ColNum);
+    PRECONDITION (Slot < UsedSlots);
+    return CurLineInfo[Slot].Info;
+}
+
+
+
+void GetFullLineInfo (Collection* LineInfos)
+/* Return full line infos, that is line infos for all slots in LineInfos. The
+ * function does also increase the usage counter for all line infos returned.
+ */
+{
+   unsigned I;
+
+    /* Copy all valid line infos to the collection */
+    for (I = 0; I < UsedSlots; ++I) {
+
+        /* Get the slot */
+        LineInfoSlot* S = CurLineInfo + I;
+
+        /* Ignore empty slots */
+        if (S->Info) {
+            ++S->Info->Usage;
+            CollAppend (LineInfos, S->Info);
+        }
+    }
+}
+
+
+
+LineInfo* UseLineInfo (LineInfo* LI)
+/* Increase the reference count of the given line info and return it. The
+ * function will gracefully accept NULL pointers and do nothing in this case.
+ */
+{
+    if (LI) {
+               ++LI->Usage;
+    }
+    return LI;
 }
 
 
 
-void ClearLineInfo (void)
-/* Clear the current line info */
+LineInfo* ReleaseLineInfo (LineInfo* LI)
+/* Decrease the reference count of the given line info and return it. The
+ * function will gracefully accept NULL pointers and do nothing in this case.
+ */
 {
-    CurLineInfo = 0;
+    if (LI) {
+        /* Cannot decrease below zero */
+               CHECK (LI->Usage != 0);
+        --LI->Usage;
+    }
+    return LI;
 }
 
 
 
 static int CmpLineInfo (void* Data attribute ((unused)),
-                       const void* LI1_, const void* LI2_)
+                       const void* LI1_, const void* LI2_)
 /* Compare function for the sort */
 {
     /* Cast the pointers */
@@ -138,21 +302,11 @@ static int CmpLineInfo (void* Data attribute ((unused)),
     const LineInfo* LI2 = LI2_;
 
     /* Unreferenced line infos are always larger, otherwise sort by file,
-     * then by line.
+     * then by line, then by column.
      */
     if ((LI1->Usage == 0) == (LI2->Usage == 0)) {
        /* Both are either referenced or unreferenced */
-               if (LI1->Pos.Name< LI2->Pos.Name) {
-           return -1;
-       } else if (LI1->Pos.Name > LI2->Pos.Name) {
-           return 1;
-       } else if (LI1->Pos.Line < LI2->Pos.Line) {
-           return -1;
-       } else if (LI1->Pos.Line > LI2->Pos.Line) {
-           return 1;
-       } else {
-           return 0;
-       }
+        return CompareFilePos (&LI1->Pos, &LI2->Pos);
     } else {
        if (LI1->Usage > 0) {
            return -1;
@@ -164,25 +318,54 @@ static int CmpLineInfo (void* Data attribute ((unused)),
 
 
 
+void WriteLineInfo (const Collection* LineInfos)
+/* Write a list of line infos to the object file. MakeLineInfoIndex has to
+ * be called before!
+ */
+{
+    unsigned I;
+
+    /* Write the count */
+    ObjWriteVar (CollCount (LineInfos));
+
+    /* Write the line info indices */
+    for (I = 0; I < CollCount (LineInfos); ++I) {
+        ObjWriteVar (((const LineInfo*) CollConstAt (LineInfos, I))->Index);
+    }
+}
+
+
+
 void MakeLineInfoIndex (void)
-/* Sort the line infos and drop all unreferenced ones */
+/* Index the line infos */
 {
     unsigned I;
 
     /* Sort the collection */
     CollSort (&LineInfoColl, CmpLineInfo, 0);
 
-    /* Walk over the list and index the line infos. */
-    for (I = 0; I < LineInfoValid; ++I) {
+    /* Walk over the list, index the line infos and count the used ones */
+    UsedLineInfoCount = 0;
+    for (I = 0; I < CollCount (&LineInfoColl); ++I) {
        /* Get a pointer to this line info */
        LineInfo* LI = CollAtUnchecked (&LineInfoColl, I);
-       LI->Index = I;
+
+        /* If it is invalid, terminate the loop. All unused line infos were
+         * placed at the end of the collection by the sort.
+         */
+        if (LI->Usage == 0) {
+            break;
+        }
+
+        /* Index and count this one */
+        LI->Index = I;
+        ++UsedLineInfoCount;
     }
 }
 
 
 
-void WriteLineInfo (void)
+void WriteLineInfos (void)
 /* Write a list of all line infos to the object file. */
 {
     /* Tell the object file module that we're about to write line infos */
@@ -194,15 +377,12 @@ void WriteLineInfo (void)
        unsigned I;
 
        /* Write the line info count to the list */
-               ObjWriteVar (LineInfoValid);
+               ObjWriteVar (UsedLineInfoCount);
 
-               /* Walk through list and write all line infos that have references.
-        * Because of the sort, this are exactly the first LineInfoValid
-        * ones.
-        */
-       for (I = 0; I < LineInfoValid; ++I) {
+               /* Walk over the list and write all line infos */
+       for (I = 0; I < UsedLineInfoCount; ++I) {
            /* Get a pointer to this line info */
-           LineInfo* LI = CollAtUnchecked (&LineInfoColl, I);
+           LineInfo* LI = CollAt (&LineInfoColl, I);
            /* Write the source file position */
            ObjWritePos (&LI->Pos);
        }
index 0d1ca495dc8d191eb21d449f065a7628655e82b7..ec654118ecc75a3287f528c8d08114aef95b3df3 100644 (file)
 #include "coll.h"
 #include "filepos.h"
 
-/* ca65 */
-#include "global.h"
-
 
 
 /*****************************************************************************/
-/*                                  Data                                    */
+/*                                  Data                                    */
 /*****************************************************************************/
 
 
 
+/* Predefined line info slots. These are allocated when initializing the
+ * module. Beware: Some code relies on the fact that slot zero is the basic
+ * standard line info. It is assumed to be always there.
+ */
+enum {
+    LI_SLOT_ASM         = 0,            /* Normal assembler source */
+    LI_SLOT_EXT         = 1,            /* Externally supplied line info */
+};
+
+/* Types of line infos. The low byte may be used for some sort of depth
+ * counter.
+ */
+enum {
+    LI_MASK_COUNT       = 0x00FF,       /* Mask to extract the count */
+
+    LI_TYPE_EXT         = 0x0100,       /* Externally supplied line info */
+    LI_TYPE_ASM         = 0x0200,       /* Normal assembler source */
+    LI_TYPE_MACRO       = 0x0300,       /* Macro expansion */
+    LI_MASK_TYPE        = 0x7F00,       /* Mask to extract the type */
+};
+
 /* The LineInfo structure is shared between several fragments, so we need a
  * reference counter.
  */
 typedef struct LineInfo LineInfo;
 struct LineInfo {
-    unsigned               Usage;                /* Usage counter */
-    unsigned        Index;                /* Index */
-    FilePos         Pos;                  /* File position */
+    unsigned    Usage;                  /* Usage counter */
+    unsigned    Type;                   /* Type of line info */
+    unsigned    Index;                  /* Index */
+    FilePos     Pos;                    /* File position */
 };
 
-/* Collection containing all line infos */
-extern Collection LineInfoColl;
-extern unsigned  LineInfoValid;           /* Valid, that is, used entries */
-
-/* Global pointer to last line info or NULL if not active */
-extern LineInfo* CurLineInfo;
-
 
 
 /*****************************************************************************/
@@ -88,23 +100,50 @@ extern LineInfo* CurLineInfo;
 
 
 
+void InitLineInfo (void);
+/* Initialize the line infos */
+
+unsigned AllocLineInfoSlot (unsigned Type);
+/* Allocate a line info slot of the given type and return the slot index */
+
+void FreeLineInfoSlot (unsigned Slot);
+/* Free the line info in the given slot. Note: Alloc/Free must be used in
+ * FIFO order.
+ */
+
+void GenLineInfo (unsigned Slot, unsigned File, unsigned long Line, unsigned Col);
+/* Generate a new line info in the given slot */
+
+void ClearLineInfo (unsigned Slot);
+/* Clear the line info in the given slot */
+
+LineInfo* GetLineInfo (unsigned Slot);
+/* Get the line info from the given slot */
+
+void GetFullLineInfo (Collection* LineInfos);
+/* Return full line infos, that is line infos for all slots in LineInfos. The
+ * function does also increase the usage counter for all line infos returned.
+ */
+
 LineInfo* UseLineInfo (LineInfo* LI);
 /* Increase the reference count of the given line info and return it. The
  * function will gracefully accept NULL pointers and do nothing in this case.
  */
 
-void GenLineInfo (unsigned FileIndex, unsigned long LineNum, unsigned ColNum);
-/* Generate a new line info */
+LineInfo* ReleaseLineInfo (LineInfo* LI);
+/* Decrease the reference count of the given line info and return it. The
+ * function will gracefully accept NULL pointers and do nothing in this case.
+ */
 
-void ClearLineInfo (void);
-/* Clear the current line info */
+void WriteLineInfo (const Collection* LineInfos);
+/* Write a list of line infos to the object file. MakeLineInfoIndex has to
+ * be called before!
+ */
 
 void MakeLineInfoIndex (void);
-/* Walk over the line info list and make an index of all entries ignoring
- * those with a usage count of zero.
- */
+/* Index the line infos */
 
-void WriteLineInfo (void);
+void WriteLineInfos (void);
 /* Write a list of all line infos to the object file. */
 
 
index 53bd5be48dca1fae4980683883f201bb8155cf8d..a5db62559750a994032965c69acc8f7a49ee4d38 100644 (file)
@@ -805,7 +805,7 @@ static void CreateObjFile (void)
     WriteDbgSyms ();
 
     /* Write line infos if requested */
-    WriteLineInfo ();
+    WriteLineInfos ();
 
     /* Write the string pool */
     WriteStrPool ();
@@ -902,7 +902,7 @@ int main (int argc, char* argv [])
                     break;
 
                        case 'o':
-                           OutFile = GetArg (&I, 2);
+                           OutFile = GetArg (&I, 2);
                            break;
 
                        case 's':
@@ -926,7 +926,7 @@ int main (int argc, char* argv [])
                    break;
 
                        case 'U':
-                   OptAutoImport (Arg, 0);
+                   OptAutoImport (Arg, 0);
                            break;
 
                        case 'V':
@@ -980,6 +980,9 @@ int main (int argc, char* argv [])
     /* Initialize the segments */
     InitSegments ();
 
+    /* Initialize the line infos */
+    InitLineInfo ();
+
     /* Initialize the scanner, open the input file */
     InitScanner (InFile);
 
index 0f07ce52b80d3084249f637539725e6dc840db8d..b94123058e82f81ba21431782141708e7c6259f5 100644 (file)
@@ -371,24 +371,24 @@ void SegCheck (void)
                        if (Abs) {
                            /* Absolute value */
                            if (Val > 255) {
-                               PError (&F->Pos, "Range error (%ld not in [0..255])", Val);
+                               LIError (&F->LI, "Range error (%ld not in [0..255])", Val);
                            }
                        } else {
                            /* PC relative value */
                            if (Val < -128 || Val > 127) {
-                               PError (&F->Pos, "Range error (%ld not in [-128..127])", Val);
+                               LIError (&F->LI, "Range error (%ld not in [-128..127])", Val);
                            }
                        }
                    } else if (F->Len == 2) {
                        if (Abs) {
                            /* Absolute value */
                            if (Val > 65535) {
-                               PError (&F->Pos, "Range error (%ld not in [0..65535])", Val);
+                               LIError (&F->LI, "Range error (%ld not in [0..65535])", Val);
                            }
                        } else {
                            /* PC relative value */
                            if (Val < -32768 || Val > 32767) {
-                               PError (&F->Pos, "Range error (%ld not in [-32768..32767])", Val);
+                               LIError (&F->LI, "Range error (%ld not in [-32768..32767])", Val);
                            }
                        }
                    }
@@ -412,7 +412,7 @@ void SegCheck (void)
                     if ((F->Len == 1 && ED.AddrSize > ADDR_SIZE_ZP)  ||
                         (F->Len == 2 && ED.AddrSize > ADDR_SIZE_ABS) ||
                         (F->Len == 3 && ED.AddrSize > ADDR_SIZE_FAR)) {
-                       PError (&F->Pos, "Range error");
+                       LIError (&F->LI, "Range error");
                    }
                }
 
@@ -477,7 +477,6 @@ static void WriteOneSeg (Segment* Seg)
 /* Write one segment to the object file */
 {
     Fragment* Frag;
-    unsigned LineInfoIndex;
     unsigned long DataSize;
     unsigned long EndPos;
 
@@ -541,14 +540,8 @@ static void WriteOneSeg (Segment* Seg)
 
        }
 
-               /* 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);
+               /* Write the line infos for this fragment */
+               WriteLineInfo (&Frag->LI);
 
        /* Next fragment */
        Frag = Frag->Next;
@@ -620,3 +613,4 @@ void WriteSegments (void)
 
 
 
+