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