1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_idlc.hxx"
26 #include <idlc/astscope.hxx>
27 #include <idlc/astbasetype.hxx>
28 #ifndef _IDLC_ASTINERFACE_HXX_
29 #include <idlc/astinterface.hxx>
30 #endif
31 #include <idlc/errorhandler.hxx>
32
33
34 using namespace ::rtl;
35
isGlobal(const OString & scopedName)36 sal_Bool isGlobal(const OString& scopedName)
37 {
38 if ((scopedName.getLength() == 0) || (scopedName.indexOf(':') == 0))
39 {
40 return sal_True;
41 }
42 return sal_False;
43 }
44
AstScope(NodeType nodeType)45 AstScope::AstScope(NodeType nodeType)
46 : m_nodeType(nodeType)
47 {
48
49 }
50
~AstScope()51 AstScope::~AstScope()
52 {
53
54 }
55
addDeclaration(AstDeclaration * pDecl)56 AstDeclaration* AstScope::addDeclaration(AstDeclaration* pDecl)
57 {
58 AstDeclaration* pDeclaration = NULL;
59
60 if ((pDeclaration = lookupForAdd(pDecl)) != NULL)
61 {
62 if (pDecl->getNodeType() == NT_union_branch )
63 {
64 m_declarations.push_back(pDecl);
65 return pDecl;
66 }
67 if ( pDecl->hasAncestor(pDeclaration) )
68 {
69 idlc()->error()->error2(EIDL_REDEF_SCOPE, pDecl, pDeclaration);
70 return NULL;
71 }
72 if ( (pDecl->getNodeType() == pDeclaration->getNodeType()) &&
73 (pDecl->getNodeType() == NT_sequence
74 || pDecl->getNodeType() == NT_array
75 || pDecl->getNodeType() == NT_instantiated_struct) )
76 {
77 return pDeclaration;
78 }
79 if ( (pDeclaration->getNodeType() == NT_interface)
80 && (pDecl->getNodeType() == NT_interface)
81 && !((AstInterface*)pDeclaration)->isDefined() )
82 {
83 m_declarations.push_back(pDecl);
84 return pDecl;
85 }
86 if ( (NT_service == m_nodeType) &&
87 ( ((pDecl->getNodeType() == NT_interface_member)
88 && (pDeclaration->getNodeType() == NT_interface)) ||
89 ((pDecl->getNodeType() == NT_service_member)
90 && (pDeclaration->getNodeType() == NT_service)) )
91 )
92 {
93 m_declarations.push_back(pDecl);
94 return pDecl;
95 }
96
97 idlc()->error()->error2(EIDL_REDEF_SCOPE, scopeAsDecl(this), pDecl);
98 return NULL;
99 }
100
101 m_declarations.push_back(pDecl);
102 return pDecl;
103 }
104
getNodeCount(NodeType nodeType)105 sal_uInt16 AstScope::getNodeCount(NodeType nodeType)
106 {
107 DeclList::const_iterator iter = getIteratorBegin();
108 DeclList::const_iterator end = getIteratorEnd();
109 AstDeclaration* pDecl = NULL;
110 sal_uInt16 count = 0;
111
112 while ( iter != end )
113 {
114 pDecl = *iter;
115 if ( pDecl->getNodeType() == nodeType )
116 count++;
117 ++iter;
118 }
119 return count;
120 }
121
lookupByName(const OString & scopedName)122 AstDeclaration* AstScope::lookupByName(const OString& scopedName)
123 {
124 AstDeclaration* pDecl = NULL;
125 AstScope* pScope = NULL;
126 if (scopedName.getLength() == 0)
127 return NULL;
128
129 // If name starts with "::" start look up in global scope
130 if ( isGlobal(scopedName) )
131 {
132 pDecl = scopeAsDecl(this);
133 if ( !pDecl )
134 return NULL;
135
136 pScope = pDecl->getScope();
137 // If this is the global scope ...
138 if ( !pScope )
139 {
140 // look up the scopedName part after "::"
141 OString subName = scopedName.copy(2);
142 pDecl = lookupByName(subName);
143 return pDecl;
144 //return pScope->lookupByName();
145 }
146 // OK, not global scope yet, so simply iterate with parent scope
147 pDecl = pScope->lookupByName(scopedName);
148 return pDecl;
149 }
150
151 // The name does not start with "::"
152 // Look up in the local scope and start with the first scope
153 sal_Int32 nIndex = scopedName.indexOf(':');
154 OString firstScope = nIndex > 0 ? scopedName.copy(0, nIndex) : scopedName;
155 sal_Bool bFindFirstScope = sal_True;
156 pDecl = lookupByNameLocal(firstScope);
157 if ( !pDecl )
158 {
159 bFindFirstScope = sal_False;
160
161 // OK, not found. Go down parent scope chain
162 pDecl = scopeAsDecl(this);
163 if ( pDecl )
164 {
165 pScope = pDecl->getScope();
166 if ( pScope )
167 pDecl = pScope->lookupByName(scopedName);
168 else
169 pDecl = NULL;
170
171 // Special case for scope which is an interface. We
172 // have to look in the inherited interfaces as well.
173 if ( !pDecl )
174 {
175 if (m_nodeType == NT_interface)
176 pDecl = lookupInInherited(scopedName);
177 }
178 }
179 }
180
181 if ( bFindFirstScope && (firstScope != scopedName) )
182 {
183 sal_Int32 i = 0;
184 sal_Int32 nOffset = 2;
185 do
186 {
187 pScope = declAsScope(pDecl);
188 if( pScope )
189 {
190 pDecl = pScope->lookupByNameLocal(scopedName.getToken(nOffset, ':', i ));
191 nOffset = 1;
192 }
193 if( !pDecl )
194 break;
195 } while( i != -1 );
196
197 if ( !pDecl )
198 {
199 // last try if is not the global scope and the scopeName isn't specify global too
200 pDecl = scopeAsDecl(this);
201 if ( pDecl && (pDecl->getLocalName() != "") )
202 {
203 pScope = pDecl->getScope();
204 if ( pScope )
205 pDecl = pScope->lookupByName(scopedName);
206 } else
207 {
208 pDecl = NULL;
209 }
210 }
211
212 }
213
214 return pDecl;
215 }
216
lookupByNameLocal(const OString & name) const217 AstDeclaration* AstScope::lookupByNameLocal(const OString& name) const
218 {
219 DeclList::const_iterator iter(m_declarations.begin());
220 DeclList::const_iterator end(m_declarations.end());
221 AstDeclaration* pDecl = NULL;
222
223 while ( iter != end )
224 {
225 pDecl = *iter;
226 if ( pDecl->getLocalName() == name )
227 return pDecl;
228 ++iter;
229 }
230 return NULL;
231 }
232
lookupInInherited(const OString & scopedName) const233 AstDeclaration* AstScope::lookupInInherited(const OString& scopedName) const
234 {
235 AstInterface* pInterface = (AstInterface*)this;
236
237 if ( !pInterface )
238 return NULL;
239
240 // Can't look in an interface which was not yet defined
241 if ( !pInterface->getScope() )
242 {
243 idlc()->error()->forwardLookupError(pInterface, scopedName);
244 }
245
246 // OK, loop through inherited interfaces. Stop when you find it
247 AstInterface::InheritedInterfaces::const_iterator iter(
248 pInterface->getAllInheritedInterfaces().begin());
249 AstInterface::InheritedInterfaces::const_iterator end(
250 pInterface->getAllInheritedInterfaces().end());
251 while ( iter != end )
252 {
253 AstInterface const * resolved = iter->getResolved();
254 AstDeclaration* pDecl = resolved->lookupByNameLocal(scopedName);
255 if ( pDecl )
256 return pDecl;
257 pDecl = resolved->lookupInInherited(scopedName);
258 if ( pDecl )
259 return pDecl;
260 ++iter;
261 }
262 // Not found
263 return NULL;
264 }
265
lookupPrimitiveType(ExprType type)266 AstDeclaration* AstScope::lookupPrimitiveType(ExprType type)
267 {
268 AstDeclaration* pDecl = NULL;
269 AstScope* pScope = NULL;
270 AstBaseType* pBaseType = NULL;
271 OString typeName;
272 pDecl = scopeAsDecl(this);
273 if ( !pDecl )
274 return NULL;
275 pScope = pDecl->getScope();
276 if ( pScope)
277 return pScope->lookupPrimitiveType(type);
278
279 switch (type)
280 {
281 case ET_none:
282 OSL_ASSERT(false);
283 break;
284 case ET_short:
285 typeName = OString("short");
286 break;
287 case ET_ushort:
288 typeName = OString("unsigned short");
289 break;
290 case ET_long:
291 typeName = OString("long");
292 break;
293 case ET_ulong:
294 typeName = OString("unsigned long");
295 break;
296 case ET_hyper:
297 typeName = OString("hyper");
298 break;
299 case ET_uhyper:
300 typeName = OString("unsigned hyper");
301 break;
302 case ET_float:
303 typeName = OString("float");
304 break;
305 case ET_double:
306 typeName = OString("double");
307 break;
308 case ET_char:
309 typeName = OString("char");
310 break;
311 case ET_byte:
312 typeName = OString("byte");
313 break;
314 case ET_boolean:
315 typeName = OString("boolean");
316 break;
317 case ET_any:
318 typeName = OString("any");
319 break;
320 case ET_void:
321 typeName = OString("void");
322 break;
323 case ET_type:
324 typeName = OString("type");
325 break;
326 case ET_string:
327 typeName = OString("string");
328 break;
329 }
330
331 pDecl = lookupByNameLocal(typeName);
332
333 if ( pDecl && (pDecl->getNodeType() == NT_predefined) )
334 {
335 pBaseType = (AstBaseType*)pDecl;
336
337 if ( pBaseType->getExprType() == type )
338 return pDecl;
339 }
340
341 return NULL;
342 }
343
lookupForAdd(AstDeclaration * pDecl)344 AstDeclaration* AstScope::lookupForAdd(AstDeclaration* pDecl)
345 {
346 if ( !pDecl )
347 return NULL;
348
349 AstDeclaration* pRetDecl = lookupByNameLocal(pDecl->getLocalName());
350
351 return pRetDecl;
352 }
353