]> git.sur5r.net Git - cc65/blob - src/ca65/objfile.c
Added line infos
[cc65] / src / ca65 / objfile.c
1 /*****************************************************************************/
2 /*                                                                           */
3 /*                                 objfile.c                                 */
4 /*                                                                           */
5 /*         Object file writing routines for the ca65 macroassembler          */
6 /*                                                                           */
7 /*                                                                           */
8 /*                                                                           */
9 /* (C) 1998-2001 Ullrich von Bassewitz                                       */
10 /*               Wacholderweg 14                                             */
11 /*               D-70597 Stuttgart                                           */
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 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <errno.h>
40
41 /* common */
42 #include "fname.h"
43 #include "objdefs.h"
44
45 /* ca65 */
46 #include "global.h"
47 #include "error.h"
48 #include "objfile.h"
49
50
51
52 /*****************************************************************************/
53 /*                                   Data                                    */
54 /*****************************************************************************/
55
56
57
58 /* File descriptor */
59 static FILE* F = 0;
60
61 /* Default extension */
62 #define OBJ_EXT ".o"
63
64 /* Header structure */
65 static ObjHeader Header = {
66     OBJ_MAGIC,
67     OBJ_VERSION
68 };
69
70
71
72 /*****************************************************************************/
73 /*                         Internally used functions                         */
74 /*****************************************************************************/
75
76
77
78 static void ObjWriteError (void)
79 /* Called on a write error. Will try to close and remove the file, then
80  * print a fatal error.
81  */
82 {
83     /* Remember the error */
84     int Error = errno;
85
86     /* Force a close of the file, ignoring errors */
87     fclose (F);
88
89     /* Try to remove the file, also ignoring errors */
90     remove (OutFile);
91
92     /* Now abort with a fatal error */
93     Fatal (FAT_CANNOT_WRITE_OUTPUT, OutFile, strerror (Error));
94 }
95
96
97
98 static void ObjWriteHeader (void)
99 /* Write the object file header to the current file position */
100 {
101     ObjWrite32 (Header.Magic);
102     ObjWrite16 (Header.Version);
103     ObjWrite16 (Header.Flags);
104     ObjWrite32 (Header.OptionOffs);
105     ObjWrite32 (Header.OptionSize);
106     ObjWrite32 (Header.FileOffs);
107     ObjWrite32 (Header.FileSize);
108     ObjWrite32 (Header.SegOffs);
109     ObjWrite32 (Header.SegSize);
110     ObjWrite32 (Header.ImportOffs);
111     ObjWrite32 (Header.ImportSize);
112     ObjWrite32 (Header.ExportOffs);
113     ObjWrite32 (Header.ExportSize);
114     ObjWrite32 (Header.DbgSymOffs);
115     ObjWrite32 (Header.DbgSymSize);
116     ObjWrite32 (Header.LineInfoOffs);
117     ObjWrite32 (Header.LineInfoSize);
118 }
119
120
121
122 /*****************************************************************************/
123 /*                                   Code                                    */
124 /*****************************************************************************/
125
126
127
128 void ObjOpen (void)
129 /* Open the object file for writing, write a dummy header */
130 {
131     /* Do we have a name for the output file? */
132     if (OutFile == 0) {
133         /* We don't have an output name explicitly given, construct one from
134          * the name of the input file.
135          */
136         OutFile = MakeFilename (InFile, OBJ_EXT);
137     }
138
139     /* Create the output file */
140     F = fopen (OutFile, "w+b");
141     if (F == 0) {
142         Fatal (FAT_CANNOT_OPEN_OUTPUT, OutFile, strerror (errno));
143     }
144
145     /* Write a dummy header */
146     ObjWriteHeader ();
147 }
148
149
150
151 void ObjClose (void)
152 /* Write an update header and close the object file. */
153 {
154     /* Go back to the beginning */
155     if (fseek (F, 0, SEEK_SET) != 0) {
156         ObjWriteError ();
157     }
158
159     /* If we have debug infos, set the flag in the header */
160     if (DbgSyms) {
161         Header.Flags |= OBJ_FLAGS_DBGINFO;
162     }
163
164     /* Write the updated header */
165     ObjWriteHeader ();
166
167     /* Close the file */
168     if (fclose (F) != 0) {
169         ObjWriteError ();
170     }
171 }
172
173
174
175 void ObjWrite8 (unsigned V)
176 /* Write an 8 bit value to the file */
177 {
178     if (putc (V, F) == EOF) {
179         ObjWriteError ();
180     }
181 }
182
183
184
185 void ObjWrite16 (unsigned V)
186 /* Write a 16 bit value to the file */
187 {
188     ObjWrite8 (V);
189     ObjWrite8 (V >> 8);
190 }
191
192
193
194 void ObjWrite24 (unsigned long V)
195 /* Write a 24 bit value to the file */
196 {
197     ObjWrite8 (V);
198     ObjWrite8 (V >> 8);
199     ObjWrite8 (V >> 16);
200 }
201
202
203
204 void ObjWrite32 (unsigned long V)
205 /* Write a 32 bit value to the file */
206 {
207     ObjWrite8 (V);
208     ObjWrite8 (V >> 8);
209     ObjWrite8 (V >> 16);
210     ObjWrite8 (V >> 24);
211 }
212
213
214
215 void ObjWriteVar (unsigned long V)
216 /* Write a variable sized value to the file in special encoding */
217 {
218     /* We will write the value to the file in 7 bit chunks. If the 8th bit
219      * is clear, we're done, if it is set, another chunk follows. This will
220      * allow us to encode smaller values with less bytes, at the expense of
221      * needing 5 bytes if a 32 bit value is written to file.
222      */
223     do {
224         unsigned char C = (V & 0x7F);
225         V >>= 7;
226         if (V) {
227             C |= 0x80;
228         }
229         ObjWrite8 (C);
230     } while (V != 0);
231 }
232
233
234
235 void ObjWriteStr (const char* S)
236 /* Write a string to the object file */
237 {
238     unsigned Len = strlen (S);
239
240     /* Write the string with the length preceeded (this is easier for
241      * the reading routine than the C format since the length is known in
242      * advance).
243      */
244     ObjWriteVar (Len);
245     ObjWriteData (S, Len);
246 }                              
247
248
249
250 void ObjWriteData (const void* Data, unsigned Size)
251 /* Write literal data to the file */
252 {
253     if (fwrite (Data, 1, Size, F) != Size) {
254         ObjWriteError ();
255     }
256 }
257
258
259
260 void ObjWritePos (const FilePos* Pos)
261 /* Write a file position to the object file */
262 {
263     /* Write the data entries */
264     ObjWriteVar (Pos->Line);
265     ObjWriteVar (Pos->Col);
266     if (Pos->Name == 0) {
267         /* Position is outside file scope, use the main file instead */
268         ObjWriteVar (0);
269     } else {
270         ObjWriteVar (Pos->Name - 1);
271     }
272 }
273
274
275
276 void ObjStartOptions (void)
277 /* Mark the start of the option section */
278 {
279     Header.OptionOffs = ftell (F);
280 }
281
282
283
284 void ObjEndOptions (void)
285 /* Mark the end of the option section */
286 {
287     Header.OptionSize = ftell (F) - Header.OptionOffs;
288 }
289
290
291
292 void ObjStartFiles (void)
293 /* Mark the start of the files section */
294 {
295     Header.FileOffs = ftell (F);
296 }
297
298
299
300 void ObjEndFiles (void)
301 /* Mark the end of the files section */
302 {
303     Header.FileSize = ftell (F) - Header.FileOffs;
304 }
305
306
307
308 void ObjStartSegments (void)
309 /* Mark the start of the segment section */
310 {
311     Header.SegOffs = ftell (F);
312 }
313
314
315
316 void ObjEndSegments (void)
317 /* Mark the end of the segment section */
318 {
319     Header.SegSize = ftell (F) - Header.SegOffs;
320 }
321
322
323
324 void ObjStartImports (void)
325 /* Mark the start of the import section */
326 {
327     Header.ImportOffs = ftell (F);
328 }
329
330
331
332 void ObjEndImports (void)
333 /* Mark the end of the import section */
334 {
335     Header.ImportSize = ftell (F) - Header.ImportOffs;
336 }
337
338
339
340 void ObjStartExports (void)
341 /* Mark the start of the export section */
342 {
343     Header.ExportOffs = ftell (F);
344 }
345
346
347
348 void ObjEndExports (void)
349 /* Mark the end of the export section */
350 {
351     Header.ExportSize = ftell (F) - Header.ExportOffs;
352 }
353
354
355
356 void ObjStartDbgSyms (void)
357 /* Mark the start of the debug symbol section */
358 {
359     Header.DbgSymOffs = ftell (F);
360 }
361
362
363
364 void ObjEndDbgSyms (void)
365 /* Mark the end of the debug symbol section */
366 {
367     Header.DbgSymSize = ftell (F) - Header.DbgSymOffs;
368 }
369
370
371
372 void ObjStartLineInfos (void)
373 /* Mark the start of the line info section */
374 {
375     Header.LineInfoOffs = ftell (F);
376 }
377
378
379
380 void ObjEndLineInfos (void)
381 /* Mark the end of the line info section */
382 {
383     Header.LineInfoSize = ftell (F) - Header.LineInfoOffs;
384 }
385
386
387