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