]> git.sur5r.net Git - cc65/blob - src/cc65/macrotab.c
fd41abe46a2ebbbb096fcdb58e96096a72270e68
[cc65] / src / cc65 / macrotab.c
1 /*****************************************************************************/
2 /*                                                                           */
3 /*                                macrotab.h                                 */
4 /*                                                                           */
5 /*             Preprocessor macro table for the cc65 C compiler              */
6 /*                                                                           */
7 /*                                                                           */
8 /*                                                                           */
9 /* (C) 2000     Ullrich von Bassewitz                                        */
10 /*              Wacholderweg 14                                              */
11 /*              D-70597 Stuttgart                                            */
12 /* EMail:       uz@musoftware.de                                             */
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 #include <string.h>
38
39 #include "error.h"
40 #include "hashstr.h"
41 #include "mem.h"
42 #include "macrotab.h"
43
44
45
46 /*****************************************************************************/
47 /*                                   data                                    */
48 /*****************************************************************************/
49
50
51
52 /* The macro hash table */
53 #define MACRO_TAB_SIZE  211
54 static Macro* MacroTab[MACRO_TAB_SIZE];
55
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.
59  */
60 static unsigned short MacroFlagTab[256];
61
62
63
64 /*****************************************************************************/
65 /*                                   code                                    */
66 /*****************************************************************************/
67
68
69
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.
73  */
74 {
75     /* Get the length of the macro name */
76     unsigned Len = strlen(Name);
77
78     /* Allocate the structure */
79     Macro* M = xmalloc (sizeof(Macro) + Len);
80
81     /* Initialize the data */
82     M->Next        = 0;
83     M->ArgCount    = -1;        /* Flag: Not a function like macro */
84     M->MaxArgs     = 0;
85     M->FormalArgs  = 0;
86     M->ActualArgs  = 0;
87     M->Replacement = 0;
88     memcpy (M->Name, Name, Len+1);
89
90     /* Return the new macro */
91     return M;
92 }
93
94
95
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.
99  */
100 {
101     int I;
102
103     for (I = 0; I < M->ArgCount; ++I) {
104         xfree (M->FormalArgs[I]);
105     }
106     xfree (M->FormalArgs);
107     xfree (M->ActualArgs);
108     xfree (M->Replacement);
109     xfree (M);
110 }
111
112
113
114 void AddNumericMacro (const char* Name, long Val)
115 /* Add a macro for a numeric constant */
116 {
117     char Buf[64];
118
119     /* Make a string from the number */
120     sprintf (Buf, "%ld", Val);
121
122     /* Handle as text macro */
123     AddTextMacro (Name, Buf);
124 }
125
126
127
128 void AddTextMacro (const char* Name, const char* Val)
129 /* Add a macro for a textual constant */
130 {
131     /* Create a new macro */
132     Macro* M = NewMacro (Name);
133
134     /* Set the value as replacement text */
135     M->Replacement = xstrdup (Val);
136
137     /* Insert the macro into the macro table */
138     InsertMacro (M);
139 }
140
141
142
143 void InsertMacro (Macro* M)
144 /* Insert the given macro into the macro table. This call will also allocate
145  * the ActualArgs parameter array.
146  */
147 {
148     unsigned Hash;
149
150     /* Allocate the ActualArgs parameter array */
151     if (M->ArgCount > 0) {
152         M->ActualArgs = xmalloc (M->ArgCount * sizeof(char*));
153     }
154
155     /* Get the hash value of the macro name */
156     Hash = HashStr (M->Name) % MACRO_TAB_SIZE;
157
158     /* Insert the macro */
159     M->Next = MacroTab[Hash];
160     MacroTab[Hash] = M;
161
162     /* Increment the number of macros starting with this char */
163     MacroFlagTab[(unsigned)(unsigned char)M->Name[0]]++;
164 }
165
166
167
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
171  * 0 otherwise.
172  */
173 {
174     /* Get the hash value of the macro name */
175     unsigned Hash = HashStr (Name) % MACRO_TAB_SIZE;
176
177     /* Search the hash chain */
178     Macro* L = 0;
179     Macro* M = MacroTab[Hash];
180     while (M) {
181         if (strcmp (M->Name, Name) == 0) {
182
183             /* Found it */
184             if (L == 0) {
185                 /* First in chain */
186                 MacroTab[Hash] = M->Next;
187             } else {
188                 L->Next = M->Next;
189             }
190
191             /* Decrement the number of macros starting with this char */
192             MacroFlagTab[(unsigned)(unsigned char)M->Name[0]]--;
193
194             /* Delete the macro */
195             FreeMacro (M);
196
197             /* Done */
198             return 1;
199         }
200
201         /* Next macro */
202         L = M;
203         M = M->Next;
204     }
205
206     /* Not found */
207     return 0;
208 }
209
210
211
212 Macro* FindMacro (const char* Name)
213 /* Find a macro with the given name. Return the macro definition or NULL */
214 {
215     /* Get the hash value of the macro name */
216     unsigned Hash = HashStr (Name) % MACRO_TAB_SIZE;
217
218     /* Search the hash chain */
219     Macro* M = MacroTab[Hash];
220     while (M) {
221         if (strcmp (M->Name, Name) == 0) {
222             /* Found it */
223             return M;
224         }
225
226         /* Next macro */
227         M = M->Next;
228     }
229
230     /* Not found */
231     return 0;
232 }
233
234
235
236 int IsMacro (const char* Name)
237 /* Return true if the given name is the name of a macro, return false otherwise */
238 {
239     return FindMacro(Name) != 0;
240 }
241
242
243
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.
247  */
248 {
249     return (MacroFlagTab[C] > 0);
250 }
251
252
253
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.
257  */
258 {
259     int I;
260     for (I = 0; I < M->ArgCount; ++I) {
261         if (strcmp (M->FormalArgs[I], Arg) == 0) {
262             /* Found */
263             return M->ActualArgs[I];
264         }
265     }
266     /* Not found */
267     return 0;
268 }
269
270
271
272 void AddMacroArg (Macro* M, const char* Arg)
273 /* Add a formal macro argument. */
274 {
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.
278      */
279     int I;
280     for (I = 0; I < M->ArgCount; ++I) {
281         if (strcmp (M->FormalArgs[I], Arg) == 0) {
282             /* Found */
283             Error (ERR_DUPLICATE_MACRO_ARG, Arg);
284             break;
285         }
286     }
287
288     /* Check if we have enough room available, otherwise expand the array
289      * that holds the formal argument list.
290      */
291     if (M->ArgCount >= M->MaxArgs) {
292         /* We must expand the array */
293         char** OldArgs = M->FormalArgs;
294         M->MaxArgs += 10;
295         M->FormalArgs = xmalloc (M->MaxArgs * sizeof(char*));
296         memcpy (M->FormalArgs, OldArgs, M->ArgCount * sizeof (char*));
297         xfree (OldArgs);
298     }
299
300     /* Add the new argument */
301     M->FormalArgs[M->ArgCount++] = xstrdup (Arg);
302 }
303
304
305
306 void PrintMacroStats (FILE* F)
307 /* Print macro statistics to the given text file. */
308 {
309     unsigned I;
310     Macro* M;
311
312     fprintf (F, "\n\nMacro Hash Table Summary\n");
313     for (I = 0; I < MACRO_TAB_SIZE; ++I) {
314         fprintf (F, "%3u : ", I);
315         M = MacroTab [I];
316         if (M) {
317             while (M) {
318                 fprintf (F, "%s ", M->Name);
319                 M = M->Next;
320             }
321             fprintf (F, "\n");
322         } else {
323             fprintf (F, "empty\n");
324         }
325     }
326 }
327
328
329