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