]> git.sur5r.net Git - cc65/blob - src/ca65/objfile.c
Added condes tables to c64 config
[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-2000 Ullrich von Bassewitz                                       */
10 /*               Wacholderweg 14                                             */
11 /*               D-70597 Stuttgart                                           */
12 /* EMail:        uz@musoftware.de                                            */
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 }
117
118
119
120 /*****************************************************************************/
121 /*                                   Code                                    */
122 /*****************************************************************************/
123
124
125
126 void ObjOpen (void)
127 /* Open the object file for writing, write a dummy header */
128 {
129     /* Do we have a name for the output file? */
130     if (OutFile == 0) {
131         /* We don't have an output name explicitly given, construct one from
132          * the name of the input file.
133          */
134         OutFile = MakeFilename (InFile, OBJ_EXT);
135     }
136
137     /* Create the output file */
138     F = fopen (OutFile, "w+b");
139     if (F == 0) {
140         Fatal (FAT_CANNOT_OPEN_OUTPUT, OutFile, strerror (errno));
141     }
142
143     /* Write a dummy header */
144     ObjWriteHeader ();
145 }
146
147
148
149 void ObjClose (void)
150 /* Write an update header and close the object file. */
151 {
152     /* Go back to the beginning */
153     if (fseek (F, 0, SEEK_SET) != 0) {
154         ObjWriteError ();
155     }
156
157     /* If we have debug infos, set the flag in the header */
158     if (DbgSyms) {
159         Header.Flags |= OBJ_FLAGS_DBGINFO;
160     }
161
162     /* Write the updated header */
163     ObjWriteHeader ();
164
165     /* Close the file */
166     if (fclose (F) != 0) {
167         ObjWriteError ();
168     }
169 }
170
171
172
173 void ObjWrite8 (unsigned V)
174 /* Write an 8 bit value to the file */
175 {
176     if (putc (V, F) == EOF) {
177         ObjWriteError ();
178     }
179 }
180
181
182
183 void ObjWrite16 (unsigned V)
184 /* Write a 16 bit value to the file */
185 {
186     ObjWrite8 (V);
187     ObjWrite8 (V >> 8);
188 }
189
190
191
192 void ObjWrite24 (unsigned long V)
193 /* Write a 24 bit value to the file */
194 {
195     ObjWrite8 (V);
196     ObjWrite8 (V >> 8);
197     ObjWrite8 (V >> 16);
198 }
199
200
201
202 void ObjWrite32 (unsigned long V)
203 /* Write a 32 bit value to the file */
204 {
205     ObjWrite8 (V);
206     ObjWrite8 (V >> 8);
207     ObjWrite8 (V >> 16);
208     ObjWrite8 (V >> 24);
209 }
210
211
212
213 void ObjWriteVar (unsigned long V)
214 /* Write a variable sized value to the file in special encoding */
215 {
216     /* We will write the value to the file in 7 bit chunks. If the 8th bit
217      * is clear, we're done, if it is set, another chunk follows. This will
218      * allow us to encode smaller values with less bytes, at the expense of
219      * needing 5 bytes if a 32 bit value is written to file.
220      */
221     do {
222         unsigned char C = (V & 0x7F);
223         V >>= 7;
224         if (V) {
225             C |= 0x80;
226         }
227         ObjWrite8 (C);
228     } while (V != 0);
229 }
230
231
232
233 void ObjWriteStr (const char* S)
234 /* Write a string to the object file */
235 {
236     unsigned Len = strlen (S);
237
238     /* Write the string with the length preceeded (this is easier for
239      * the reading routine than the C format since the length is known in
240      * advance).
241      */
242     ObjWriteVar (Len);
243     ObjWriteData (S, Len);
244 }
245
246
247
248 void ObjWriteData (const void* Data, unsigned Size)
249 /* Write literal data to the file */
250 {
251     if (fwrite (Data, 1, Size, F) != Size) {
252         ObjWriteError ();
253     }
254 }
255
256
257
258 void ObjWritePos (const FilePos* Pos)
259 /* Write a file position to the object file */
260 {
261     /* Write the data entries */
262     ObjWriteVar (Pos->Line);
263     ObjWriteVar (Pos->Col);
264     if (Pos->Name == 0) {
265         /* Position is outside file scope, use the main file instead */
266         ObjWriteVar (0);
267     } else {
268         ObjWriteVar (Pos->Name - 1);
269     }              
270 }
271
272
273
274 void ObjStartOptions (void)
275 /* Mark the start of the option section */
276 {
277     Header.OptionOffs = ftell (F);
278 }
279
280
281
282 void ObjEndOptions (void)
283 /* Mark the end of the option section */
284 {
285     Header.OptionSize = ftell (F) - Header.OptionOffs;
286 }
287
288
289
290 void ObjStartFiles (void)
291 /* Mark the start of the files section */
292 {
293     Header.FileOffs = ftell (F);
294 }
295
296
297
298 void ObjEndFiles (void)
299 /* Mark the end of the files section */
300 {
301     Header.FileSize = ftell (F) - Header.FileOffs;
302 }
303
304
305
306 void ObjStartSegments (void)
307 /* Mark the start of the segment section */
308 {
309     Header.SegOffs = ftell (F);
310 }
311
312
313
314 void ObjEndSegments (void)
315 /* Mark the end of the segment section */
316 {
317     Header.SegSize = ftell (F) - Header.SegOffs;
318 }
319
320
321
322 void ObjStartImports (void)
323 /* Mark the start of the import section */
324 {
325     Header.ImportOffs = ftell (F);
326 }
327
328
329
330 void ObjEndImports (void)
331 /* Mark the end of the import section */
332 {
333     Header.ImportSize = ftell (F) - Header.ImportOffs;
334 }
335
336
337
338 void ObjStartExports (void)
339 /* Mark the start of the export section */
340 {
341     Header.ExportOffs = ftell (F);
342 }
343
344
345
346 void ObjEndExports (void)
347 /* Mark the end of the export section */
348 {
349     Header.ExportSize = ftell (F) - Header.ExportOffs;
350 }
351
352
353
354 void ObjStartDbgSyms (void)
355 /* Mark the start of the debug symbol section */
356 {
357     Header.DbgSymOffs = ftell (F);
358 }
359
360
361
362 void ObjEndDbgSyms (void)
363 /* Mark the end of the debug symbol section */
364 {
365     Header.DbgSymSize = ftell (F) - Header.DbgSymOffs;
366 }
367
368
369