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