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