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