]> git.sur5r.net Git - cc65/blob - src/ca65/symbol.c
New module strstack
[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-2003 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 <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 (char* Name, StrBuf* ScopeName)
57 /* Parse a (possibly scoped) identifer. Name must point to a buffer big enough
58  * to hold such an identifier. The scope of the name must exist and is returned
59  * as function result, while the last part (the identifier) which may be either
60  * a symbol or a scope depending on the context is returned in Name. ScopeName
61  * is a string buffer that is used to store the name of the scope, the
62  * identifier lives in. It does contain anything but the identifier itself, so
63  * if ScopeName is empty on return, no explicit scope was specified. The full
64  * name of the identifier (including the scope) is ScopeName+Name.
65  */
66 {
67     /* Get the starting table */
68     SymTable* Scope;
69     if (Tok == TOK_NAMESPACE) {
70
71         /* Start from the root scope */
72         Scope = RootScope;
73
74     } else if (Tok == TOK_IDENT) {
75
76         /* Remember the name and skip it */
77         strcpy (Name, SVal);
78         NextTok ();
79
80         /* If no namespace symbol follows, we're already done */
81         if (Tok != TOK_NAMESPACE) {
82             SB_Terminate (ScopeName);
83             return CurrentScope;
84         }
85
86         /* Pass the scope back to the caller */
87         SB_AppendStr (ScopeName, Name);
88
89         /* The scope must exist, so search for it starting with the current
90          * scope.
91          */
92         Scope = SymFindAnyScope (CurrentScope, Name);
93         if (Scope == 0) {
94             /* Scope not found */
95             SB_Terminate (ScopeName);
96             Error ("No such scope: `%s'", SB_GetConstBuf (ScopeName));
97             return 0;
98         }
99
100     } else {
101
102         /* Invalid token */
103         Error ("Identifier expected");
104         SB_Terminate (ScopeName);
105         Name[0] = '\0';
106         return 0;
107
108     }
109
110     /* Skip the namespace token that follows */
111     SB_AppendStr (ScopeName, "::");
112     NextTok ();
113
114     /* Resolve scopes. */
115     while (1) {
116
117         /* Next token must be an identifier. */
118         if (Tok != TOK_IDENT) {
119             Error ("Identifier expected");
120             SB_Terminate (ScopeName);
121             Name[0] = '\0';
122             return 0;
123         }
124
125         /* Remember and skip the identifier */
126         strcpy (Name, SVal);
127         NextTok ();
128
129         /* If a namespace token follows, we search for another scope, otherwise
130          * the name is a symbol and we're done.
131          */
132         if (Tok != TOK_NAMESPACE) {
133             /* Symbol */
134             SB_Terminate (ScopeName);
135             return Scope;
136         }
137
138         /* Pass the scope back to the caller */
139         SB_AppendStr (ScopeName, Name);
140
141         /* Search for the child scope */
142         Scope = SymFindScope (Scope, Name, SYM_FIND_EXISTING);
143         if (Scope == 0) {
144             /* Scope not found */
145             SB_Terminate (ScopeName);
146             Error ("No such scope: `%s'", SB_GetConstBuf (ScopeName));
147             return 0;
148         }
149
150         /* Skip the namespace token that follows */
151         SB_AppendStr (ScopeName, "::");
152         NextTok ();
153     }
154 }
155
156
157
158 SymEntry* ParseScopedSymName (int AllocNew)
159 /* Parse a (possibly scoped) symbol name, search for it in the symbol table
160  * and return the symbol table entry.
161  */
162 {
163     StrBuf    ScopeName = AUTO_STRBUF_INITIALIZER;
164     char      Ident[sizeof (SVal)];
165     int       NoScope;
166     SymEntry* Sym;
167
168     /* Parse the scoped symbol name */
169     SymTable* Scope = ParseScopedIdent (Ident, &ScopeName);
170
171     /* If ScopeName is empty, no scope was specified */
172     NoScope = SB_IsEmpty (&ScopeName);
173
174     /* We don't need ScopeName any longer */
175     DoneStrBuf (&ScopeName);
176
177     /* Check if the scope is valid. Errors have already been diagnosed by
178      * the routine, so just exit.
179      */
180     if (Scope) {
181         /* Search for the symbol and return it. If no scope was specified,
182          * search also in the upper levels.
183          */
184         if (NoScope && !AllocNew) {
185             Sym = SymFindAny (Scope, Ident);
186         } else {
187             Sym = SymFind (Scope, Ident, AllocNew);
188         }
189     } else {
190         /* No scope ==> no symbol. To avoid errors in the calling routine that
191          * may not expect NULL to be returned if AllocNew is true, create a new
192          * symbol.
193          */
194         if (AllocNew) {
195             Sym = NewSymEntry (Ident, SF_NONE);
196         } else {
197             Sym = 0;
198         }
199     }
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 = AUTO_STRBUF_INITIALIZER;
213     char      Name[sizeof (SVal)];
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     DoneStrBuf (&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     return Scope;
239 }
240
241
242