]> git.sur5r.net Git - cc65/blob - src/da65/output.c
git-svn-id: svn://svn.cc65.org/cc65/trunk@3863 b7a2c559-68d2-44c3-8de9-860c34a00d81
[cc65] / src / da65 / output.c
1 /*****************************************************************************/
2 /*                                                                           */
3 /*                                 output.c                                  */
4 /*                                                                           */
5 /*                       Disassembler output routines                        */
6 /*                                                                           */
7 /*                                                                           */
8 /*                                                                           */
9 /* (C) 2000-2007 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 <stdarg.h>
38 #include <string.h>
39 #include <ctype.h>
40 #include <errno.h>
41
42 /* common */
43 #include "addrsize.h"
44 #include "cpu.h"
45 #include "version.h"
46
47 /* da65 */
48 #include "code.h"
49 #include "error.h"
50 #include "global.h"
51 #include "output.h"
52
53
54
55 /*****************************************************************************/
56 /*                                   Data                                    */
57 /*****************************************************************************/
58
59
60
61 static FILE*    F       = 0;            /* Output stream */
62 static unsigned Col     = 1;            /* Current column */
63 static unsigned Line    = 0;            /* Current line on page */
64 static unsigned Page    = 1;            /* Current output page */
65
66
67
68 /*****************************************************************************/
69 /*                                   Code                                    */
70 /*****************************************************************************/
71
72
73
74 static void PageHeader (void)
75 /* Print a page header */
76 {
77     fprintf (F,
78              "; da65 V%u.%u.%u - (C) Copyright 2000-2005,  Ullrich von Bassewitz\n"
79              "; Created:    %s\n"
80              "; Input file: %s\n"
81              "; Page:       %u\n\n",
82              VER_MAJOR, VER_MINOR, VER_PATCH,
83              Now,
84              InFile,
85              Page);
86 }
87
88
89
90 void OpenOutput (const char* Name)
91 /* Open the given file for output */
92 {
93     /* If we have a name given, open the output file, otherwise use stdout */
94     if (Name != 0) {
95         F = fopen (Name, "w");
96         if (F == 0) {
97             Error ("Cannot open `%s': %s", Name, strerror (errno));
98         }
99     } else {
100         F = stdout;
101     }
102
103     /* Output the header and initialize stuff */
104     PageHeader ();
105     Line = 5;
106     Col  = 1;
107 }
108
109
110
111 void CloseOutput (void)
112 /* Close the output file */
113 {
114     if (F != stdout && fclose (F) != 0) {
115         Error ("Error closing output file: %s", strerror (errno));
116     }
117 }
118
119
120
121 void Output (const char* Format, ...)
122 /* Write to the output file */
123 {
124     if (Pass == PassCount) {
125         va_list ap;
126         va_start (ap, Format);
127         Col += vfprintf (F, Format, ap);
128         va_end (ap);
129     }
130 }
131
132
133
134 void Indent (unsigned N)
135 /* Make sure the current line column is at position N (zero based) */
136 {
137     if (Pass == PassCount) {
138         while (Col < N) {
139             fputc (' ', F);
140             ++Col;
141         }
142     }
143 }
144
145
146
147 void LineFeed (void)
148 /* Add a linefeed to the output file */
149 {
150     if (Pass == PassCount) {
151         fputc ('\n', F);
152         if (PageLength > 0 && ++Line >= PageLength) {
153             if (FormFeeds) {
154                 fputc ('\f', F);
155             }
156             ++Page;
157             PageHeader ();
158             Line = 5;
159         }
160         Col = 1;
161     }
162 }
163
164
165
166 void DefLabel (const char* Name)
167 /* Define a label with the given name */
168 {
169     Output ("%s:", Name);
170     /* If the label is longer than the configured maximum, or if it runs into
171      * the opcode column, start a new line.
172      */
173     if (Col > LBreak+2 || Col > MCol) {
174         LineFeed ();
175     }
176 }
177
178
179
180 void DefForward (const char* Name, const char* Comment, unsigned Offs)
181 /* Define a label as "* + x", where x is the offset relative to the
182  * current PC.
183  */
184 {
185     if (Pass == PassCount) {
186         Output ("%s", Name);
187         Indent (ACol);
188         if (UseHexOffs) {
189             Output (":= * + $%04X", Offs);
190         } else {
191             Output (":= * + %u", Offs);
192         }
193         if (Comment) {
194             Indent (CCol);
195             Output ("; %s", Comment);
196         }
197         LineFeed ();
198     }
199 }
200
201
202
203 void DefConst (const char* Name, const char* Comment, unsigned Addr)
204 /* Define an address constant */
205 {
206     if (Pass == PassCount) {
207         Output ("%s", Name);
208         Indent (ACol);
209         Output (":= $%04X", Addr);
210         if (Comment) {
211             Indent (CCol);
212             Output ("; %s", Comment);
213         }
214         LineFeed ();
215     }
216 }
217
218
219
220 void StartSegment (const char* Name, unsigned AddrSize)
221 /* Start a segment */
222 {
223     if (Pass == PassCount) {
224         Output (".segment");
225         Indent (ACol);
226         if (AddrSize == ADDR_SIZE_DEFAULT) {
227             Output ("\"%s\"", Name);
228         } else {
229             Output ("\"%s\": %s", Name, AddrSizeToStr (AddrSize));
230         }
231         LineFeed ();
232     }
233 }
234
235
236
237 void DataByteLine (unsigned ByteCount)
238 /* Output a line with bytes */
239 {
240     unsigned I;
241
242     Indent (MCol);
243     Output (".byte");
244     Indent (ACol);
245     for (I = 0; I < ByteCount; ++I) {
246         if (I > 0) {
247             Output (",$%02X", CodeBuf[PC+I]);
248         } else {
249             Output ("$%02X", CodeBuf[PC+I]);
250         }
251     }
252     LineComment (PC, ByteCount);
253     LineFeed ();
254 }
255
256
257
258 void DataDByteLine (unsigned ByteCount)
259 /* Output a line with dbytes */
260 {
261     unsigned I;
262
263     Indent (MCol);
264     Output (".dbyt");
265     Indent (ACol);
266     for (I = 0; I < ByteCount; I += 2) {
267         if (I > 0) {
268             Output (",$%04X", GetCodeDByte (PC+I));
269         } else {
270             Output ("$%04X", GetCodeDByte (PC+I));
271         }
272     }
273     LineComment (PC, ByteCount);
274     LineFeed ();
275 }
276
277
278
279 void DataWordLine (unsigned ByteCount)
280 /* Output a line with words */
281 {
282     unsigned I;
283
284     Indent (MCol);
285     Output (".word");
286     Indent (ACol);
287     for (I = 0; I < ByteCount; I += 2) {
288         if (I > 0) {
289             Output (",$%04X", GetCodeWord (PC+I));
290         } else {
291             Output ("$%04X", GetCodeWord (PC+I));
292         }
293     }
294     LineComment (PC, ByteCount);
295     LineFeed ();
296 }
297
298
299
300 void DataDWordLine (unsigned ByteCount)
301 /* Output a line with dwords */
302 {
303     unsigned I;
304
305     Indent (MCol);
306     Output (".dword");
307     Indent (ACol);
308     for (I = 0; I < ByteCount; I += 4) {
309         if (I > 0) {
310             Output (",$%08lX", GetCodeDWord (PC+I));
311         } else {
312             Output ("$%08lX", GetCodeDWord (PC+I));
313         }
314     }
315     LineComment (PC, ByteCount);
316     LineFeed ();
317 }
318
319
320
321 void SeparatorLine (void)
322 /* Print a separator line */
323 {
324     if (Pass == PassCount && Comments >= 1) {
325         Output ("; ----------------------------------------------------------------------------");
326         LineFeed ();
327     }
328 }
329
330
331
332 void UserComment (const char* Comment)
333 /* Output a comment line */
334 {
335     Output ("; %s", Comment);
336     LineFeed ();
337 }
338
339
340
341 void LineComment (unsigned PC, unsigned Count)
342 /* Add a line comment with the PC and data bytes */
343 {
344     unsigned I;
345
346     if (Pass == PassCount && Comments >= 2) {
347         Indent (CCol);
348         Output ("; %04X", PC);
349         if (Comments >= 3) {
350             for (I = 0; I < Count; ++I) {
351                 Output (" %02X", CodeBuf [PC+I]);
352             }
353             if (Comments >= 4) {
354                 Indent (TCol);
355                 for (I = 0; I < Count; ++I) {
356                     unsigned char C = CodeBuf [PC+I];
357                     if (!isprint (C)) {
358                         C = '.';
359                     }
360                     Output ("%c", C);
361                 }
362             }
363         }
364     }
365 }
366
367
368
369 void OutputSettings (void)
370 /* Output CPU and other settings */
371 {
372     LineFeed ();
373     Indent (MCol);
374     Output (".setcpu");
375     Indent (ACol);
376     Output ("\"%s\"", CPUNames[CPU]);
377     LineFeed ();
378     LineFeed ();
379 }
380
381
382