1 /*****************************************************************************/
5 /* Source file line info structure */
9 /* (C) 2001-2011, Ullrich von Bassewitz */
10 /* Roemerstrasse 52 */
11 /* 70794 Filderstadt */
12 /* EMail: uz@cc65.org */
15 /* This software is provided 'as-is', without any expressed or implied */
16 /* warranty. In no event will the authors be held liable for any damages */
17 /* arising from the use of this software. */
19 /* Permission is granted to anyone to use this software for any purpose, */
20 /* including commercial applications, and to alter it and redistribute it */
21 /* freely, subject to the following restrictions: */
23 /* 1. The origin of this software must not be misrepresented; you must not */
24 /* claim that you wrote the original software. If you use this software */
25 /* in a product, an acknowledgment in the product documentation would be */
26 /* appreciated but is not required. */
27 /* 2. Altered source versions must be plainly marked as such, and must not */
28 /* be misrepresented as being the original software. */
29 /* 3. This notice may not be removed or altered from any source */
32 /*****************************************************************************/
36 /* Note: The line infos kept here are additional line infos supplied by the
37 * ".dbg line" command. The native line infos are always kept in the fragments
38 * itself (because one fragment always originates from one line). The
39 * additional line infos (which may not exist if none are supplied in the
40 * source) may have several fragments attached (as is the case with sources
41 * generated by the C compiler).
60 /*****************************************************************************/
62 /*****************************************************************************/
66 /* An invalid line info index */
67 #define INV_LINEINFO_INDEX UINT_MAX
69 /* Collection containing all line infos */
70 static Collection LineInfoColl = STATIC_COLLECTION_INITIALIZER;
72 /* Number of valid (=used) line infos in LineInfoColl */
73 static unsigned UsedLineInfoCount;
75 /* Entry in CurLineInfo */
76 typedef struct LineInfoSlot LineInfoSlot;
82 /* Dynamically allocated array of LineInfoSlots */
83 static LineInfoSlot* CurLineInfo;
84 static unsigned AllocatedSlots;
85 static unsigned UsedSlots;
89 /*****************************************************************************/
91 /*****************************************************************************/
95 static LineInfo* NewLineInfo (unsigned Type, unsigned File,
96 unsigned long Line, unsigned Col)
97 /* Create and return a new line info. Usage will be zero. */
100 LineInfo* LI = xmalloc (sizeof (LineInfo));
102 /* Initialize the fields */
105 LI->Index = INV_LINEINFO_INDEX;
110 /* Return the new struct */
116 static void FreeLineInfo (LineInfo* LI)
117 /* "Free" line info. If the usage counter is non zero, move it to the
118 * collection that contains all line infos, otherwise delete it.
119 * The function handles a NULL pointer transparently.
124 CollAppend (&LineInfoColl, LI);
133 /*****************************************************************************/
135 /*****************************************************************************/
139 void InitLineInfo (void)
140 /* Initialize the line infos */
142 /* Allocate 8 slots */
144 CurLineInfo = xmalloc (AllocatedSlots * sizeof (LineInfoSlot));
146 /* Initalize the predefined slots */
148 CurLineInfo[LI_SLOT_ASM].Type = LI_TYPE_ASM;
149 CurLineInfo[LI_SLOT_ASM].Info = 0;
150 CurLineInfo[LI_SLOT_EXT].Type = LI_TYPE_EXT;
151 CurLineInfo[LI_SLOT_EXT].Info = 0;
156 unsigned AllocLineInfoSlot (unsigned Type)
157 /* Allocate a line info slot of the given type and return the slot index */
159 /* Grow the array if necessary */
160 if (UsedSlots >= AllocatedSlots) {
161 LineInfoSlot* NewLineInfo;
163 NewLineInfo = xmalloc (AllocatedSlots * sizeof (LineInfoSlot));
164 memcpy (NewLineInfo, CurLineInfo, UsedSlots * sizeof (LineInfoSlot));
166 CurLineInfo = NewLineInfo;
169 /* Array is now big enough, add the new data */
170 CurLineInfo[UsedSlots].Type = Type;
171 CurLineInfo[UsedSlots].Info = 0;
173 /* Increment the count and return the index of the new slot */
179 void FreeLineInfoSlot (unsigned Slot)
180 /* Free the line info in the given slot. Note: Alloc/Free must be used in
184 /* Check the parameter */
185 PRECONDITION (Slot == UsedSlots - 1);
187 /* Free the last entry */
188 FreeLineInfo (CurLineInfo[Slot].Info);
194 void GenLineInfo (unsigned Slot, unsigned File, unsigned long Line, unsigned Col)
195 /* Generate a new line info in the given slot */
197 /* Get a pointer to the slot */
198 LineInfoSlot* S = CurLineInfo + Slot;
200 /* Check if we already have data */
202 /* Generate new data only if it is different from the existing. */
203 if (S->Info->Pos.Col == Col &&
204 S->Info->Pos.Line == Line &&
205 S->Info->Pos.Name == File) {
210 /* We have data, but it's not identical. If it is in use, copy it to
211 * line info collection, otherwise delete it.
213 FreeLineInfo (S->Info);
217 /* Allocate new data */
218 S->Info = NewLineInfo (S->Type, File, Line, Col);
223 void ClearLineInfo (unsigned Slot)
224 /* Clear the line info in the given slot */
226 /* Get a pointer to the slot */
227 LineInfoSlot* S = CurLineInfo + Slot;
229 /* Free the struct and zero the pointer */
230 FreeLineInfo (S->Info);
236 LineInfo* GetLineInfo (unsigned Slot)
237 /* Get the line info from the given slot */
239 PRECONDITION (Slot < UsedSlots);
240 return CurLineInfo[Slot].Info;
245 void GetFullLineInfo (Collection* LineInfos)
246 /* Return full line infos, that is line infos for all slots in LineInfos. The
247 * function does also increase the usage counter for all line infos returned.
252 /* Copy all valid line infos to the collection */
253 for (I = 0; I < UsedSlots; ++I) {
256 LineInfoSlot* S = CurLineInfo + I;
258 /* Ignore empty slots */
261 CollAppend (LineInfos, S->Info);
268 LineInfo* UseLineInfo (LineInfo* LI)
269 /* Increase the reference count of the given line info and return it. The
270 * function will gracefully accept NULL pointers and do nothing in this case.
281 LineInfo* ReleaseLineInfo (LineInfo* LI)
282 /* Decrease the reference count of the given line info and return it. The
283 * function will gracefully accept NULL pointers and do nothing in this case.
287 /* Cannot decrease below zero */
288 CHECK (LI->Usage != 0);
296 static int CmpLineInfo (void* Data attribute ((unused)),
297 const void* LI1_, const void* LI2_)
298 /* Compare function for the sort */
300 /* Cast the pointers */
301 const LineInfo* LI1 = LI1_;
302 const LineInfo* LI2 = LI2_;
304 /* Unreferenced line infos are always larger, otherwise sort by file,
305 * then by line, then by column.
307 if ((LI1->Usage == 0) == (LI2->Usage == 0)) {
308 /* Both are either referenced or unreferenced */
309 return CompareFilePos (&LI1->Pos, &LI2->Pos);
311 if (LI1->Usage > 0) {
321 void WriteLineInfo (const Collection* LineInfos)
322 /* Write a list of line infos to the object file. MakeLineInfoIndex has to
328 /* Write the count */
329 ObjWriteVar (CollCount (LineInfos));
331 /* Write the line info indices */
332 for (I = 0; I < CollCount (LineInfos); ++I) {
333 ObjWriteVar (((const LineInfo*) CollConstAt (LineInfos, I))->Index);
339 void MakeLineInfoIndex (void)
340 /* Index the line infos */
344 /* Sort the collection */
345 CollSort (&LineInfoColl, CmpLineInfo, 0);
347 /* Walk over the list, index the line infos and count the used ones */
348 UsedLineInfoCount = 0;
349 for (I = 0; I < CollCount (&LineInfoColl); ++I) {
350 /* Get a pointer to this line info */
351 LineInfo* LI = CollAtUnchecked (&LineInfoColl, I);
353 /* If it is invalid, terminate the loop. All unused line infos were
354 * placed at the end of the collection by the sort.
356 if (LI->Usage == 0) {
360 /* Index and count this one */
368 void WriteLineInfos (void)
369 /* Write a list of all line infos to the object file. */
371 /* Tell the object file module that we're about to write line infos */
372 ObjStartLineInfos ();
374 /* Check if debug info is requested */
379 /* Write the line info count to the list */
380 ObjWriteVar (UsedLineInfoCount);
382 /* Walk over the list and write all line infos */
383 for (I = 0; I < UsedLineInfoCount; ++I) {
384 /* Get a pointer to this line info */
385 LineInfo* LI = CollAt (&LineInfoColl, I);
386 /* Write the source file position */
387 ObjWritePos (&LI->Pos);
397 /* End of line infos */