1/*****************************************************************************/
2/* */
3/* lineinfo.h */
4/* */
5/* Source file line info structure */
6/* */
7/* */
8/* */
9/* (C) 2001-2012, Ullrich von Bassewitz */
10/* Roemerstrasse 52 */
11/* D-70794 Filderstadt */
12/* EMail: uz@cc65.org */
13/* */
14/* */
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. */
18/* */
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: */
22/* */
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 */
30/* distribution. */
31/* */
32/*****************************************************************************/
33
34
35
36/* common */
37#include "check.h"
38#include "lidefs.h"
39#include "xmalloc.h"
40
41/* ld65 */
42#include "error.h"
43#include "fileinfo.h"
44#include "fileio.h"
45#include "lineinfo.h"
46#include "objdata.h"
47#include "segments.h"
48
49
50
51/*****************************************************************************/
52/* Code */
53/*****************************************************************************/
54
55
56
57static LineInfo* NewLineInfo (void)
58/* Create and return a new LineInfo struct with mostly empty fields */
59{
60 /* Allocate memory */
61 LineInfo* LI = xmalloc (sizeof (LineInfo));
62
63 /* Initialize the fields */
64 LI->Id = ~0U;
65 LI->File = 0;
66 LI->Type = LI_MAKE_TYPE (LI_TYPE_ASM, 0);
67 LI->Pos.Name = INVALID_STRING_ID;
68 LI->Pos.Line = 0;
69 LI->Pos.Col = 0;
70 LI->Spans = 0;
71
72 /* Return the new struct */
73 return LI;
74}
75
76
77
78void FreeLineInfo (LineInfo* LI)
79/* Free a LineInfo structure. */
80{
81 /* Free the span list */
82 xfree (LI->Spans);
83
84 /* Free the structure itself */
85 xfree (LI);
86}
87
88
89
90LineInfo* DupLineInfo (const LineInfo* LI)
91/* Creates a duplicate of a line info structure */
92{
93 /* Allocate memory */
94 LineInfo* New = xmalloc (sizeof (LineInfo));
95
96 /* Copy the fields (leave id invalid) */
97 New->Id = LI->Id;
98 New->File = LI->File;
99 New->Type = LI->Type;
100 New->Pos = LI->Pos;
101 New->Spans = DupSpanList (LI->Spans);
102
103 /* Return the copy */
104 return New;
105}
106
107
108
109LineInfo* GenLineInfo (const FilePos* Pos)
110/* Generate a new (internally used) line info with the given information */
111{
112 /* Create a new LineInfo struct */
113 LineInfo* LI = NewLineInfo ();
114
115 /* Initialize the fields in the new LineInfo */
116 LI->Pos = *Pos;
117
118 /* Return the struct read */
119 return LI;
120}
121
122
123
124LineInfo* ReadLineInfo (FILE* F, ObjData* O)
125/* Read a line info from a file and return it */
126{
127 /* Create a new LineInfo struct */
128 LineInfo* LI = NewLineInfo ();
129
130 /* Read/fill the fields in the new LineInfo */
131 LI->Pos.Line = ReadVar (F);
132 LI->Pos.Col = ReadVar (F);
133 LI->File = CollAt (&O->Files, ReadVar (F));
134 LI->Pos.Name = LI->File->Name;
135 LI->Type = ReadVar (F);
136 LI->Spans = ReadSpanList (F);
137
138 /* Return the struct read */
139 return LI;
140}
141
142
143
144void ReadLineInfoList (FILE* F, ObjData* O, Collection* LineInfos)
145/* Read a list of line infos stored as a list of indices in the object file,
146** make real line infos from them and place them into the passed collection.
147*/
148{
149 /* Read the number of line info indices that follow */
150 unsigned LineInfoCount = ReadVar (F);
151
152 /* Grow the collection as needed */
153 CollGrow (LineInfos, LineInfoCount);
154
155 /* Read the line infos and resolve them */
156 while (LineInfoCount--) {
157
158 /* Read an index */
159 unsigned LineInfoIndex = ReadVar (F);
160
161 /* The line info index was written by the assembler and must
162 ** therefore be part of the line infos read from the object file.
163 */
164 if (LineInfoIndex >= CollCount (&O->LineInfos)) {
165 Internal ("Invalid line info index %u in module '%s' - max is %u",
166 LineInfoIndex,
167 GetObjFileName (O),
168 CollCount (&O->LineInfos));
169 }
170
171 /* Add the line info to the collection */
172 CollAppend (LineInfos, CollAt (&O->LineInfos, LineInfoIndex));
173 }
174}
175
176
177
178const LineInfo* GetAsmLineInfo (const Collection* LineInfos)
179/* Find a line info of type LI_TYPE_ASM and count zero in the given collection
180** and return it. Return NULL if no such line info was found.
181*/
182{
183 unsigned I;
184
185 /* Search for a line info of LI_TYPE_ASM */
186 for (I = 0; I < CollCount (LineInfos); ++I) {
187 const LineInfo* LI = CollConstAt (LineInfos, I);
188 if (LI->Type == LI_MAKE_TYPE (LI_TYPE_ASM, 0)) {
189 return LI;
190 }
191 }
192
193 /* Not found */
194 return 0;
195}
196
197
198
199unsigned LineInfoCount (void)
200/* Return the total number of line infos */
201{
202 /* Walk over all object files */
203 unsigned I;
204 unsigned Count = 0;
205 for (I = 0; I < CollCount (&ObjDataList); ++I) {
206
207 /* Get this object file */
208 const ObjData* O = CollAtUnchecked (&ObjDataList, I);
209
210 /* Count spans */
211 Count += CollCount (&O->LineInfos);
212 }
213
214 return Count;
215}
216
217
218
219void AssignLineInfoIds (void)
220/* Assign the ids to the line infos */
221{
222 unsigned I, J;
223
224 /* Walk over all line infos */
225 unsigned Id = 0;
226 for (I = 0; I < CollCount (&ObjDataList); ++I) {
227
228 /* Get the object file */
229 ObjData* O = CollAtUnchecked (&ObjDataList, I);
230
231 /* Output the line infos */
232 for (J = 0; J < CollCount (&O->LineInfos); ++J) {
233
234 /* Get this line info */
235 LineInfo* LI = CollAtUnchecked (&O->LineInfos, J);
236
237 /* Assign the id */
238 LI->Id = Id++;
239 }
240 }
241}
242
243
244
245void PrintDbgLineInfo (FILE* F)
246/* Output the line infos to a debug info file */
247{
248 unsigned I, J;
249
250 /* Print line infos from all modules we have linked into the output file */
251 for (I = 0; I < CollCount (&ObjDataList); ++I) {
252
253 /* Get the object file */
254 const ObjData* O = CollAtUnchecked (&ObjDataList, I);
255
256 /* Output the line infos */
257 for (J = 0; J < CollCount (&O->LineInfos); ++J) {
258
259 /* Get this line info */
260 const LineInfo* LI = CollConstAt (&O->LineInfos, J);
261
262 /* Get the line info type and count */
263 unsigned Type = LI_GET_TYPE (LI->Type);
264 unsigned Count = LI_GET_COUNT (LI->Type);
265
266 /* Print the start of the line */
267 fprintf (F,
268 "line\tid=%u,file=%u,line=%u",
269 LI->Id, LI->File->Id, GetSourceLine (LI));
270
271 /* Print type if not LI_TYPE_ASM and count if not zero */
272 if (Type != LI_TYPE_ASM) {
273 fprintf (F, ",type=%u", Type);
274 }
275 if (Count != 0) {
276 fprintf (F, ",count=%u", Count);
277 }
278
279 /* Add spans if the line info has it */
280 PrintDbgSpanList (F, O, LI->Spans);
281
282 /* Terminate line */
283 fputc ('\n', F);
284 }
285 }
286}
287