1 /*****************************************************************************/
5 /* Literal string handling for the cc65 C compiler */
9 /* (C) 1998-2009, Ullrich von Bassewitz */
10 /* Roemerstrasse 52 */
11 /* D-70794 Filderstadt */
12 /* EMail: uz@cc65.org */
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. */
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: */
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 */
32 /*****************************************************************************/
53 /*****************************************************************************/
55 /*****************************************************************************/
59 /* Forward for struct SymEntry */
62 /* Definition of the literal pool */
63 typedef struct LiteralPool 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 */
71 /* The current literal pool */
72 static LiteralPool* LP = 0;
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
79 static Collection LPStack = STATIC_COLLECTION_INITIALIZER;
83 /*****************************************************************************/
85 /*****************************************************************************/
89 static LiteralPool* NewLiteralPool (struct SymEntry* Func)
90 /* Create a new literal pool and return it */
93 LiteralPool* LP = xmalloc (sizeof (*LP));
95 /* Initialize the fields */
96 LP->Writable = IS_Get (&WritableStrings);
97 LP->Label = GetLocalLabel ();
101 /* Return the new pool */
107 static void FreeLiteralPool (LiteralPool* LP)
108 /* Free a LiteralPool structure */
110 /* Free the string buffer contained within the struct */
113 /* Free the struct itself */
119 void InitLiteralPool (void)
120 /* Initialize the literal pool */
122 /* Create a new pool */
123 LP = NewLiteralPool (0);
128 void PushLiteralPool (struct SymEntry* Func)
129 /* Push the current literal pool onto the stack and create a new one */
131 /* We must have a literal pool to push! */
132 PRECONDITION (LP != 0);
134 /* Push the old pool */
135 CollAppend (&LPStack, LP);
137 /* Create a new one */
138 LP = NewLiteralPool (Func);
143 void PopLiteralPool (void)
144 /* Free the current literal pool and restore the one from TOS */
146 /* Free the current literal pool */
147 FreeLiteralPool (LP);
149 /* Pop one from stack */
150 LP = CollPop (&LPStack);
155 void TranslateLiteralPool (unsigned Offs)
156 /* Translate the literals starting from the given offset into the target
160 TgtTranslateBuf (SB_GetBuf (&LP->Pool) + Offs, SB_GetLen (&LP->Pool) - Offs);
165 void DumpLiteralPool (void)
166 /* Dump the literal pool */
168 /* If nothing there, exit... */
169 if (SB_GetLen (&LP->Pool) == 0) {
173 /* Switch to the correct segment */
180 /* Define the label */
181 g_defdatalabel (LP->Label);
183 /* Translate the buffer contents into the target charset */
184 TranslateLiteralPool (0);
186 /* Output the buffer data */
187 g_defbytes (SB_GetConstBuf (&LP->Pool), SB_GetLen (&LP->Pool));
192 unsigned GetLiteralPoolLabel (void)
193 /* Return the asm label for the current literal pool */
200 unsigned GetLiteralPoolOffs (void)
201 /* Return the current offset into the literal pool */
203 return SB_GetLen (&LP->Pool);
208 void ResetLiteralPoolOffs (unsigned Offs)
209 /* Reset the offset into the literal pool to some earlier value, effectively
210 * removing values from the pool.
213 CHECK (Offs <= SB_GetLen (&LP->Pool));
214 SB_Cut (&LP->Pool, Offs);
219 unsigned AddLiteral (const char* S)
220 /* Add a literal string to the literal pool. Return the starting offset into
224 return AddLiteralBuf (S, strlen (S) + 1);
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.
234 /* Remember the starting offset */
235 unsigned Start = SB_GetLen (&LP->Pool);
237 /* Append the buffer */
238 SB_AppendBuf (&LP->Pool, Buf, Len);
240 /* Return the starting offset */
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.
251 return AddLiteralBuf (SB_GetConstBuf (S), SB_GetLen (S));
256 const char* GetLiteral (unsigned Offs)
257 /* Get a pointer to the literal with the given offset in the pool */
259 CHECK (Offs < SB_GetLen (&LP->Pool));
260 return SB_GetConstBuf (&LP->Pool) + Offs;
265 void GetLiteralStrBuf (StrBuf* Target, unsigned Offs)
266 /* Copy the string starting at Offs and lasting to the end of the buffer
270 CHECK (Offs <= SB_GetLen (&LP->Pool));
271 SB_Slice (Target, &LP->Pool, Offs, SB_GetLen (&LP->Pool) - Offs);
276 void PrintLiteralPoolStats (FILE* F)
277 /* Print statistics about the literal space used */
279 fprintf (F, "Literal space used: %u bytes\n", SB_GetLen (&LP->Pool));