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 /*****************************************************************************/
46 /*****************************************************************************/
48 /*****************************************************************************/
52 /* The macro hash table */
53 #define MACRO_TAB_SIZE 211
54 static Macro* MacroTab[MACRO_TAB_SIZE];
56 /* A table that holds the count of macros that start with a specific character.
57 * It is used to determine quickly, if an identifier may be a macro or not
58 * without calculating the hash over the name.
60 static unsigned short MacroFlagTab[256];
64 /*****************************************************************************/
66 /*****************************************************************************/
70 Macro* NewMacro (const char* Name)
71 /* Allocate a macro structure with the given name. The structure is not
72 * inserted into the macro table.
75 /* Get the length of the macro name */
76 unsigned Len = strlen(Name);
78 /* Allocate the structure */
79 Macro* M = xmalloc (sizeof(Macro) + Len);
81 /* Initialize the data */
83 M->ArgCount = -1; /* Flag: Not a function like macro */
88 memcpy (M->Name, Name, Len+1);
90 /* Return the new macro */
96 void FreeMacro (Macro* M)
97 /* Delete a macro definition. The function will NOT remove the macro from the
98 * table, use UndefineMacro for that.
103 for (I = 0; I < M->ArgCount; ++I) {
104 xfree (M->FormalArgs[I]);
106 xfree (M->FormalArgs);
107 xfree (M->ActualArgs);
108 xfree (M->Replacement);
114 void AddNumericMacro (const char* Name, long Val)
115 /* Add a macro for a numeric constant */
119 /* Make a string from the number */
120 sprintf (Buf, "%ld", Val);
122 /* Handle as text macro */
123 AddTextMacro (Name, Buf);
128 void AddTextMacro (const char* Name, const char* Val)
129 /* Add a macro for a textual constant */
131 /* Create a new macro */
132 Macro* M = NewMacro (Name);
134 /* Set the value as replacement text */
135 M->Replacement = xstrdup (Val);
137 /* Insert the macro into the macro table */
143 void InsertMacro (Macro* M)
144 /* Insert the given macro into the macro table. This call will also allocate
145 * the ActualArgs parameter array.
150 /* Allocate the ActualArgs parameter array */
151 if (M->ArgCount > 0) {
152 M->ActualArgs = xmalloc (M->ArgCount * sizeof(char*));
155 /* Get the hash value of the macro name */
156 Hash = HashStr (M->Name) % MACRO_TAB_SIZE;
158 /* Insert the macro */
159 M->Next = MacroTab[Hash];
162 /* Increment the number of macros starting with this char */
163 MacroFlagTab[(unsigned)(unsigned char)M->Name[0]]++;
168 int UndefineMacro (const char* Name)
169 /* Search for the macro with the given name and remove it from the macro
170 * table if it exists. Return 1 if a macro was found and deleted, return
174 /* Get the hash value of the macro name */
175 unsigned Hash = HashStr (Name) % MACRO_TAB_SIZE;
177 /* Search the hash chain */
179 Macro* M = MacroTab[Hash];
181 if (strcmp (M->Name, Name) == 0) {
186 MacroTab[Hash] = M->Next;
191 /* Decrement the number of macros starting with this char */
192 MacroFlagTab[(unsigned)(unsigned char)M->Name[0]]--;
194 /* Delete the macro */
212 Macro* FindMacro (const char* Name)
213 /* Find a macro with the given name. Return the macro definition or NULL */
215 /* Get the hash value of the macro name */
216 unsigned Hash = HashStr (Name) % MACRO_TAB_SIZE;
218 /* Search the hash chain */
219 Macro* M = MacroTab[Hash];
221 if (strcmp (M->Name, Name) == 0) {
236 int IsMacro (const char* Name)
237 /* Return true if the given name is the name of a macro, return false otherwise */
239 return FindMacro(Name) != 0;
244 int MaybeMacro (unsigned char C)
245 /* Return true if the given character may be the start of the name of an
246 * existing macro, return false if not.
249 return (MacroFlagTab[C] > 0);
254 const char* FindMacroArg (Macro* M, const char* Arg)
255 /* Search for a formal macro argument. If found, return the actual
256 * (replacement) argument. If the argument was not found, return NULL.
260 for (I = 0; I < M->ArgCount; ++I) {
261 if (strcmp (M->FormalArgs[I], Arg) == 0) {
263 return M->ActualArgs[I];
272 void AddMacroArg (Macro* M, const char* Arg)
273 /* Add a formal macro argument. */
275 /* Check if we have a duplicate macro argument, but add it anyway.
276 * Beware: Don't use FindMacroArg here, since the actual argument array
277 * may not be initialized.
280 for (I = 0; I < M->ArgCount; ++I) {
281 if (strcmp (M->FormalArgs[I], Arg) == 0) {
283 Error (ERR_DUPLICATE_MACRO_ARG, Arg);
288 /* Check if we have enough room available, otherwise expand the array
289 * that holds the formal argument list.
291 if (M->ArgCount >= M->MaxArgs) {
292 /* We must expand the array */
293 char** OldArgs = M->FormalArgs;
295 M->FormalArgs = xmalloc (M->MaxArgs * sizeof(char*));
296 memcpy (M->FormalArgs, OldArgs, M->ArgCount * sizeof (char*));
300 /* Add the new argument */
301 M->FormalArgs[M->ArgCount++] = xstrdup (Arg);
306 void PrintMacroStats (FILE* F)
307 /* Print macro statistics to the given text file. */
312 fprintf (F, "\n\nMacro Hash Table Summary\n");
313 for (I = 0; I < MACRO_TAB_SIZE; ++I) {
314 fprintf (F, "%3u : ", I);
318 fprintf (F, "%s ", M->Name);
323 fprintf (F, "empty\n");