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 /* Add the line info to the list of all line infos */
98 CollAppend (&LineInfoColl, LI);
100 /* Return the new struct */
106 /*****************************************************************************/
108 /*****************************************************************************/
112 void InitLineInfo (void)
113 /* Initialize the line infos */
115 static const FilePos DefaultPos = STATIC_FILEPOS_INITIALIZER;
117 /* Increase the initial count of the line info collection */
118 CollGrow (&LineInfoColl, 200);
120 /* Allocate 8 slots */
122 CurLineInfo = xmalloc (AllocatedSlots * sizeof (LineInfoSlot));
124 /* Initalize the predefined slots. Be sure to ccreate a new LineInfo for
125 * the default source. This is necessary to allow error message to be
126 * generated without any input file open.
129 CurLineInfo[LI_SLOT_ASM].Type = LI_TYPE_ASM; /* Count = 0 */
130 CurLineInfo[LI_SLOT_ASM].Info = NewLineInfo (LI_TYPE_ASM, &DefaultPos);
131 CurLineInfo[LI_SLOT_EXT].Type = LI_TYPE_EXT; /* Count = 0 */
132 CurLineInfo[LI_SLOT_EXT].Info = 0;
137 int AllocLineInfoSlot (unsigned Type, unsigned Count)
138 /* Allocate a line info slot of the given type and return the slot index */
140 /* Grow the array if necessary */
141 if (UsedSlots >= AllocatedSlots) {
142 LineInfoSlot* NewLineInfo;
144 NewLineInfo = xmalloc (AllocatedSlots * sizeof (LineInfoSlot));
145 memcpy (NewLineInfo, CurLineInfo, UsedSlots * sizeof (LineInfoSlot));
147 CurLineInfo = NewLineInfo;
150 /* Array is now big enough, add the new data */
151 CurLineInfo[UsedSlots].Type = LI_MAKE_TYPE(Type, Count);
152 CurLineInfo[UsedSlots].Info = 0;
154 /* Increment the count and return the index of the new slot */
155 return (int) UsedSlots++;
160 void FreeLineInfoSlot (int Slot)
161 /* Free the line info in the given slot. Note: Alloc/Free must be used in
165 /* Check the parameter */
166 PRECONDITION (Slot == (int) UsedSlots - 1);
168 /* Free the last entry */
169 CurLineInfo[Slot].Info = 0;
175 void GenLineInfo (int Slot, const FilePos* Pos)
176 /* Generate a new line info in the given slot */
178 /* Get a pointer to the slot */
179 LineInfoSlot* S = CurLineInfo + Slot;
181 /* Generate new data only if it is different from the existing. */
182 if (S->Info && CompareFilePos (&S->Info->Pos, Pos) == 0) {
187 /* Allocate new data */
188 S->Info = NewLineInfo (S->Type, Pos);
193 void ClearLineInfo (int Slot)
194 /* Clear the line info in the given slot */
196 /* Zero the pointer */
197 CurLineInfo[Slot].Info = 0;
202 void GetFullLineInfo (Collection* LineInfos, unsigned IncUsage)
203 /* Return full line infos, that is line infos for all slots in LineInfos. The
204 * function will clear LineInfos before usage and will increment the usage
205 * counter by IncUsage for all line infos returned.
210 /* Clear the collection */
211 CollDeleteAll (LineInfos);
213 /* Copy all valid line infos to the collection */
214 for (I = 0; I < UsedSlots; ++I) {
216 /* Get the line info from the slot */
217 LineInfo* LI = CurLineInfo[I].Info;
219 /* Ignore empty slots */
221 LI->Usage += IncUsage;
222 CollAppend (LineInfos, LI);
229 LineInfo* UseLineInfo (LineInfo* LI)
230 /* Increase the reference count of the given line info and return it. The
231 * function will gracefully accept NULL pointers and do nothing in this case.
242 LineInfo* ReleaseLineInfo (LineInfo* LI)
243 /* Decrease the reference count of the given line info and return it. The
244 * function will gracefully accept NULL pointers and do nothing in this case.
248 /* Cannot decrease below zero */
249 CHECK (LI->Usage != 0);
257 static int CmpLineInfo (void* Data attribute ((unused)),
258 const void* LI1_, const void* LI2_)
259 /* Compare function for the sort */
261 /* Cast the pointers */
262 const LineInfo* LI1 = LI1_;
263 const LineInfo* LI2 = LI2_;
265 /* Unreferenced line infos are always larger, otherwise sort by file,
266 * then by line, then by column.
268 if ((LI1->Usage == 0) == (LI2->Usage == 0)) {
269 /* Both are either referenced or unreferenced */
270 return CompareFilePos (&LI1->Pos, &LI2->Pos);
272 if (LI1->Usage > 0) {
282 void WriteLineInfo (const Collection* LineInfos)
283 /* Write a list of line infos to the object file. MakeLineInfoIndex has to
289 /* Write the count */
290 ObjWriteVar (CollCount (LineInfos));
292 /* Write the line info indices */
293 for (I = 0; I < CollCount (LineInfos); ++I) {
295 /* Get a pointer to the line info */
296 const LineInfo* LI = CollConstAt (LineInfos, I);
298 /* Check the index */
299 CHECK (LI->Index != INV_LINEINFO_INDEX);
301 /* Write the index to the file */
302 ObjWriteVar (LI->Index);
308 void MakeLineInfoIndex (void)
309 /* Index the line infos */
313 /* Sort the line info list */
314 CollSort (&LineInfoColl, CmpLineInfo, 0);
316 /* Walk over the list, index the line infos and count the used ones */
317 UsedLineInfoCount = 0;
318 for (I = 0; I < CollCount (&LineInfoColl); ++I) {
319 /* Get a pointer to this line info */
320 LineInfo* LI = CollAtUnchecked (&LineInfoColl, I);
322 /* If it is invalid, terminate the loop. All unused line infos were
323 * placed at the end of the collection by the sort.
325 if (LI->Usage == 0) {
329 /* Index and count this one */
337 void WriteLineInfos (void)
338 /* Write a list of all line infos to the object file. */
342 /* Tell the object file module that we're about to write line infos */
343 ObjStartLineInfos ();
345 /* Write the line info count to the list */
346 ObjWriteVar (UsedLineInfoCount);
348 /* Walk over the list and write all line infos */
349 for (I = 0; I < UsedLineInfoCount; ++I) {
350 /* Get a pointer to this line info */
351 LineInfo* LI = CollAt (&LineInfoColl, I);
353 /* Write the type and count of the line info */
354 ObjWriteVar (LI->Type);
356 /* Write the source file position */
357 ObjWritePos (&LI->Pos);
360 /* End of line infos */