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