]> git.sur5r.net Git - cc65/blob - src/ca65/symbol.c
Added search paths similar to that of the linker and compiler.
[cc65] / src / ca65 / symbol.c
1 /*****************************************************************************/
2 /*                                                                           */
3 /*                                 symbol.c                                  */
4 /*                                                                           */
5 /*                   Parse a symbol name and search for it                   */
6 /*                                                                           */
7 /*                                                                           */
8 /*                                                                           */
9 /* (C) 1998-2008 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 <string.h>
37
38 /* common */
39 #include "strbuf.h"
40
41 /* ca65 */
42 #include "error.h"
43 #include "nexttok.h"
44 #include "scanner.h"
45 #include "symbol.h"
46 #include "symtab.h"
47
48
49
50 /*****************************************************************************/
51 /*                                   Code                                    */
52 /*****************************************************************************/
53
54
55
56 SymTable* ParseScopedIdent (StrBuf* Name, StrBuf* FullName)
57 /* Parse a (possibly scoped) identifer. The scope of the name must exist and
58  * is returned as function result, while the last part (the identifier) which
59  * may be either a symbol or a scope depending on the context is returned in
60  * Name. FullName is a string buffer that is used to store the full name of
61  * the identifier including the scope. It is used internally and may be used
62  * by the caller for error messages or similar.
63  */
64 {
65     SymTable* Scope;
66
67     /* Clear both passed string buffers */
68     SB_Clear (Name);
69     SB_Clear (FullName);
70
71     /* Get the starting table */
72     if (Tok == TOK_NAMESPACE) {
73
74         /* Start from the root scope */
75         Scope = RootScope;
76
77     } else if (Tok == TOK_IDENT) {
78
79         /* Remember the name and skip it */
80         SB_Copy (Name, &SVal);
81         NextTok ();
82
83         /* If no namespace symbol follows, we're already done */
84         if (Tok != TOK_NAMESPACE) {
85             SB_Terminate (FullName);
86             return CurrentScope;
87         }
88
89         /* Pass the scope back to the caller */
90         SB_Append (FullName, Name);
91
92         /* The scope must exist, so search for it starting with the current
93          * scope.
94          */
95         Scope = SymFindAnyScope (CurrentScope, Name);
96         if (Scope == 0) {
97             /* Scope not found */
98             SB_Terminate (FullName);
99             Error ("No such scope: `%m%p'", FullName);
100             return 0;
101         }
102
103     } else {
104
105         /* Invalid token */
106         Error ("Identifier expected");
107         return 0;
108
109     }
110
111     /* Skip the namespace token that follows */
112     SB_AppendStr (FullName, "::");
113     NextTok ();
114
115     /* Resolve scopes. */
116     while (1) {
117
118         /* Next token must be an identifier. */
119         if (Tok != TOK_IDENT) {
120             Error ("Identifier expected");
121             return 0;
122         }
123
124         /* Remember and skip the identifier */
125         SB_Copy (Name, &SVal);
126         NextTok ();
127
128         /* If a namespace token follows, we search for another scope, otherwise
129          * the name is a symbol and we're done.
130          */
131         if (Tok != TOK_NAMESPACE) {
132             /* Symbol */
133             return Scope;
134         }
135
136         /* Pass the scope back to the caller */
137         SB_Append (FullName, Name);
138
139         /* Search for the child scope */
140         Scope = SymFindScope (Scope, Name, SYM_FIND_EXISTING);
141         if (Scope == 0) {
142             /* Scope not found */
143             Error ("No such scope: `%m%p'", FullName);
144             return 0;
145         }
146
147         /* Skip the namespace token that follows */
148         SB_AppendStr (FullName, "::");
149         NextTok ();
150     }
151 }
152
153
154
155 SymEntry* ParseScopedSymName (int AllocNew)
156 /* Parse a (possibly scoped) symbol name, search for it in the symbol table
157  * and return the symbol table entry.
158  */
159 {
160     StrBuf    ScopeName = STATIC_STRBUF_INITIALIZER;
161     StrBuf    Ident = STATIC_STRBUF_INITIALIZER;
162     int       NoScope;
163     SymEntry* Sym;
164
165     /* Parse the scoped symbol name */
166     SymTable* Scope = ParseScopedIdent (&Ident, &ScopeName);
167
168     /* If ScopeName is empty, no scope was specified */
169     NoScope = SB_IsEmpty (&ScopeName);
170
171     /* We don't need ScopeName any longer */
172     SB_Done (&ScopeName);
173
174     /* Check if the scope is valid. Errors have already been diagnosed by
175      * the routine, so just exit.
176      */
177     if (Scope) {
178         /* Search for the symbol and return it. If no scope was specified,
179          * search also in the upper levels.
180          */
181         if (NoScope && !AllocNew) {
182             Sym = SymFindAny (Scope, &Ident);
183         } else {
184             Sym = SymFind (Scope, &Ident, AllocNew);
185         }
186     } else {
187         /* No scope ==> no symbol. To avoid errors in the calling routine that
188          * may not expect NULL to be returned if AllocNew is true, create a new
189          * symbol.
190          */
191         if (AllocNew) {
192             Sym = NewSymEntry (&Ident, SF_NONE);
193         } else {
194             Sym = 0;
195         }
196     }
197
198     /* Deallocate memory for ident */
199     SB_Done (&Ident);
200
201     /* Return the symbol found */
202     return Sym;
203 }
204
205
206
207 SymTable* ParseScopedSymTable (void)
208 /* Parse a (possibly scoped) symbol table (scope) name, search for it in the
209  * symbol space and return the symbol table struct.
210  */
211 {
212     StrBuf    ScopeName = STATIC_STRBUF_INITIALIZER;
213     StrBuf    Name = STATIC_STRBUF_INITIALIZER;
214     int       NoScope;
215
216
217     /* Parse the scoped symbol name */
218     SymTable* Scope = ParseScopedIdent (&Name, &ScopeName);
219
220     /* If ScopeName is empty, no scope was specified */
221     NoScope = SB_IsEmpty (&ScopeName);
222
223     /* We don't need FullName any longer */
224     SB_Done (&ScopeName);
225
226     /* If we got no error, search for the child scope withint the enclosing one.
227      * Beware: If no explicit parent scope was specified, search in all upper
228      * levels.
229      */
230     if (Scope) {
231         /* Search for the last scope */
232         if (NoScope) {
233             Scope = SymFindAnyScope (Scope, &Name);
234         } else {
235             Scope = SymFindScope (Scope, &Name, SYM_FIND_EXISTING);
236         }
237     }
238
239     /* Free memory for name */
240     SB_Done (&Name);
241
242     /* Return the scope found */
243     return Scope;
244 }
245
246
247