1 /*****************************************************************************/
5 /* Preprocessor macro table for the cc65 C compiler */
9 /* (C) 2000 Ullrich von Bassewitz */
11 /* D-70597 Stuttgart */
12 /* EMail: uz@musoftware.de */
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 /*****************************************************************************/
39 #include "../common/hashstr.h"
40 #include "../common/xmalloc.h"
47 /*****************************************************************************/
49 /*****************************************************************************/
53 /* The macro hash table */
54 #define MACRO_TAB_SIZE 211
55 static Macro* MacroTab[MACRO_TAB_SIZE];
57 /* A table that holds the count of macros that start with a specific character.
58 * It is used to determine quickly, if an identifier may be a macro or not
59 * without calculating the hash over the name.
61 static unsigned short MacroFlagTab[256];
65 /*****************************************************************************/
67 /*****************************************************************************/
71 Macro* NewMacro (const char* Name)
72 /* Allocate a macro structure with the given name. The structure is not
73 * inserted into the macro table.
76 /* Get the length of the macro name */
77 unsigned Len = strlen(Name);
79 /* Allocate the structure */
80 Macro* M = xmalloc (sizeof(Macro) + Len);
82 /* Initialize the data */
84 M->ArgCount = -1; /* Flag: Not a function like macro */
89 memcpy (M->Name, Name, Len+1);
91 /* Return the new macro */
97 void FreeMacro (Macro* M)
98 /* Delete a macro definition. The function will NOT remove the macro from the
99 * table, use UndefineMacro for that.
104 for (I = 0; I < M->ArgCount; ++I) {
105 xfree (M->FormalArgs[I]);
107 xfree (M->FormalArgs);
108 xfree (M->ActualArgs);
109 xfree (M->Replacement);
115 void AddNumericMacro (const char* Name, long Val)
116 /* Add a macro for a numeric constant */
120 /* Make a string from the number */
121 sprintf (Buf, "%ld", Val);
123 /* Handle as text macro */
124 AddTextMacro (Name, Buf);
129 void AddTextMacro (const char* Name, const char* Val)
130 /* Add a macro for a textual constant */
132 /* Create a new macro */
133 Macro* M = NewMacro (Name);
135 /* Set the value as replacement text */
136 M->Replacement = xstrdup (Val);
138 /* Insert the macro into the macro table */
144 void InsertMacro (Macro* M)
145 /* Insert the given macro into the macro table. This call will also allocate
146 * the ActualArgs parameter array.
151 /* Allocate the ActualArgs parameter array */
152 if (M->ArgCount > 0) {
153 M->ActualArgs = xmalloc (M->ArgCount * sizeof(char*));
156 /* Get the hash value of the macro name */
157 Hash = HashStr (M->Name) % MACRO_TAB_SIZE;
159 /* Insert the macro */
160 M->Next = MacroTab[Hash];
163 /* Increment the number of macros starting with this char */
164 MacroFlagTab[(unsigned)(unsigned char)M->Name[0]]++;
169 int UndefineMacro (const char* Name)
170 /* Search for the macro with the given name and remove it from the macro
171 * table if it exists. Return 1 if a macro was found and deleted, return
175 /* Get the hash value of the macro name */
176 unsigned Hash = HashStr (Name) % MACRO_TAB_SIZE;
178 /* Search the hash chain */
180 Macro* M = MacroTab[Hash];
182 if (strcmp (M->Name, Name) == 0) {
187 MacroTab[Hash] = M->Next;
192 /* Decrement the number of macros starting with this char */
193 MacroFlagTab[(unsigned)(unsigned char)M->Name[0]]--;
195 /* Delete the macro */
213 Macro* FindMacro (const char* Name)
214 /* Find a macro with the given name. Return the macro definition or NULL */
216 /* Get the hash value of the macro name */
217 unsigned Hash = HashStr (Name) % MACRO_TAB_SIZE;
219 /* Search the hash chain */
220 Macro* M = MacroTab[Hash];
222 if (strcmp (M->Name, Name) == 0) {
237 int IsMacro (const char* Name)
238 /* Return true if the given name is the name of a macro, return false otherwise */
240 return FindMacro(Name) != 0;
245 int MaybeMacro (unsigned char C)
246 /* Return true if the given character may be the start of the name of an
247 * existing macro, return false if not.
250 return (MacroFlagTab[C] > 0);
255 const char* FindMacroArg (Macro* M, const char* Arg)
256 /* Search for a formal macro argument. If found, return the actual
257 * (replacement) argument. If the argument was not found, return NULL.
261 for (I = 0; I < M->ArgCount; ++I) {
262 if (strcmp (M->FormalArgs[I], Arg) == 0) {
264 return M->ActualArgs[I];
273 void AddMacroArg (Macro* M, const char* Arg)
274 /* Add a formal macro argument. */
276 /* Check if we have a duplicate macro argument, but add it anyway.
277 * Beware: Don't use FindMacroArg here, since the actual argument array
278 * may not be initialized.
281 for (I = 0; I < M->ArgCount; ++I) {
282 if (strcmp (M->FormalArgs[I], Arg) == 0) {
284 Error (ERR_DUPLICATE_MACRO_ARG, Arg);
289 /* Check if we have enough room available, otherwise expand the array
290 * that holds the formal argument list.
292 if (M->ArgCount >= M->MaxArgs) {
293 /* We must expand the array */
294 char** OldArgs = M->FormalArgs;
296 M->FormalArgs = xmalloc (M->MaxArgs * sizeof(char*));
297 memcpy (M->FormalArgs, OldArgs, M->ArgCount * sizeof (char*));
301 /* Add the new argument */
302 M->FormalArgs[M->ArgCount++] = xstrdup (Arg);
307 void PrintMacroStats (FILE* F)
308 /* Print macro statistics to the given text file. */
313 fprintf (F, "\n\nMacro Hash Table Summary\n");
314 for (I = 0; I < MACRO_TAB_SIZE; ++I) {
315 fprintf (F, "%3u : ", I);
319 fprintf (F, "%s ", M->Name);
324 fprintf (F, "empty\n");