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 /*****************************************************************************/
49 /*****************************************************************************/
51 /*****************************************************************************/
55 /* The macro hash table */
56 #define MACRO_TAB_SIZE 211
57 static Macro* MacroTab[MACRO_TAB_SIZE];
59 /* A table that holds the count of macros that start with a specific character.
60 * It is used to determine quickly, if an identifier may be a macro or not
61 * without calculating the hash over the name.
63 static unsigned short MacroFlagTab[256];
67 /*****************************************************************************/
69 /*****************************************************************************/
73 Macro* NewMacro (const char* Name)
74 /* Allocate a macro structure with the given name. The structure is not
75 * inserted into the macro table.
78 /* Get the length of the macro name */
79 unsigned Len = strlen(Name);
81 /* Allocate the structure */
82 Macro* M = (Macro*) xmalloc (sizeof(Macro) + Len);
84 /* Initialize the data */
86 M->ArgCount = -1; /* Flag: Not a function like macro */
91 memcpy (M->Name, Name, Len+1);
93 /* Return the new macro */
99 void FreeMacro (Macro* M)
100 /* Delete a macro definition. The function will NOT remove the macro from the
101 * table, use UndefineMacro for that.
106 for (I = 0; I < M->ArgCount; ++I) {
107 xfree (M->FormalArgs[I]);
109 xfree (M->FormalArgs);
110 xfree (M->ActualArgs);
111 xfree (M->Replacement);
117 void DefineNumericMacro (const char* Name, long Val)
118 /* Define a macro for a numeric constant */
122 /* Make a string from the number */
123 sprintf (Buf, "%ld", Val);
125 /* Handle as text macro */
126 DefineTextMacro (Name, Buf);
131 void DefineTextMacro (const char* Name, const char* Val)
132 /* Define a macro for a textual constant */
134 /* Create a new macro */
135 Macro* M = NewMacro (Name);
137 /* Set the value as replacement text */
138 M->Replacement = xstrdup (Val);
140 /* Insert the macro into the macro table */
146 void InsertMacro (Macro* M)
147 /* Insert the given macro into the macro table. This call will also allocate
148 * the ActualArgs parameter array.
153 /* Allocate the ActualArgs parameter array */
154 if (M->ArgCount > 0) {
155 M->ActualArgs = (char const**) xmalloc (M->ArgCount * sizeof(char*));
158 /* Get the hash value of the macro name */
159 Hash = HashStr (M->Name) % MACRO_TAB_SIZE;
161 /* Insert the macro */
162 M->Next = MacroTab[Hash];
165 /* Increment the number of macros starting with this char */
166 MacroFlagTab[(unsigned)(unsigned char)M->Name[0]]++;
171 int UndefineMacro (const char* Name)
172 /* Search for the macro with the given name and remove it from the macro
173 * table if it exists. Return 1 if a macro was found and deleted, return
177 /* Get the hash value of the macro name */
178 unsigned Hash = HashStr (Name) % MACRO_TAB_SIZE;
180 /* Search the hash chain */
182 Macro* M = MacroTab[Hash];
184 if (strcmp (M->Name, Name) == 0) {
189 MacroTab[Hash] = M->Next;
194 /* Decrement the number of macros starting with this char */
195 MacroFlagTab[(unsigned)(unsigned char)M->Name[0]]--;
197 /* Delete the macro */
215 Macro* FindMacro (const char* Name)
216 /* Find a macro with the given name. Return the macro definition or NULL */
218 /* Get the hash value of the macro name */
219 unsigned Hash = HashStr (Name) % MACRO_TAB_SIZE;
221 /* Search the hash chain */
222 Macro* M = MacroTab[Hash];
224 if (strcmp (M->Name, Name) == 0) {
239 int IsMacro (const char* Name)
240 /* Return true if the given name is the name of a macro, return false otherwise */
242 return MaybeMacro(Name[0]) && FindMacro(Name) != 0;
247 int MaybeMacro (unsigned char C)
248 /* Return true if the given character may be the start of the name of an
249 * existing macro, return false if not.
252 return (MacroFlagTab[C] > 0);
257 const char* FindMacroArg (Macro* M, const char* Arg)
258 /* Search for a formal macro argument. If found, return the actual
259 * (replacement) argument. If the argument was not found, return NULL.
263 for (I = 0; I < M->ArgCount; ++I) {
264 if (strcmp (M->FormalArgs[I], Arg) == 0) {
266 return M->ActualArgs[I];
275 void AddMacroArg (Macro* M, const char* Arg)
276 /* Add a formal macro argument. */
278 /* Check if we have a duplicate macro argument, but add it anyway.
279 * Beware: Don't use FindMacroArg here, since the actual argument array
280 * may not be initialized.
283 for (I = 0; I < M->ArgCount; ++I) {
284 if (strcmp (M->FormalArgs[I], Arg) == 0) {
286 Error ("Duplicate macro parameter: `%s'", Arg);
291 /* Check if we have enough room available, otherwise expand the array
292 * that holds the formal argument list.
294 if (M->ArgCount >= (int) M->MaxArgs) {
295 /* We must expand the array */
296 char** OldArgs = M->FormalArgs;
298 M->FormalArgs = (char**) xmalloc (M->MaxArgs * sizeof(char*));
299 memcpy (M->FormalArgs, OldArgs, M->ArgCount * sizeof (char*));
303 /* Add the new argument */
304 M->FormalArgs[M->ArgCount++] = xstrdup (Arg);
309 int MacroCmp (const Macro* M1, const Macro* M2)
310 /* Compare two macros and return zero if both are identical. */
314 /* Argument count must be identical */
315 if (M1->ArgCount != M2->ArgCount) {
319 /* Compare the arguments */
320 for (I = 0; I < M1->ArgCount; ++I) {
321 if (strcmp (M1->FormalArgs[I], M2->FormalArgs[I]) != 0) {
326 /* Compare the replacement */
327 return strcmp (M1->Replacement, M2->Replacement);
332 void PrintMacroStats (FILE* F)
333 /* Print macro statistics to the given text file. */
338 fprintf (F, "\n\nMacro Hash Table Summary\n");
339 for (I = 0; I < MACRO_TAB_SIZE; ++I) {
340 fprintf (F, "%3u : ", I);
344 fprintf (F, "%s ", M->Name);
349 fprintf (F, "empty\n");