]> git.sur5r.net Git - cc65/blob - src/da65/data.c
Added new options and info file attribute to set the columns where the
[cc65] / src / da65 / data.c
1 /*****************************************************************************/
2 /*                                                                           */
3 /*                                  data.c                                   */
4 /*                                                                           */
5 /*                           Data output routines                            */
6 /*                                                                           */
7 /*                                                                           */
8 /*                                                                           */
9 /* (C) 2000-2004 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 /* da65 */
37 #include "attrtab.h"
38 #include "code.h"
39 #include "error.h"
40 #include "global.h"
41 #include "labels.h"
42 #include "output.h"
43 #include "data.h"
44
45
46
47 /*****************************************************************************/
48 /*                                   Code                                    */
49 /*****************************************************************************/
50
51
52
53 static unsigned GetSpan (attr_t Style)
54 /* Get the number of bytes for a given style */
55 {
56     /* Get the number of bytes still available */
57     unsigned RemainingBytes = GetRemainingBytes ();
58
59     /* Count how many bytes are available. This number is limited by the
60      * number of remaining bytes, a label, or the end of the given Style
61      * attribute.
62      */
63     unsigned Count = 1;
64     while (Count < RemainingBytes) {
65         if (MustDefLabel(PC+Count) || GetStyleAttr (PC+Count) != Style) {
66             break;
67         }
68         ++Count;
69     }
70
71     /* Return the number of bytes */
72     return Count;
73 }
74
75
76
77 static unsigned DoTable (attr_t Style, unsigned MemberSize, void (*TableFunc) (unsigned))
78 /* Output a table of bytes */
79 {
80     unsigned BytesLeft;
81
82     /* Count how many bytes may be output. */
83     unsigned Count = GetSpan (Style);
84
85     /* If the count is less than the member size, print a row of Count data
86      * bytes. We assume here that there is no member with a size that is less
87      * than BytesPerLine.
88      */
89     if (Count < MemberSize) {
90         DataByteLine (Count);
91         return Count;
92     }
93
94     /* Make Count an even number of multiples of MemberSize */
95     Count &= ~(MemberSize-1);
96
97     /* Output as many data bytes lines as needed */
98     BytesLeft = Count;
99     while (BytesLeft > 0) {
100
101         /* Calculate the number of bytes for the next line */
102         unsigned Chunk = (BytesLeft > BytesPerLine)? BytesPerLine : BytesLeft;
103
104         /* Output a line with these bytes */
105         TableFunc (Chunk);
106
107         /* Next line */
108         BytesLeft -= Chunk;
109         PC        += Chunk;
110     }
111
112     /* If the next line is not the same style, add a separator */
113     if (CodeLeft() && GetStyleAttr (PC) != Style) {
114         SeparatorLine ();
115     }
116
117     /* Return the number of bytes output */
118     return Count;
119 }
120
121
122
123 unsigned ByteTable (void)
124 /* Output a table of bytes */
125 {
126     /* Call the low level function */
127     return DoTable (atByteTab, 1, DataByteLine);
128 }
129
130
131
132 unsigned DByteTable (void)
133 /* Output a table of dbytes */
134 {
135     /* Call the low level function */
136     return DoTable (atDByteTab, 2, DataDByteLine);
137 }
138
139
140
141 unsigned WordTable (void)
142 /* Output a table of words */
143 {
144     /* Call the low level function */
145     return DoTable (atWordTab, 2, DataWordLine);
146 }
147
148
149
150 unsigned DWordTable (void)
151 /* Output a table of double words */
152 {
153     /* Call the low level function */
154     return DoTable (atDWordTab, 4, DataDWordLine);
155 }
156
157
158
159 unsigned AddrTable (void)
160 /* Output a table of addresses */
161 {
162     unsigned long BytesLeft = GetRemainingBytes ();
163     unsigned long Start = PC;
164
165     /* Loop while table bytes left and we don't need to create a label at the
166      * current position.
167      */
168     while (BytesLeft && GetStyleAttr (PC) == atAddrTab) {
169
170         unsigned Addr;
171
172         /* If just one byte is left, define it and bail out */
173         if (BytesLeft == 1 || GetStyleAttr (PC+1) != atAddrTab) {
174             DataByteLine (1);
175             break;
176         }
177
178         /* More than one byte left. Define a forward label if necessary */
179         ForwardLabel (1);
180
181         /* Now get the address from the PC */
182         Addr = GetCodeWord (PC);
183
184         /* In pass 1, define a label, in pass 2 output the line */
185         if (Pass == 1) {
186             if (!HaveLabel (Addr)) {
187                 AddIntLabel (Addr);
188             }
189         } else {
190             const char* Label = GetLabel (Addr, PC);
191             if (Label == 0) {
192                 /* OOPS! Should not happen */
193                 Internal ("OOPS - Label for address 0x%06X disappeard!", Addr);
194             }
195             Indent (MCol);
196             Output (".addr");
197             Indent (ACol);
198             Output ("%s", Label);
199             LineComment (PC, 2);
200             LineFeed ();
201         }
202
203         /* Next table entry */
204         PC        += 2;
205         BytesLeft -= 2;
206
207         /* If we must define a label here, bail out */
208         if (BytesLeft && MustDefLabel (PC)) {
209             break;
210         }
211     }
212
213     /* If the next line is not an address table line, add a separator */
214     if (CodeLeft() && GetStyleAttr (PC) != atAddrTab) {
215         SeparatorLine ();
216     }
217
218     /* Return the number of bytes output */
219     return PC - Start;
220 }
221
222
223
224 unsigned RtsTable (void)
225 /* Output a table of RTS addresses (address - 1) */
226 {
227     unsigned long BytesLeft = GetRemainingBytes ();
228     unsigned long Start = PC;
229
230     /* Loop while table bytes left and we don't need to create a label at the
231      * current position.
232      */
233     while (BytesLeft && GetStyleAttr (PC) == atRtsTab) {
234
235         unsigned Addr;
236
237         /* If just one byte is left, define it and bail out */
238         if (BytesLeft == 1 || GetStyleAttr (PC+1) != atRtsTab) {
239             DataByteLine (1);
240             break;
241         }
242
243         /* More than one byte left. Define a forward label if necessary */
244         ForwardLabel (1);
245
246         /* Now get the address from the PC */
247         Addr = (GetCodeWord (PC) + 1) & 0xFFFF;
248
249         /* In pass 1, define a label, in pass 2 output the line */
250         if (Pass == 1) {
251             if (!HaveLabel (Addr)) {
252                 AddIntLabel (Addr);
253             }
254         } else {
255             const char* Label = GetLabel (Addr, PC);
256             if (Label == 0) {
257                 /* OOPS! Should not happen */
258                 Internal ("OOPS - Label for address 0x%06X disappeard!", Addr);
259             }
260             Indent (MCol);
261             Output (".word");
262             Indent (ACol);
263             Output ("%s-1", Label);
264             LineComment (PC, 2);
265             LineFeed ();
266         }
267
268         /* Next table entry */
269         PC        += 2;
270         BytesLeft -= 2;
271
272         /* If we must define a label here, bail out */
273         if (BytesLeft && MustDefLabel (PC)) {
274             break;
275         }
276     }
277
278     /* If the next line is not a return address table line, add a separator */
279     if (CodeLeft() && GetStyleAttr (PC) != atRtsTab) {
280         SeparatorLine ();
281     }
282
283     /* Return the number of bytes output */
284     return PC - Start;
285 }
286
287
288
289 unsigned TextTable (void)
290 /* Output a table of text messages */
291 {
292     /* Count how many bytes may be output. */
293     unsigned ByteCount = GetSpan (atTextTab);
294
295     /* Output as many data bytes lines as needed. */
296     unsigned BytesLeft = ByteCount;
297     while (BytesLeft > 0) {
298
299         unsigned I;
300
301         /* Count the number of characters that can be output as such */
302         unsigned Count = 0;
303         while (Count < BytesLeft && Count < BytesPerLine*4-1) {
304             unsigned char C = GetCodeByte (PC + Count);
305             if (C >= 0x20 && C <= 0x7E && C != '\"') {
306                 ++Count;
307             } else {
308                 break;
309             }
310         }
311
312         /* If we have text, output it */
313         if (Count > 0) {
314             unsigned CBytes;
315             Indent (MCol);
316             Output (".byte");
317             Indent (ACol);
318             Output ("\"");
319             for (I = 0; I < Count; ++I) {
320                 Output ("%c", GetCodeByte (PC+I));
321             }
322             Output ("\"");
323             CBytes = Count;
324             while (CBytes > 0) {
325                 unsigned Chunk = CBytes;
326                 if (Chunk > BytesPerLine) {
327                     Chunk = BytesPerLine;
328                 }
329                 LineComment (PC, Chunk);
330                 LineFeed ();
331                 CBytes -= Chunk;
332                 PC += Chunk;
333             }
334             BytesLeft -= Count;
335         }
336
337         /* Count the number of bytes that must be output as bytes */
338         Count = 0;
339         while (Count < BytesLeft && Count < BytesPerLine) {
340             unsigned char C = GetCodeByte (PC + Count);
341             if (C < 0x20 || C > 0x7E || C == '\"') {
342                 ++Count;
343             } else {
344                 break;
345             }
346         }
347
348         /* If we have raw output bytes, print them */
349         if (Count > 0) {
350             DataByteLine (Count);
351             PC += Count;
352             BytesLeft -= Count;
353         }
354
355     }
356
357     /* If the next line is not a byte table line, add a separator */
358     if (CodeLeft() && GetStyleAttr (PC) != atTextTab) {
359         SeparatorLine ();
360     }
361
362     /* Return the number of bytes output */
363     return ByteCount;
364 }
365
366
367