]> git.sur5r.net Git - cc65/blob - src/cc65/macrotab.c
Forgot a cast, sorry
[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-2011, Ullrich von Bassewitz                                      */
10 /*                Roemerstrasse 52                                           */
11 /*                D-70794 Filderstadt                                        */
12 /* EMail:         uz@cc65.org                                                */
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 /* common */
40 #include "hashfunc.h"
41 #include "xmalloc.h"
42
43 /* cc65 */
44 #include "error.h"
45 #include "macrotab.h"
46
47
48
49 /*****************************************************************************/
50 /*                                   data                                    */
51 /*****************************************************************************/
52
53
54
55 /* The macro hash table */
56 #define MACRO_TAB_SIZE  211
57 static Macro* MacroTab[MACRO_TAB_SIZE];
58
59
60
61 /*****************************************************************************/
62 /*                                   code                                    */
63 /*****************************************************************************/
64
65
66
67 Macro* NewMacro (const char* Name)
68 /* Allocate a macro structure with the given name. The structure is not
69 ** inserted into the macro table.
70 */
71 {
72     /* Get the length of the macro name */
73     unsigned Len = strlen(Name);
74
75     /* Allocate the structure */
76     Macro* M = (Macro*) xmalloc (sizeof(Macro) + Len);
77
78     /* Initialize the data */
79     M->Next        = 0;
80     M->Expanding   = 0;
81     M->ArgCount    = -1;        /* Flag: Not a function like macro */
82     M->MaxArgs     = 0;
83     InitCollection (&M->FormalArgs);
84     SB_Init (&M->Replacement);
85     M->Variadic    = 0;
86     memcpy (M->Name, Name, Len+1);
87
88     /* Return the new macro */
89     return M;
90 }
91
92
93
94 void FreeMacro (Macro* M)
95 /* Delete a macro definition. The function will NOT remove the macro from the
96 ** table, use UndefineMacro for that.
97 */
98 {
99     unsigned I;
100
101     for (I = 0; I < CollCount (&M->FormalArgs); ++I) {
102         xfree (CollAtUnchecked (&M->FormalArgs, I));
103     }
104     DoneCollection (&M->FormalArgs);
105     SB_Done (&M->Replacement);
106     xfree (M);
107 }
108
109
110
111 void DefineNumericMacro (const char* Name, long Val)
112 /* Define a macro for a numeric constant */
113 {
114     char Buf[64];
115
116     /* Make a string from the number */
117     sprintf (Buf, "%ld", Val);
118
119     /* Handle as text macro */
120     DefineTextMacro (Name, Buf);
121 }
122
123
124
125 void DefineTextMacro (const char* Name, const char* Val)
126 /* Define a macro for a textual constant */
127 {
128     /* Create a new macro */
129     Macro* M = NewMacro (Name);
130
131     /* Set the value as replacement text */
132     SB_CopyStr (&M->Replacement, Val);
133
134     /* Insert the macro into the macro table */
135     InsertMacro (M);
136 }
137
138
139
140 void InsertMacro (Macro* M)
141 /* Insert the given macro into the macro table. */
142 {
143     /* Get the hash value of the macro name */
144     unsigned Hash = HashStr (M->Name) % MACRO_TAB_SIZE;
145
146     /* Insert the macro */
147     M->Next = MacroTab[Hash];
148     MacroTab[Hash] = M;
149 }
150
151
152
153 int UndefineMacro (const char* Name)
154 /* Search for the macro with the given name and remove it from the macro
155 ** table if it exists. Return 1 if a macro was found and deleted, return
156 ** 0 otherwise.
157 */
158 {
159     /* Get the hash value of the macro name */
160     unsigned Hash = HashStr (Name) % MACRO_TAB_SIZE;
161
162     /* Search the hash chain */
163     Macro* L = 0;
164     Macro* M = MacroTab[Hash];
165     while (M) {
166         if (strcmp (M->Name, Name) == 0) {
167
168             /* Found it */
169             if (L == 0) {
170                 /* First in chain */
171                 MacroTab[Hash] = M->Next;
172             } else {
173                 L->Next = M->Next;
174             }
175
176             /* Delete the macro */
177             FreeMacro (M);
178
179             /* Done */
180             return 1;
181         }
182
183         /* Next macro */
184         L = M;
185         M = M->Next;
186     }
187
188     /* Not found */
189     return 0;
190 }
191
192
193
194 Macro* FindMacro (const char* Name)
195 /* Find a macro with the given name. Return the macro definition or NULL */
196 {
197     /* Get the hash value of the macro name */
198     unsigned Hash = HashStr (Name) % MACRO_TAB_SIZE;
199
200     /* Search the hash chain */
201     Macro* M = MacroTab[Hash];
202     while (M) {
203         if (strcmp (M->Name, Name) == 0) {
204             /* Found it */
205             return M;
206         }
207
208         /* Next macro */
209         M = M->Next;
210     }
211
212     /* Not found */
213     return 0;
214 }
215
216
217
218 int FindMacroArg (Macro* M, const char* Arg)
219 /* Search for a formal macro argument. If found, return the index of the
220 ** argument. If the argument was not found, return -1.
221 */
222 {
223     unsigned I;
224     for (I = 0; I < CollCount (&M->FormalArgs); ++I) {
225         if (strcmp (CollAtUnchecked (&M->FormalArgs, I), Arg) == 0) {
226             /* Found */
227             return I;
228         }
229     }
230
231     /* Not found */
232     return -1;
233 }
234
235
236
237 void AddMacroArg (Macro* M, const char* Arg)
238 /* Add a formal macro argument. */
239 {
240     /* Check if we have a duplicate macro argument, but add it anyway.
241     ** Beware: Don't use FindMacroArg here, since the actual argument array
242     ** may not be initialized.
243     */
244     unsigned I;
245     for (I = 0; I < CollCount (&M->FormalArgs); ++I) {
246         if (strcmp (CollAtUnchecked (&M->FormalArgs, I), Arg) == 0) {
247             /* Found */
248             Error ("Duplicate macro parameter: '%s'", Arg);
249             break;
250         }
251     }
252
253     /* Add the new argument */
254     CollAppend (&M->FormalArgs, xstrdup (Arg));
255     ++M->ArgCount;
256 }
257
258
259
260 int MacroCmp (const Macro* M1, const Macro* M2)
261 /* Compare two macros and return zero if both are identical. */
262 {
263     int I;
264
265     /* Argument count must be identical */
266     if (M1->ArgCount != M2->ArgCount) {
267         return 1;
268     }
269
270     /* Compare the arguments */
271     for (I = 0; I < M1->ArgCount; ++I) {
272         if (strcmp (CollConstAt (&M1->FormalArgs, I),
273                     CollConstAt (&M2->FormalArgs, I)) != 0) {
274             return 1;
275         }
276     }
277
278     /* Compare the replacement */
279     return SB_Compare (&M1->Replacement, &M2->Replacement);
280 }
281
282
283
284 void PrintMacroStats (FILE* F)
285 /* Print macro statistics to the given text file. */
286 {
287     unsigned I;
288     Macro* M;
289
290     fprintf (F, "\n\nMacro Hash Table Summary\n");
291     for (I = 0; I < MACRO_TAB_SIZE; ++I) {
292         fprintf (F, "%3u : ", I);
293         M = MacroTab [I];
294         if (M) {
295             while (M) {
296                 fprintf (F, "%s ", M->Name);
297                 M = M->Next;
298             }
299             fprintf (F, "\n");
300         } else {
301             fprintf (F, "empty\n");
302         }
303     }
304 }