2001-05-23 07:04:09 +00:00
|
|
|
/*****************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* lineinfo.c */
|
|
|
|
/* */
|
|
|
|
/* Source file line info structure */
|
|
|
|
/* */
|
|
|
|
/* */
|
|
|
|
/* */
|
2011-01-20 20:54:30 +00:00
|
|
|
/* (C) 2001-2011, Ullrich von Bassewitz */
|
|
|
|
/* Roemerstrasse 52 */
|
|
|
|
/* 70794 Filderstadt */
|
|
|
|
/* EMail: uz@cc65.org */
|
2001-05-23 07:04:09 +00:00
|
|
|
/* */
|
|
|
|
/* */
|
|
|
|
/* 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. */
|
|
|
|
/* */
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-01-24 22:38:22 +00:00
|
|
|
#include <string.h>
|
|
|
|
#include <limits.h>
|
|
|
|
|
2001-05-23 07:04:09 +00:00
|
|
|
/* common */
|
|
|
|
#include "coll.h"
|
|
|
|
#include "xmalloc.h"
|
|
|
|
|
|
|
|
/* ca65 */
|
2011-01-24 22:38:22 +00:00
|
|
|
#include "global.h"
|
2001-05-23 07:04:09 +00:00
|
|
|
#include "lineinfo.h"
|
2011-01-24 22:38:22 +00:00
|
|
|
#include "objfile.h"
|
2001-05-23 07:04:09 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
2011-01-24 22:38:22 +00:00
|
|
|
/* Data */
|
2001-05-23 07:04:09 +00:00
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-01-24 22:38:22 +00:00
|
|
|
/* An invalid line info index */
|
|
|
|
#define INV_LINEINFO_INDEX UINT_MAX
|
|
|
|
|
2001-05-23 22:02:19 +00:00
|
|
|
/* Collection containing all line infos */
|
2011-01-24 22:38:22 +00:00
|
|
|
static Collection LineInfoColl = STATIC_COLLECTION_INITIALIZER;
|
2001-05-23 07:04:09 +00:00
|
|
|
|
2011-01-24 22:38:22 +00:00
|
|
|
/* 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;
|
2001-05-23 07:04:09 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
2011-01-24 22:38:22 +00:00
|
|
|
/* struct LineInfo */
|
2001-05-23 07:04:09 +00:00
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-01-27 16:39:30 +00:00
|
|
|
static LineInfo* NewLineInfo (unsigned Type, const FilePos* Pos)
|
2001-05-23 07:04:09 +00:00
|
|
|
/* Create and return a new line info. Usage will be zero. */
|
|
|
|
{
|
|
|
|
/* Allocate memory */
|
|
|
|
LineInfo* LI = xmalloc (sizeof (LineInfo));
|
|
|
|
|
|
|
|
/* Initialize the fields */
|
2011-01-27 16:39:30 +00:00
|
|
|
LI->Usage = 0;
|
|
|
|
LI->Type = Type;
|
|
|
|
LI->Index = INV_LINEINFO_INDEX;
|
|
|
|
LI->Pos = *Pos;
|
2001-05-23 07:04:09 +00:00
|
|
|
|
2011-01-29 18:43:36 +00:00
|
|
|
/* Add the line info to the list of all line infos */
|
|
|
|
CollAppend (&LineInfoColl, LI);
|
|
|
|
|
2001-05-23 07:04:09 +00:00
|
|
|
/* Return the new struct */
|
|
|
|
return LI;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-01-24 22:38:22 +00:00
|
|
|
/*****************************************************************************/
|
|
|
|
/* Code */
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void InitLineInfo (void)
|
|
|
|
/* Initialize the line infos */
|
|
|
|
{
|
2011-01-27 16:39:30 +00:00
|
|
|
static const FilePos DefaultPos = STATIC_FILEPOS_INITIALIZER;
|
|
|
|
|
2011-01-29 18:43:36 +00:00
|
|
|
/* Increase the initial count of the line info collection */
|
|
|
|
CollGrow (&LineInfoColl, 200);
|
|
|
|
|
2011-01-24 22:38:22 +00:00
|
|
|
/* Allocate 8 slots */
|
|
|
|
AllocatedSlots = 8;
|
|
|
|
CurLineInfo = xmalloc (AllocatedSlots * sizeof (LineInfoSlot));
|
|
|
|
|
2011-01-27 16:39:30 +00:00
|
|
|
/* Initalize the predefined slots. Be sure to ccreate a new LineInfo for
|
|
|
|
* the default source. This is necessary to allow error message to be
|
|
|
|
* generated without any input file open.
|
|
|
|
*/
|
2011-01-24 22:38:22 +00:00
|
|
|
UsedSlots = 2;
|
2011-01-29 22:16:03 +00:00
|
|
|
CurLineInfo[LI_SLOT_ASM].Type = LI_TYPE_ASM; /* Count = 0 */
|
2011-01-27 16:39:30 +00:00
|
|
|
CurLineInfo[LI_SLOT_ASM].Info = NewLineInfo (LI_TYPE_ASM, &DefaultPos);
|
2011-01-29 22:16:03 +00:00
|
|
|
CurLineInfo[LI_SLOT_EXT].Type = LI_TYPE_EXT; /* Count = 0 */
|
2011-01-24 22:38:22 +00:00
|
|
|
CurLineInfo[LI_SLOT_EXT].Info = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-06-13 08:53:41 +00:00
|
|
|
int AllocLineInfoSlot (unsigned Type, unsigned Count)
|
2011-01-24 22:38:22 +00:00
|
|
|
/* 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 */
|
2011-01-29 22:16:03 +00:00
|
|
|
CurLineInfo[UsedSlots].Type = LI_MAKE_TYPE(Type, Count);
|
2011-01-24 22:38:22 +00:00
|
|
|
CurLineInfo[UsedSlots].Info = 0;
|
|
|
|
|
|
|
|
/* Increment the count and return the index of the new slot */
|
2011-06-13 08:53:41 +00:00
|
|
|
return (int) UsedSlots++;
|
2011-01-24 22:38:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-06-13 08:53:41 +00:00
|
|
|
void FreeLineInfoSlot (int Slot)
|
2011-01-24 22:38:22 +00:00
|
|
|
/* Free the line info in the given slot. Note: Alloc/Free must be used in
|
|
|
|
* FIFO order.
|
|
|
|
*/
|
|
|
|
{
|
|
|
|
/* Check the parameter */
|
2011-06-13 08:53:41 +00:00
|
|
|
PRECONDITION (Slot == (int) UsedSlots - 1);
|
2011-01-24 22:38:22 +00:00
|
|
|
|
|
|
|
/* Free the last entry */
|
2011-01-29 18:43:36 +00:00
|
|
|
CurLineInfo[Slot].Info = 0;
|
2011-01-24 22:38:22 +00:00
|
|
|
--UsedSlots;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-06-13 08:53:41 +00:00
|
|
|
void GenLineInfo (int Slot, const FilePos* Pos)
|
2011-01-24 22:38:22 +00:00
|
|
|
/* Generate a new line info in the given slot */
|
|
|
|
{
|
|
|
|
/* Get a pointer to the slot */
|
|
|
|
LineInfoSlot* S = CurLineInfo + Slot;
|
|
|
|
|
2011-01-29 18:43:36 +00:00
|
|
|
/* Generate new data only if it is different from the existing. */
|
|
|
|
if (S->Info && CompareFilePos (&S->Info->Pos, Pos) == 0) {
|
|
|
|
/* Already there */
|
|
|
|
return;
|
2011-01-24 22:38:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Allocate new data */
|
2011-01-27 16:39:30 +00:00
|
|
|
S->Info = NewLineInfo (S->Type, Pos);
|
2011-01-24 22:38:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-06-13 08:53:41 +00:00
|
|
|
void ClearLineInfo (int Slot)
|
2011-01-24 22:38:22 +00:00
|
|
|
/* Clear the line info in the given slot */
|
|
|
|
{
|
2011-01-29 18:43:36 +00:00
|
|
|
/* Zero the pointer */
|
|
|
|
CurLineInfo[Slot].Info = 0;
|
2011-01-24 22:38:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-01-29 18:43:36 +00:00
|
|
|
void GetFullLineInfo (Collection* LineInfos, unsigned IncUsage)
|
2011-01-24 22:38:22 +00:00
|
|
|
/* Return full line infos, that is line infos for all slots in LineInfos. The
|
2011-01-29 18:43:36 +00:00
|
|
|
* function will clear LineInfos before usage and will increment the usage
|
|
|
|
* counter by IncUsage for all line infos returned.
|
2011-01-24 22:38:22 +00:00
|
|
|
*/
|
|
|
|
{
|
2011-01-29 18:43:36 +00:00
|
|
|
unsigned I;
|
|
|
|
|
|
|
|
/* Clear the collection */
|
|
|
|
CollDeleteAll (LineInfos);
|
2011-01-24 22:38:22 +00:00
|
|
|
|
|
|
|
/* Copy all valid line infos to the collection */
|
|
|
|
for (I = 0; I < UsedSlots; ++I) {
|
|
|
|
|
2011-01-29 18:43:36 +00:00
|
|
|
/* Get the line info from the slot */
|
|
|
|
LineInfo* LI = CurLineInfo[I].Info;
|
2011-01-24 22:38:22 +00:00
|
|
|
|
|
|
|
/* Ignore empty slots */
|
2011-01-29 18:43:36 +00:00
|
|
|
if (LI) {
|
|
|
|
LI->Usage += IncUsage;
|
|
|
|
CollAppend (LineInfos, LI);
|
2011-01-24 22:38:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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;
|
2001-05-23 07:04:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-01-24 22:38:22 +00:00
|
|
|
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.
|
|
|
|
*/
|
2001-05-23 19:03:40 +00:00
|
|
|
{
|
2011-01-24 22:38:22 +00:00
|
|
|
if (LI) {
|
|
|
|
/* Cannot decrease below zero */
|
|
|
|
CHECK (LI->Usage != 0);
|
|
|
|
--LI->Usage;
|
|
|
|
}
|
|
|
|
return LI;
|
2001-05-23 19:03:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-01-20 20:54:30 +00:00
|
|
|
static int CmpLineInfo (void* Data attribute ((unused)),
|
2011-01-27 16:39:30 +00:00
|
|
|
const void* LI1_, const void* LI2_)
|
2001-05-23 22:02:19 +00:00
|
|
|
/* Compare function for the sort */
|
2001-05-23 07:04:09 +00:00
|
|
|
{
|
2001-05-23 22:02:19 +00:00
|
|
|
/* Cast the pointers */
|
|
|
|
const LineInfo* LI1 = LI1_;
|
|
|
|
const LineInfo* LI2 = LI2_;
|
|
|
|
|
|
|
|
/* Unreferenced line infos are always larger, otherwise sort by file,
|
2011-01-24 22:38:22 +00:00
|
|
|
* then by line, then by column.
|
2001-05-23 22:02:19 +00:00
|
|
|
*/
|
|
|
|
if ((LI1->Usage == 0) == (LI2->Usage == 0)) {
|
|
|
|
/* Both are either referenced or unreferenced */
|
2011-01-24 22:38:22 +00:00
|
|
|
return CompareFilePos (&LI1->Pos, &LI2->Pos);
|
2001-05-23 22:02:19 +00:00
|
|
|
} else {
|
|
|
|
if (LI1->Usage > 0) {
|
|
|
|
return -1;
|
|
|
|
} else {
|
|
|
|
return 1;
|
2001-05-23 07:04:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-01-20 20:54:30 +00:00
|
|
|
|
2001-05-23 07:04:09 +00:00
|
|
|
|
2011-01-24 22:38:22 +00:00
|
|
|
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) {
|
2011-01-27 16:39:30 +00:00
|
|
|
|
|
|
|
/* Get a pointer to the line info */
|
|
|
|
const LineInfo* LI = CollConstAt (LineInfos, I);
|
|
|
|
|
|
|
|
/* Check the index */
|
|
|
|
CHECK (LI->Index != INV_LINEINFO_INDEX);
|
|
|
|
|
|
|
|
/* Write the index to the file */
|
|
|
|
ObjWriteVar (LI->Index);
|
2011-01-24 22:38:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2001-05-23 22:02:19 +00:00
|
|
|
void MakeLineInfoIndex (void)
|
2011-01-24 22:38:22 +00:00
|
|
|
/* Index the line infos */
|
2001-05-23 22:02:19 +00:00
|
|
|
{
|
2001-05-29 07:39:01 +00:00
|
|
|
unsigned I;
|
|
|
|
|
2011-01-29 18:43:36 +00:00
|
|
|
/* Sort the line info list */
|
2001-05-23 22:02:19 +00:00
|
|
|
CollSort (&LineInfoColl, CmpLineInfo, 0);
|
2001-05-29 07:39:01 +00:00
|
|
|
|
2011-01-24 22:38:22 +00:00
|
|
|
/* Walk over the list, index the line infos and count the used ones */
|
|
|
|
UsedLineInfoCount = 0;
|
|
|
|
for (I = 0; I < CollCount (&LineInfoColl); ++I) {
|
2001-05-29 07:39:01 +00:00
|
|
|
/* Get a pointer to this line info */
|
|
|
|
LineInfo* LI = CollAtUnchecked (&LineInfoColl, I);
|
2011-01-24 22:38:22 +00:00
|
|
|
|
|
|
|
/* 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;
|
2001-05-29 07:39:01 +00:00
|
|
|
}
|
2001-05-23 22:02:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-01-24 22:38:22 +00:00
|
|
|
void WriteLineInfos (void)
|
2001-05-23 19:03:40 +00:00
|
|
|
/* Write a list of all line infos to the object file. */
|
|
|
|
{
|
2011-01-27 16:39:30 +00:00
|
|
|
unsigned I;
|
|
|
|
|
2001-05-23 19:03:40 +00:00
|
|
|
/* Tell the object file module that we're about to write line infos */
|
|
|
|
ObjStartLineInfos ();
|
|
|
|
|
2011-01-27 16:39:30 +00:00
|
|
|
/* Write the line info count to the list */
|
|
|
|
ObjWriteVar (UsedLineInfoCount);
|
2001-05-23 19:03:40 +00:00
|
|
|
|
2011-01-27 16:39:30 +00:00
|
|
|
/* Walk over the list and write all line infos */
|
|
|
|
for (I = 0; I < UsedLineInfoCount; ++I) {
|
|
|
|
/* Get a pointer to this line info */
|
|
|
|
LineInfo* LI = CollAt (&LineInfoColl, I);
|
2011-01-29 22:16:03 +00:00
|
|
|
|
|
|
|
/* Write the type and count of the line info */
|
|
|
|
ObjWriteVar (LI->Type);
|
|
|
|
|
2011-01-27 16:39:30 +00:00
|
|
|
/* Write the source file position */
|
|
|
|
ObjWritePos (&LI->Pos);
|
2001-05-23 19:03:40 +00:00
|
|
|
}
|
2001-05-29 07:39:01 +00:00
|
|
|
|
|
|
|
/* End of line infos */
|
|
|
|
ObjEndLineInfos ();
|
2001-05-23 19:03:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|