1 // -*- c++ -*-
2 //                          Package   : omniidl
3 // idlscope.h               Created on: 1999/10/11
4 //			    Author    : Duncan Grisby (dpg1)
5 //
6 //    Copyright (C) 1999 AT&T Laboratories Cambridge
7 //
8 //  This file is part of omniidl.
9 //
10 //  omniidl is free software; you can redistribute it and/or modify it
11 //  under the terms of the GNU General Public License as published by
12 //  the Free Software Foundation; either version 2 of the License, or
13 //  (at your option) any later version.
14 //
15 //  This program is distributed in the hope that it will be useful,
16 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
17 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18 //  General Public License for more details.
19 //
20 //  You should have received a copy of the GNU General Public License
21 //  along with this program.  If not, see http://www.gnu.org/licenses/
22 //
23 // Description:
24 //
25 //   Definitions for scope manipulation
26 
27 #ifndef _idlscope_h_
28 #define _idlscope_h_
29 
30 #include <idlutil.h>
31 
32 
33 // Class to represent an absolute or relative scoped name as a list.
34 class ScopedName {
35 public:
36 
37   class Fragment {
38   public:
39     // Constructor copies identifier
Fragment(const char * identifier)40     Fragment(const char* identifier) :
41       next_(0), identifier_(idl_strdup(identifier)) {}
42 
~Fragment()43     ~Fragment() {
44       delete [] identifier_;
45     }
46 
identifier()47     inline const char* identifier() const { return identifier_; }
next()48     inline Fragment*   next()       const { return next_; };
49 
50   protected:
51     Fragment* next_;
52 
53   private:
54     char* identifier_;
55 
56     friend class ScopedName;
57   };
58 
59   ScopedName(const char* identifier, IDL_Boolean absolute);
60 
61   // Copy constructors
62   ScopedName(const ScopedName* sn);
63   ScopedName(const Fragment*   frags, IDL_Boolean absolute);
64 
65   ~ScopedName();
66 
67   // Return the scope list
scopeList()68   Fragment* scopeList() const { return scopeList_; }
69 
70   // Is the name absolute (i.e. ::A::... rather than A::...)
absolute()71   IDL_Boolean absolute() const { return absolute_; }
72 
73   // toString() returns a new string containing the stringified
74   // name. The caller is responsible for deleting it. If qualify is
75   // true, and the name is absolute, prefix with ::, otherwise do not.
76   char* toString(IDL_Boolean qualify=0) const;
77 
78   IDL_Boolean equal(const ScopedName* sn) const;
79 
80   // Append a new fragment
81   void append(const char* identifier);
82 
83 private:
84   Fragment*      scopeList_;
85   Fragment*      last_;
86   IDL_Boolean    absolute_;
87 };
88 
89 
90 // Class to represent a scope
91 
92 class Decl;
93 class IdlType;
94 class InheritSpec;
95 class ValueInheritSpec;
96 
97 class Scope {
98 public:
99 
100   class Entry;			// Entry in a scope
101   class EntryList;		// Linked list of entries
102 
103   enum Kind { S_GLOBAL, S_MODULE, S_INTERFACE, S_STRUCT, S_EXCEPTION,
104 	      S_UNION, S_OPERATION, S_VALUE };
105 
106   // Static functions to return the current and global scopes
global()107   static Scope* global()  { return global_; }
current()108   static Scope* current() { return current_; }
109 
110   // Static functions to initialise and clear the global and CORBA:: scopes
111   static void init();
112   static void clear();
113 
114   // Functions to create new sub-scopes of the current scope. If
115   // newModuleScope() is asked to create a module scope which already
116   // exists, it re-opens the existing scope.
117   Scope* newModuleScope   (const char* identifier, const char* file, int line);
118   Scope* newInterfaceScope(const char* identifier, const char* file, int line);
119   Scope* newStructScope   (const char* identifier, const char* file, int line);
120   Scope* newExceptionScope(const char* identifier, const char* file, int line);
121   Scope* newUnionScope    (const char* identifier, const char* file, int line);
122   Scope* newOperationScope(const char* file, int line);
123   Scope* newValueScope    (const char* identifier, const char* file, int line);
124 
125   // Change the current scope
126   static void startScope(Scope* s);
127   static void endScope();
128 
129   // Create an unnamed or named scope. If the nestedUse flag is true,
130   // use of identifiers in child scopes are considered uses within
131   // this scope. This is true for scopes created by interfaces and
132   // valuetypes, but not those created by modules. If the parent scope
133   // has nestedUse true, this scope sets it too.
134   Scope(Scope* parent, Kind k, IDL_Boolean nestedUse,
135 	const char* file, int line);
136   Scope(Scope* parent, const char* identifier,
137 	Kind k, IDL_Boolean nestedUse,
138 	const char* file, int line);
139 
140   ~Scope();
141 
142   // For interfaces, set a list of inherited Scopes. Checks that
143   // inheritance has not added any clashing operation or attribute
144   // names.
145   void setInherited(InheritSpec*      inherited, const char* file, int line);
146   void setInherited(ValueInheritSpec* inherited, const char* file, int line);
147 
148   // Query interface
parent()149   Scope*            parent()     const { return parent_; }
kind()150   Kind              kind()       const { return kind_; }
identifier()151   const char*       identifier() const { return identifier_; }
scopedName()152   const ScopedName* scopedName() const { return scopedName_; }
nestedUse()153   IDL_Boolean       nestedUse()  const { return nestedUse_; }
entries()154   Entry*            entries()    const { return entries_; }
155 
156   // Functions to lookup and add entries to the scope, reporting any
157   // violations of the IDL scope rules as errors.
158 
159   // Find an entry in this scope.
160   Entry* find(const char* identifier) const;
161 
162   // Find an entry in this scope, ignoring case
163   Entry* iFind(const char* identifier) const;
164 
165   // Find entries in this scope or inherited scopes. Does not return
166   // USE or PARENT entries.
167   EntryList* findWithInheritance(const char* identifier) const;
168   EntryList* iFindWithInheritance(const char* identifier) const;
169 
170   // Find an entry based on a ScopedName. File and line requesting the
171   // find are given so errors can be reported nicely. If file and line
172   // are zero, do not report errors.
173   const Entry* findScopedName(const ScopedName* sn,
174 			      const char* file = 0, int line = 0) const;
175 
176   // Find an entry based on a ScopedName, and mark it as used in this
177   // scope (and any parent scopes with nestedUse true).
178   const Entry* findForUse(const ScopedName* sn, const char* file, int line);
179 
180   void addUse(const ScopedName* sn, const char* file, int line);
181 
182   // Given source and destination ScopedNames, construct a relative or
183   // absolute ScopedName which uniquely identifies the destination
184   // from within the scope of the source. Returns 0 if either scoped
185   // name does not exist, or is not absolute.
186   static ScopedName* relativeScopedName(const ScopedName* from,
187 					const ScopedName* to);
188 
189 
190   // The following add functions take identifiers with _ escape
191   // characters intact, so they can properly detect clashes with
192   // keywords.
193 
194   // Add a module, or do nothing if the module was already added
195   void addModule(const char* identifier,
196 		 Scope* scope,
197 		 Decl* decl,
198 		 const char* file, int line);
199 
200   // Add a declaration
201   void addDecl(const char* identifier,
202 	       Scope*      scope,   // Scope formed by this declaration, if any
203 	       Decl*       decl,    // Decl object for this declaration
204 	       IdlType*    idltype, // IdlType for this declaration
205 	       const char* file, int line);
206 
207   // Add an operation or attribute
208   void addCallable(const char* identifier, Scope* scope, Decl* decl,
209 		   const char* file, int line);
210 
211   // Add an inherited operation or attribute
212   void addInherited(const char* identifier, Scope* scope, Decl* decl,
213 		    Entry* inh_from, const char* file, int line);
214 
215   // Add an instance
216   void addInstance(const char* identifier,
217 		   Decl* decl,	      // Declaration of the instance
218 		   IdlType* idltype,  // Type of the instance
219 		   const char* file, int line);
220 
221   // Remove an entry. Only used to remove a forward declared interface
222   // when the full definition comes along.
223   void remEntry(Entry* e);
224 
225   class Entry {
226   public:
227 
228     enum EntryKind {
229       E_MODULE,			// Module
230       E_DECL,			// Declaration
231       E_CALLABLE,		// Operation or attribute
232       E_INHERITED,		// Inherited callable
233       E_INSTANCE,		// Instance of a type
234       E_USE,			// Identifier introduced through use
235       E_PARENT			// Name of enclosing scope
236     };
237 
238     Entry(const Scope* container, EntryKind kind, const char* identifier,
239 	  Scope* scope, Decl* decl, IdlType* idltype, Entry* inh_from,
240 	  const char* file, int line);
241 
242     ~Entry();
243 
container()244     const Scope*      container()  const { return container_; }
kind()245     EntryKind         kind()       const { return kind_; }
identifier()246     const char*       identifier() const { return identifier_; }
scopedName()247     const ScopedName* scopedName() const { return scopedName_; }
file()248     const char*       file()       const { return file_; }
line()249     int               line()       const { return line_; }
250 
251     // Scope, Decl, IdlType, and Entry inherited from, if appropriate,
252     // null if not
scope()253     Scope*            scope()      const { return scope_; }
decl()254     Decl*             decl()       const { return decl_; }
idltype()255     IdlType*          idltype()    const { return idltype_; }
inh_from()256     Entry*            inh_from()   const { return inh_from_; }
257 
258     // Linked list inside Scope
next()259     Entry*            next()       const { return next_; }
260 
261   private:
262     const Scope*      container_;
263     EntryKind         kind_;
264     char*             identifier_;
265     ScopedName*       scopedName_;
266     Scope*            scope_;
267     Decl*             decl_;
268     IdlType*          idltype_;
269     Entry*            inh_from_;
270     char*             file_;
271     int               line_;
272     Entry*            next_;
273 
274     friend class Scope;
275   };
276 
277   class EntryList {
278   public:
EntryList(const Entry * e)279     EntryList(const Entry* e) : head_(e), next_(0) { last_ = this; }
280 
~EntryList()281     ~EntryList() { if (next_) delete next_; }
282 
head()283     const Entry* head() const { return head_; }
tail()284     EntryList*   tail() const { return next_; }
285 
append(EntryList * el)286     void append(EntryList* el) {
287       last_->next_ = el;
288       last_        = el->last_;
289     }
290     void merge(EntryList* ml);
291 
292   private:
293     const Entry* head_;
294 
295   protected:
296     EntryList* next_;
297     EntryList* last_;
298   };
299 
300 private:
301   Scope*            parent_;
302   Kind              kind_;
303   char*             identifier_;
304   ScopedName*       scopedName_;
305   IDL_Boolean       nestedUse_;
306   Entry*            entries_;
307   Entry*            last_;
308   InheritSpec*      inherited_;
309   ValueInheritSpec* valueInherited_;
310 
311   static Scope*     global_;
312   static Scope*     current_;
313 
314   void appendEntry(Entry* e);
315   IDL_Boolean keywordClash(const char* identifier,
316 			   const char* file, int line);
317 };
318 
319 #endif // _idlscope_h_
320