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