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 /*****************************************************************************/
50 /*****************************************************************************/
52 /*****************************************************************************/
56 /* An invalid line info index */
57 #define INV_LINEINFO_INDEX UINT_MAX
59 /* Collection containing all line infos */
60 static Collection LineInfoColl = STATIC_COLLECTION_INITIALIZER;
62 /* Number of valid (=used) line infos in LineInfoColl */
63 static unsigned UsedLineInfoCount;
65 /* Entry in CurLineInfo */
66 typedef struct LineInfoSlot LineInfoSlot;
72 /* Dynamically allocated array of LineInfoSlots */
73 static LineInfoSlot* CurLineInfo;
74 static unsigned AllocatedSlots;
75 static unsigned UsedSlots;
79 /*****************************************************************************/
81 /*****************************************************************************/
85 static LineInfo* NewLineInfo (unsigned Type, const FilePos* Pos)
86 /* Create and return a new line info. Usage will be zero. */
89 LineInfo* LI = xmalloc (sizeof (LineInfo));
91 /* Initialize the fields */
94 LI->Index = INV_LINEINFO_INDEX;
97 /* Return the new struct */
103 static void FreeLineInfo (LineInfo* LI)
104 /* "Free" line info. If the usage counter is non zero, move it to the
105 * collection that contains all line infos, otherwise delete it.
106 * The function handles a NULL pointer transparently.
111 CollAppend (&LineInfoColl, LI);
120 /*****************************************************************************/
122 /*****************************************************************************/
126 void InitLineInfo (void)
127 /* Initialize the line infos */
129 static const FilePos DefaultPos = STATIC_FILEPOS_INITIALIZER;
131 /* Allocate 8 slots */
133 CurLineInfo = xmalloc (AllocatedSlots * sizeof (LineInfoSlot));
135 /* Initalize the predefined slots. Be sure to ccreate a new LineInfo for
136 * the default source. This is necessary to allow error message to be
137 * generated without any input file open.
140 CurLineInfo[LI_SLOT_ASM].Type = LI_TYPE_ASM;
141 CurLineInfo[LI_SLOT_ASM].Info = NewLineInfo (LI_TYPE_ASM, &DefaultPos);
142 CurLineInfo[LI_SLOT_EXT].Type = LI_TYPE_EXT;
143 CurLineInfo[LI_SLOT_EXT].Info = 0;
148 unsigned AllocLineInfoSlot (unsigned Type)
149 /* Allocate a line info slot of the given type and return the slot index */
151 /* Grow the array if necessary */
152 if (UsedSlots >= AllocatedSlots) {
153 LineInfoSlot* NewLineInfo;
155 NewLineInfo = xmalloc (AllocatedSlots * sizeof (LineInfoSlot));
156 memcpy (NewLineInfo, CurLineInfo, UsedSlots * sizeof (LineInfoSlot));
158 CurLineInfo = NewLineInfo;
161 /* Array is now big enough, add the new data */
162 CurLineInfo[UsedSlots].Type = Type;
163 CurLineInfo[UsedSlots].Info = 0;
165 /* Increment the count and return the index of the new slot */
171 void FreeLineInfoSlot (unsigned Slot)
172 /* Free the line info in the given slot. Note: Alloc/Free must be used in
176 /* Check the parameter */
177 PRECONDITION (Slot == UsedSlots - 1);
179 /* Free the last entry */
180 FreeLineInfo (CurLineInfo[Slot].Info);
186 void GenLineInfo (unsigned Slot, const FilePos* Pos)
187 /* Generate a new line info in the given slot */
189 /* Get a pointer to the slot */
190 LineInfoSlot* S = CurLineInfo + Slot;
192 /* Check if we already have data */
194 /* Generate new data only if it is different from the existing. */
195 if (CompareFilePos (&S->Info->Pos, Pos) == 0) {
200 /* We have data, but it's not identical. If it is in use, copy it to
201 * line info collection, otherwise delete it.
203 FreeLineInfo (S->Info);
207 /* Allocate new data */
208 S->Info = NewLineInfo (S->Type, Pos);
213 void ClearLineInfo (unsigned Slot)
214 /* Clear the line info in the given slot */
216 /* Get a pointer to the slot */
217 LineInfoSlot* S = CurLineInfo + Slot;
219 /* Free the struct and zero the pointer */
220 FreeLineInfo (S->Info);
226 LineInfo* GetLineInfo (unsigned Slot)
227 /* Get the line info from the given slot */
229 PRECONDITION (Slot < UsedSlots);
230 return CurLineInfo[Slot].Info;
235 void GetFullLineInfo (Collection* LineInfos)
236 /* Return full line infos, that is line infos for all slots in LineInfos. The
237 * function does also increase the usage counter for all line infos returned.
242 /* Copy all valid line infos to the collection */
243 for (I = 0; I < UsedSlots; ++I) {
246 LineInfoSlot* S = CurLineInfo + I;
248 /* Ignore empty slots */
251 CollAppend (LineInfos, S->Info);
258 LineInfo* UseLineInfo (LineInfo* LI)
259 /* Increase the reference count of the given line info and return it. The
260 * function will gracefully accept NULL pointers and do nothing in this case.
271 LineInfo* ReleaseLineInfo (LineInfo* LI)
272 /* Decrease the reference count of the given line info and return it. The
273 * function will gracefully accept NULL pointers and do nothing in this case.
277 /* Cannot decrease below zero */
278 CHECK (LI->Usage != 0);
286 static int CmpLineInfo (void* Data attribute ((unused)),
287 const void* LI1_, const void* LI2_)
288 /* Compare function for the sort */
290 /* Cast the pointers */
291 const LineInfo* LI1 = LI1_;
292 const LineInfo* LI2 = LI2_;
294 /* Unreferenced line infos are always larger, otherwise sort by file,
295 * then by line, then by column.
297 if ((LI1->Usage == 0) == (LI2->Usage == 0)) {
298 /* Both are either referenced or unreferenced */
299 return CompareFilePos (&LI1->Pos, &LI2->Pos);
301 if (LI1->Usage > 0) {
311 void WriteLineInfo (const Collection* LineInfos)
312 /* Write a list of line infos to the object file. MakeLineInfoIndex has to
318 /* Write the count */
319 ObjWriteVar (CollCount (LineInfos));
321 /* Write the line info indices */
322 for (I = 0; I < CollCount (LineInfos); ++I) {
324 /* Get a pointer to the line info */
325 const LineInfo* LI = CollConstAt (LineInfos, I);
327 /* Check the index */
328 CHECK (LI->Index != INV_LINEINFO_INDEX);
330 /* Write the index to the file */
331 ObjWriteVar (LI->Index);
337 void MakeLineInfoIndex (void)
338 /* Index the line infos */
342 /* Be sure to move pending line infos to the global list */
343 for (I = 0; I < UsedSlots; ++I) {
344 FreeLineInfo (CurLineInfo[I].Info);
347 /* Sort the collection */
348 CollSort (&LineInfoColl, CmpLineInfo, 0);
350 /* Walk over the list, index the line infos and count the used ones */
351 UsedLineInfoCount = 0;
352 for (I = 0; I < CollCount (&LineInfoColl); ++I) {
353 /* Get a pointer to this line info */
354 LineInfo* LI = CollAtUnchecked (&LineInfoColl, I);
356 /* If it is invalid, terminate the loop. All unused line infos were
357 * placed at the end of the collection by the sort.
359 if (LI->Usage == 0) {
363 /* Index and count this one */
371 void WriteLineInfos (void)
372 /* Write a list of all line infos to the object file. */
376 /* Tell the object file module that we're about to write line infos */
377 ObjStartLineInfos ();
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);
390 /* End of line infos */