]> git.sur5r.net Git - cc65/blob - src/cc65/litpool.c
Fixed problem with last change. Wide string constants were not handled
[cc65] / src / cc65 / litpool.c
1 /*****************************************************************************/
2 /*                                                                           */
3 /*                                 litpool.c                                 */
4 /*                                                                           */
5 /*              Literal string handling for the cc65 C compiler              */
6 /*                                                                           */
7 /*                                                                           */
8 /*                                                                           */
9 /* (C) 1998-2009, 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
38 /* common */
39 #include "check.h"
40 #include "coll.h"
41 #include "tgttrans.h"
42 #include "xmalloc.h"
43
44 /* cc65 */
45 #include "asmlabel.h"
46 #include "codegen.h"
47 #include "error.h"
48 #include "global.h"
49 #include "litpool.h"
50
51
52
53 /*****************************************************************************/
54 /*                                   Data                                    */
55 /*****************************************************************************/
56
57
58
59 /* Forward for struct SymEntry */
60 struct SymEntry;
61
62 /* Definition of the literal pool */
63 typedef struct LiteralPool LiteralPool;
64 struct LiteralPool {
65     int                 Writable;       /* True if strings are writable */
66     unsigned            Label;          /* Pool asm label */
67     struct SymEntry*    Func;           /* Function that contains the pool */
68     StrBuf              Pool;           /* The pool itself */
69 };
70
71 /* The current literal pool */
72 static LiteralPool*     LP = 0;
73
74 /* Stack that contains the nested literal pools. Since TOS is in LiteralPool
75  * and functions aren't nested in C, the maximum depth is 1. I'm using a
76  * collection anyway, so the code is prepared for nested functions or
77  * whatever.
78  */
79 static Collection       LPStack  = STATIC_COLLECTION_INITIALIZER;
80
81
82
83 /*****************************************************************************/
84 /*                                   Code                                    */
85 /*****************************************************************************/
86
87
88
89 static LiteralPool* NewLiteralPool (struct SymEntry* Func)
90 /* Create a new literal pool and return it */
91 {
92     /* Allocate memory */
93     LiteralPool* LP = xmalloc (sizeof (*LP));
94
95     /* Initialize the fields */
96     LP->Writable = IS_Get (&WritableStrings);
97     LP->Label = GetLocalLabel ();
98     LP->Func  = Func;
99     SB_Init (&LP->Pool);
100
101     /* Return the new pool */
102     return LP;
103 }
104
105
106
107 static void FreeLiteralPool (LiteralPool* LP)
108 /* Free a LiteralPool structure */
109 {
110     /* Free the string buffer contained within the struct */
111     SB_Done (&LP->Pool);
112
113     /* Free the struct itself */
114     xfree (LP);
115 }
116
117
118
119 void InitLiteralPool (void)
120 /* Initialize the literal pool */
121 {
122     /* Create a new pool */
123     LP = NewLiteralPool (0);
124 }
125
126
127
128 void PushLiteralPool (struct SymEntry* Func)
129 /* Push the current literal pool onto the stack and create a new one */
130 {
131     /* We must have a literal pool to push! */
132     PRECONDITION (LP != 0);
133
134     /* Push the old pool */
135     CollAppend (&LPStack, LP);
136
137     /* Create a new one */
138     LP = NewLiteralPool (Func);
139 }
140
141
142
143 void PopLiteralPool (void)
144 /* Free the current literal pool and restore the one from TOS */
145 {
146     /* Free the current literal pool */
147     FreeLiteralPool (LP);
148
149     /* Pop one from stack */
150     LP = CollPop (&LPStack);
151 }
152
153
154
155 void TranslateLiteralPool (unsigned Offs)
156 /* Translate the literals starting from the given offset into the target
157  * charset.
158  */
159 {
160     TgtTranslateBuf (SB_GetBuf (&LP->Pool) + Offs, SB_GetLen (&LP->Pool) - Offs);
161 }
162
163
164
165 void DumpLiteralPool (void)
166 /* Dump the literal pool */
167 {
168     /* If nothing there, exit... */
169     if (SB_GetLen (&LP->Pool) == 0) {
170         return;
171     }
172
173     /* Switch to the correct segment */
174     if (LP->Writable) {
175         g_usedata ();
176     } else {
177         g_userodata ();
178     }
179
180     /* Define the label */
181     g_defdatalabel (LP->Label);
182
183     /* Translate the buffer contents into the target charset */
184     TranslateLiteralPool (0);
185
186     /* Output the buffer data */
187     g_defbytes (SB_GetConstBuf (&LP->Pool), SB_GetLen (&LP->Pool));
188 }
189
190
191
192 unsigned GetLiteralPoolLabel (void)
193 /* Return the asm label for the current literal pool */
194 {
195     return LP->Label;
196 }
197
198
199
200 unsigned GetLiteralPoolOffs (void)
201 /* Return the current offset into the literal pool */
202 {
203     return SB_GetLen (&LP->Pool);
204 }
205
206
207
208 void ResetLiteralPoolOffs (unsigned Offs)
209 /* Reset the offset into the literal pool to some earlier value, effectively
210  * removing values from the pool.
211  */
212 {
213     CHECK (Offs <= SB_GetLen (&LP->Pool));
214     SB_Cut (&LP->Pool, Offs);
215 }
216
217
218
219 unsigned AddLiteral (const char* S)
220 /* Add a literal string to the literal pool. Return the starting offset into
221  * the pool
222  */
223 {
224     return AddLiteralBuf (S, strlen (S) + 1);
225 }
226
227
228
229 unsigned AddLiteralBuf (const void* Buf, unsigned Len)
230 /* Add a buffer containing a literal string to the literal pool. Return the
231  * starting offset into the pool for this string.
232  */
233 {
234     /* Remember the starting offset */
235     unsigned Start = SB_GetLen (&LP->Pool);
236
237     /* Append the buffer */
238     SB_AppendBuf (&LP->Pool, Buf, Len);
239
240     /* Return the starting offset */
241     return Start;
242 }
243
244
245
246 unsigned AddLiteralStr (const StrBuf* S)
247 /* Add a literal string to the literal pool. Return the starting offset into
248  * the pool for this string.
249  */
250 {
251     return AddLiteralBuf (SB_GetConstBuf (S), SB_GetLen (S));
252 }
253
254
255
256 const char* GetLiteral (unsigned Offs)
257 /* Get a pointer to the literal with the given offset in the pool */
258 {
259     CHECK (Offs < SB_GetLen (&LP->Pool));
260     return SB_GetConstBuf (&LP->Pool) + Offs;
261 }
262
263
264
265 void GetLiteralStrBuf (StrBuf* Target, unsigned Offs)
266 /* Copy the string starting at Offs and lasting to the end of the buffer
267  * into Target.
268  */
269 {
270     CHECK (Offs <= SB_GetLen (&LP->Pool));
271     SB_Slice (Target, &LP->Pool, Offs, SB_GetLen (&LP->Pool) - Offs);
272 }
273
274
275
276 void PrintLiteralPoolStats (FILE* F)
277 /* Print statistics about the literal space used */
278 {
279     fprintf (F, "Literal space used: %u bytes\n", SB_GetLen (&LP->Pool));
280 }
281
282
283