]> git.sur5r.net Git - cc65/blob - src/ca65/objfile.c
Replace error/warning numbers by strings.
[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-2003 Ullrich von Bassewitz                                       */
10 /*               Römerstraße 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 #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,          /* 32: Magic number */
67     OBJ_VERSION,        /* 16: Version number */
68     0,                  /* 16: flags */
69     0,                  /* 32: Offset to option table */
70     0,                  /* 32: Size of options */
71     0,                  /* 32: Offset to file table */
72     0,                  /* 32: Size of files */
73     0,                  /* 32: Offset to segment table */
74     0,                  /* 32: Size of segment table */
75     0,                  /* 32: Offset to import list */
76     0,                  /* 32: Size of import list */
77     0,                  /* 32: Offset to export list */
78     0,                  /* 32: Size of export list */
79     0,                  /* 32: Offset to list of debug symbols */
80     0,                  /* 32: Size of debug symbols */
81     0,                  /* 32: Offset to list of line infos */
82     0,                  /* 32: Size of line infos */
83     0,                  /* 32: Offset to string pool */
84     0,                  /* 32: Size of string pool */
85     0,                  /* 32: Offset to assertion table */
86     0                   /* 32: Size of assertion table */
87 };
88
89
90
91 /*****************************************************************************/
92 /*                         Internally used functions                         */
93 /*****************************************************************************/
94
95
96
97 static void ObjWriteError (void)
98 /* Called on a write error. Will try to close and remove the file, then
99  * print a fatal error.
100  */
101 {
102     /* Remember the error */
103     int Error = errno;
104
105     /* Force a close of the file, ignoring errors */
106     fclose (F);
107
108     /* Try to remove the file, also ignoring errors */
109     remove (OutFile);
110
111     /* Now abort with a fatal error */
112     Fatal ("Cannot write to output file `%s': %s", OutFile, strerror (Error));
113 }
114
115
116
117 static void ObjWriteHeader (void)
118 /* Write the object file header to the current file position */
119 {
120     ObjWrite32 (Header.Magic);
121     ObjWrite16 (Header.Version);
122     ObjWrite16 (Header.Flags);
123     ObjWrite32 (Header.OptionOffs);
124     ObjWrite32 (Header.OptionSize);
125     ObjWrite32 (Header.FileOffs);
126     ObjWrite32 (Header.FileSize);
127     ObjWrite32 (Header.SegOffs);
128     ObjWrite32 (Header.SegSize);
129     ObjWrite32 (Header.ImportOffs);
130     ObjWrite32 (Header.ImportSize);
131     ObjWrite32 (Header.ExportOffs);
132     ObjWrite32 (Header.ExportSize);
133     ObjWrite32 (Header.DbgSymOffs);
134     ObjWrite32 (Header.DbgSymSize);
135     ObjWrite32 (Header.LineInfoOffs);
136     ObjWrite32 (Header.LineInfoSize);
137     ObjWrite32 (Header.StrPoolOffs);
138     ObjWrite32 (Header.StrPoolSize);
139     ObjWrite32 (Header.AssertOffs);
140     ObjWrite32 (Header.AssertSize);
141 }
142
143
144
145 /*****************************************************************************/
146 /*                                   Code                                    */
147 /*****************************************************************************/
148
149
150
151 void ObjOpen (void)
152 /* Open the object file for writing, write a dummy header */
153 {
154     /* Do we have a name for the output file? */
155     if (OutFile == 0) {
156         /* We don't have an output name explicitly given, construct one from
157          * the name of the input file.
158          */
159         OutFile = MakeFilename (InFile, OBJ_EXT);
160     }
161
162     /* Create the output file */
163     F = fopen (OutFile, "w+b");
164     if (F == 0) {
165         Fatal ("Cannot open output file `%s': %s", OutFile, strerror (errno));
166     }
167
168     /* Write a dummy header */
169     ObjWriteHeader ();
170 }
171
172
173
174 void ObjClose (void)
175 /* Write an update header and close the object file. */
176 {
177     /* Go back to the beginning */
178     if (fseek (F, 0, SEEK_SET) != 0) {
179         ObjWriteError ();
180     }
181
182     /* If we have debug infos, set the flag in the header */
183     if (DbgSyms) {
184         Header.Flags |= OBJ_FLAGS_DBGINFO;
185     }
186
187     /* Write the updated header */
188     ObjWriteHeader ();
189
190     /* Close the file */
191     if (fclose (F) != 0) {
192         ObjWriteError ();
193     }
194 }
195
196
197
198 unsigned long ObjGetFilePos (void)
199 /* Get the current file position */
200 {
201     long Pos = ftell (F);
202     if (Pos < 0) {
203         ObjWriteError ();
204     }
205     return Pos;
206 }
207
208
209
210 void ObjSetFilePos (unsigned long Pos)
211 /* Set the file position */
212 {
213     if (fseek (F, Pos, SEEK_SET) != 0) {
214         ObjWriteError ();
215     }
216 }
217
218
219
220 void ObjWrite8 (unsigned V)
221 /* Write an 8 bit value to the file */
222 {
223     if (putc (V, F) == EOF) {
224         ObjWriteError ();
225     }
226 }
227
228
229
230 void ObjWrite16 (unsigned V)
231 /* Write a 16 bit value to the file */
232 {
233     ObjWrite8 (V);
234     ObjWrite8 (V >> 8);
235 }
236
237
238
239 void ObjWrite24 (unsigned long V)
240 /* Write a 24 bit value to the file */
241 {
242     ObjWrite8 (V);
243     ObjWrite8 (V >> 8);
244     ObjWrite8 (V >> 16);
245 }
246
247
248
249 void ObjWrite32 (unsigned long V)
250 /* Write a 32 bit value to the file */
251 {
252     ObjWrite8 (V);
253     ObjWrite8 (V >> 8);
254     ObjWrite8 (V >> 16);
255     ObjWrite8 (V >> 24);
256 }
257
258
259
260 void ObjWriteVar (unsigned long V)
261 /* Write a variable sized value to the file in special encoding */
262 {
263     /* We will write the value to the file in 7 bit chunks. If the 8th bit
264      * is clear, we're done, if it is set, another chunk follows. This will
265      * allow us to encode smaller values with less bytes, at the expense of
266      * needing 5 bytes if a 32 bit value is written to file.
267      */
268     do {
269         unsigned char C = (V & 0x7F);
270         V >>= 7;
271         if (V) {
272             C |= 0x80;
273         }
274         ObjWrite8 (C);
275     } while (V != 0);
276 }
277
278
279
280 void ObjWriteStr (const char* S)
281 /* Write a string to the object file */
282 {
283     unsigned Len = strlen (S);
284
285     /* Write the string with the length preceeded (this is easier for
286      * the reading routine than the C format since the length is known in
287      * advance).
288      */
289     ObjWriteVar (Len);
290     ObjWriteData (S, Len);
291 }
292
293
294
295 void ObjWriteData (const void* Data, unsigned Size)
296 /* Write literal data to the file */
297 {
298     if (fwrite (Data, 1, Size, F) != Size) {
299         ObjWriteError ();
300     }
301 }
302
303
304
305 void ObjWritePos (const FilePos* Pos)
306 /* Write a file position to the object file */
307 {
308     /* Write the data entries */
309     ObjWriteVar (Pos->Line);
310     ObjWriteVar (Pos->Col);
311     if (Pos->Name == 0) {
312         /* Position is outside file scope, use the main file instead */
313         ObjWriteVar (0);
314     } else {
315         ObjWriteVar (Pos->Name - 1);
316     }
317 }
318
319
320
321 void ObjStartOptions (void)
322 /* Mark the start of the option section */
323 {
324     Header.OptionOffs = ftell (F);
325 }
326
327
328
329 void ObjEndOptions (void)
330 /* Mark the end of the option section */
331 {
332     Header.OptionSize = ftell (F) - Header.OptionOffs;
333 }
334
335
336
337 void ObjStartFiles (void)
338 /* Mark the start of the files section */
339 {
340     Header.FileOffs = ftell (F);
341 }
342
343
344
345 void ObjEndFiles (void)
346 /* Mark the end of the files section */
347 {
348     Header.FileSize = ftell (F) - Header.FileOffs;
349 }
350
351
352
353 void ObjStartSegments (void)
354 /* Mark the start of the segment section */
355 {
356     Header.SegOffs = ftell (F);
357 }
358
359
360
361 void ObjEndSegments (void)
362 /* Mark the end of the segment section */
363 {
364     Header.SegSize = ftell (F) - Header.SegOffs;
365 }
366
367
368
369 void ObjStartImports (void)
370 /* Mark the start of the import section */
371 {
372     Header.ImportOffs = ftell (F);
373 }
374
375
376
377 void ObjEndImports (void)
378 /* Mark the end of the import section */
379 {
380     Header.ImportSize = ftell (F) - Header.ImportOffs;
381 }
382
383
384
385 void ObjStartExports (void)
386 /* Mark the start of the export section */
387 {
388     Header.ExportOffs = ftell (F);
389 }
390
391
392
393 void ObjEndExports (void)
394 /* Mark the end of the export section */
395 {
396     Header.ExportSize = ftell (F) - Header.ExportOffs;
397 }
398
399
400
401 void ObjStartDbgSyms (void)
402 /* Mark the start of the debug symbol section */
403 {
404     Header.DbgSymOffs = ftell (F);
405 }
406
407
408
409 void ObjEndDbgSyms (void)
410 /* Mark the end of the debug symbol section */
411 {
412     Header.DbgSymSize = ftell (F) - Header.DbgSymOffs;
413 }
414
415
416
417 void ObjStartLineInfos (void)
418 /* Mark the start of the line info section */
419 {
420     Header.LineInfoOffs = ftell (F);
421 }
422
423
424
425 void ObjEndLineInfos (void)
426 /* Mark the end of the line info section */
427 {
428     Header.LineInfoSize = ftell (F) - Header.LineInfoOffs;
429 }
430
431
432
433 void ObjStartStrPool (void)
434 /* Mark the start of the string pool section */
435 {
436     Header.StrPoolOffs = ftell (F);
437 }
438
439
440
441 void ObjEndStrPool (void)
442 /* Mark the end of the string pool section */
443 {
444     Header.StrPoolSize = ftell (F) - Header.StrPoolOffs;
445 }
446
447
448
449 void ObjStartAssertions (void)
450 /* Mark the start of the assertion table */
451 {
452     Header.AssertOffs = ftell (F);
453 }
454
455
456
457 void ObjEndAssertions (void)
458 /* Mark the end of the assertion table */
459 {
460     Header.AssertSize = ftell (F) - Header.AssertOffs;
461 }
462
463
464