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