xref: /aoo41x/main/idlc/source/astinterface.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/astinterface.hxx>
31 #include <idlc/astattribute.hxx>
32 #include <idlc/astoperation.hxx>
33 #include "idlc/idlc.hxx"
34 
35 #include "registry/version.h"
36 #include "registry/writer.hxx"
37 
38 using namespace ::rtl;
39 
40 AstInterface::AstInterface(const ::rtl::OString& name,
41 						   AstInterface const * pInherits,
42 						   AstScope* pScope)
43 	: AstType(NT_interface, name, pScope)
44 	, AstScope(NT_interface)
45     , m_mandatoryInterfaces(0)
46     , m_bIsDefined(false)
47 	, m_bForwarded(sal_False)
48 	, m_bForwardedInSameFile(sal_False)
49     , m_bSingleInheritance(pInherits != 0)
50 {
51     if (pInherits != 0) {
52         addInheritedInterface(pInherits, false, rtl::OUString());
53     }
54 }
55 
56 AstInterface::~AstInterface()
57 {
58 }
59 
60 AstInterface::DoubleDeclarations AstInterface::checkInheritedInterfaceClashes(
61     AstInterface const * ifc, bool optional) const
62 {
63     DoubleDeclarations doubleDecls;
64     std::set< rtl::OString > seen;
65     checkInheritedInterfaceClashes(
66         doubleDecls, seen, ifc, true, optional, optional);
67     return doubleDecls;
68 }
69 
70 void AstInterface::addInheritedInterface(
71     AstType const * ifc, bool optional, rtl::OUString const & documentation)
72 {
73     m_inheritedInterfaces.push_back(
74         InheritedInterface(ifc, optional, documentation));
75     if (!optional) {
76         ++m_mandatoryInterfaces;
77     }
78     AstInterface const * resolved = resolveInterfaceTypedefs(ifc);
79     addVisibleInterface(resolved, true, optional);
80     if (optional) {
81         addOptionalVisibleMembers(resolved);
82     }
83 }
84 
85 AstInterface::DoubleMemberDeclarations AstInterface::checkMemberClashes(
86     AstDeclaration const * member) const
87 {
88     DoubleMemberDeclarations doubleMembers;
89     checkMemberClashes(doubleMembers, member, true);
90     return doubleMembers;
91 }
92 
93 void AstInterface::addMember(AstDeclaration /*TODO: const*/ * member) {
94     addDeclaration(member);
95     m_visibleMembers.insert(
96         VisibleMembers::value_type(
97             member->getLocalName(), VisibleMember(member)));
98 }
99 
100 void AstInterface::forwardDefined(AstInterface const & def)
101 {
102     setImported(def.isImported());
103     setInMainfile(def.isInMainfile());
104     setLineNumber(def.getLineNumber());
105     setFileName(def.getFileName());
106     setDocumentation(def.getDocumentation());
107     m_inheritedInterfaces = def.m_inheritedInterfaces;
108     m_mandatoryInterfaces = def.m_mandatoryInterfaces;
109     m_bIsDefined = true;
110 }
111 
112 sal_Bool AstInterface::dump(RegistryKey& rKey)
113 {
114 	if ( !isDefined() )
115 		return sal_True;
116 
117 	RegistryKey localKey;
118 	if (rKey.createKey( OStringToOUString(getFullName(), RTL_TEXTENCODING_UTF8 ), localKey))
119 	{
120 		fprintf(stderr, "%s: warning, could	not create key '%s' in '%s'\n",
121 			    idlc()->getOptions()->getProgramName().getStr(),
122 			    getFullName().getStr(), OUStringToOString(rKey.getRegistryName(), RTL_TEXTENCODING_UTF8).getStr());
123 		return sal_False;
124 	}
125 
126     if (m_mandatoryInterfaces > SAL_MAX_UINT16
127         || m_inheritedInterfaces.size() - m_mandatoryInterfaces
128             > SAL_MAX_UINT16)
129     {
130         fprintf(
131             stderr, "%s: interface %s has too many direct base interfaces\n",
132             idlc()->getOptions()->getProgramName().getStr(),
133             getScopedName().getStr());
134         return false;
135     }
136     sal_uInt16 nBaseTypes = static_cast< sal_uInt16 >(m_mandatoryInterfaces);
137 	sal_uInt16 nAttributes = 0;
138 	sal_uInt16 nMethods = 0;
139     sal_uInt16 nReferences = static_cast< sal_uInt16 >(
140         m_inheritedInterfaces.size() - m_mandatoryInterfaces);
141     typereg_Version version
142         = (nBaseTypes <= 1 && nReferences == 0 && !m_bPublished
143            ? TYPEREG_VERSION_0 : TYPEREG_VERSION_1);
144     {for (DeclList::const_iterator i(getIteratorBegin()); i != getIteratorEnd();
145           ++i)
146     {
147         switch ((*i)->getNodeType()) {
148         case NT_attribute:
149             {
150                 if (!increment(&nAttributes, "attributes")) {
151                     return false;
152                 }
153 //                AstAttribute * attr = static_cast< AstAttribute * >(*i);
154                 AstAttribute * attr = (AstAttribute *)(*i);
155                 if (attr->isBound()) {
156                     version = TYPEREG_VERSION_1;
157                 }
158                 DeclList::size_type getCount = attr->getGetExceptionCount();
159                 if (getCount > SAL_MAX_UINT16) {
160                     fprintf(
161                         stderr,
162                         ("%s: raises clause of getter for attribute %s of"
163                          " interface %s is too long\n"),
164                         idlc()->getOptions()->getProgramName().getStr(),
165                         (*i)->getLocalName().getStr(),
166                         getScopedName().getStr());
167                     return false;
168                 }
169                 if (getCount > 0) {
170                     version = TYPEREG_VERSION_1;
171                     if (!increment(&nMethods, "attributes")) {
172                         return false;
173                     }
174                 }
175                 DeclList::size_type setCount = attr->getSetExceptionCount();
176                 if (setCount > SAL_MAX_UINT16) {
177                     fprintf(
178                         stderr,
179                         ("%s: raises clause of setter for attribute %s of"
180                          " interface %s is too long\n"),
181                         idlc()->getOptions()->getProgramName().getStr(),
182                         (*i)->getLocalName().getStr(),
183                         getScopedName().getStr());
184                     return false;
185                 }
186                 if (setCount > 0) {
187                     version = TYPEREG_VERSION_1;
188                     if (!increment(&nMethods, "attributes")) {
189                         return false;
190                     }
191                 }
192                 break;
193             }
194 
195         case NT_operation:
196             if (!increment(&nMethods, "methods")) {
197                 return false;
198             }
199             break;
200 
201         default:
202             OSL_ASSERT(false);
203             break;
204         }
205     }}
206 
207     OUString emptyStr;
208 	typereg::Writer aBlob(
209         version, getDocumentation(), emptyStr, RT_TYPE_INTERFACE, m_bPublished,
210         OStringToOUString(getRelativName(), RTL_TEXTENCODING_UTF8), nBaseTypes,
211         nAttributes, nMethods, nReferences);
212 
213     sal_uInt16 superTypeIndex = 0;
214     sal_uInt16 referenceIndex = 0;
215     {for (InheritedInterfaces::iterator i = m_inheritedInterfaces.begin();
216           i != m_inheritedInterfaces.end(); ++i)
217     {
218         if (i->isOptional()) {
219             aBlob.setReferenceData(
220                 referenceIndex++, i->getDocumentation(), RT_REF_SUPPORTS,
221                 RT_ACCESS_OPTIONAL,
222                 OStringToOUString(
223                     i->getInterface()->getRelativName(),
224                     RTL_TEXTENCODING_UTF8));
225         } else {
226             aBlob.setSuperTypeName(
227                 superTypeIndex++,
228                 OStringToOUString(
229                     i->getInterface()->getRelativName(),
230                     RTL_TEXTENCODING_UTF8));
231         }
232     }}
233 
234     sal_uInt16 attributeIndex = 0;
235     sal_uInt16 methodIndex = 0;
236     {for (DeclList::const_iterator i(getIteratorBegin()); i != getIteratorEnd();
237           ++i)
238     {
239         switch ((*i)->getNodeType()) {
240         case NT_attribute:
241 //           static_cast< AstAttribute * >(*i)->dumpBlob(
242 
243             ((AstAttribute *)(*i))->dumpBlob(
244                 aBlob, attributeIndex++, &methodIndex);
245             break;
246 
247         case NT_operation:
248 //            static_cast< AstOperation * >(*i)->dumpBlob(aBlob, methodIndex++);
249             ((AstOperation *)(*i))->dumpBlob(aBlob, methodIndex++);
250             break;
251 
252         default:
253             OSL_ASSERT(false);
254             break;
255         }
256     }}
257 
258     sal_uInt32 aBlobSize;
259     void const * pBlob = aBlob.getBlob(&aBlobSize);
260 
261 	if (localKey.setValue(emptyStr, RG_VALUETYPE_BINARY, (RegValue)pBlob, aBlobSize))
262 	{
263 		fprintf(stderr, "%s: warning, could	not set value of key \"%s\" in %s\n",
264 			    idlc()->getOptions()->getProgramName().getStr(),
265 				getFullName().getStr(), OUStringToOString(localKey.getRegistryName(), RTL_TEXTENCODING_UTF8).getStr());
266 		return sal_False;
267 	}
268 
269 	return true;
270 }
271 
272 void AstInterface::checkInheritedInterfaceClashes(
273     DoubleDeclarations & doubleDeclarations,
274     std::set< rtl::OString > & seenInterfaces, AstInterface const * ifc,
275     bool direct, bool optional, bool mainOptional) const
276 {
277     if (direct || optional
278         || seenInterfaces.insert(ifc->getScopedName()).second)
279     {
280         VisibleInterfaces::const_iterator visible(
281             m_visibleInterfaces.find(ifc->getScopedName()));
282         if (visible != m_visibleInterfaces.end()) {
283             switch (visible->second) {
284             case INTERFACE_INDIRECT_OPTIONAL:
285                 if (direct && optional) {
286                     doubleDeclarations.interfaces.push_back(ifc);
287                     return;
288                 }
289                 break;
290 
291             case INTERFACE_DIRECT_OPTIONAL:
292                 if (direct || !mainOptional) {
293                     doubleDeclarations.interfaces.push_back(ifc);
294                 }
295                 return;
296 
297             case INTERFACE_INDIRECT_MANDATORY:
298                 if (direct) {
299                     doubleDeclarations.interfaces.push_back(ifc);
300                 }
301                 return;
302 
303             case INTERFACE_DIRECT_MANDATORY:
304                 if (direct || (!optional && !mainOptional)) {
305                     doubleDeclarations.interfaces.push_back(ifc);
306                 }
307                 return;
308             }
309         }
310         if (direct || !optional) {
311             {for (DeclList::const_iterator i(ifc->getIteratorBegin());
312                   i != ifc->getIteratorEnd(); ++i)
313             {
314                 checkMemberClashes(
315                     doubleDeclarations.members, *i, !mainOptional);
316             }}
317             {for (InheritedInterfaces::const_iterator i(
318                       ifc->m_inheritedInterfaces.begin());
319                   i != ifc->m_inheritedInterfaces.end(); ++i)
320             {
321                 checkInheritedInterfaceClashes(
322                     doubleDeclarations, seenInterfaces, i->getResolved(),
323                     false, i->isOptional(), mainOptional);
324             }}
325         }
326     }
327 }
328 
329 void AstInterface::checkMemberClashes(
330     DoubleMemberDeclarations & doubleMembers, AstDeclaration const * member,
331     bool checkOptional) const
332 {
333     VisibleMembers::const_iterator i(
334         m_visibleMembers.find(member->getLocalName()));
335     if (i != m_visibleMembers.end()) {
336         if (i->second.mandatory != 0) {
337             if (i->second.mandatory->getScopedName() != member->getScopedName())
338             {
339                 DoubleMemberDeclaration d;
340                 d.first = i->second.mandatory;
341                 d.second = member;
342                 doubleMembers.push_back(d);
343             }
344         } else if (checkOptional) {
345             for (VisibleMember::Optionals::const_iterator j(
346                      i->second.optionals.begin());
347                  j != i->second.optionals.end(); ++j)
348             {
349                 if (j->second->getScopedName() != member->getScopedName()) {
350                     DoubleMemberDeclaration d;
351                     d.first = j->second;
352                     d.second = member;
353                     doubleMembers.push_back(d);
354                 }
355             }
356         }
357     }
358 }
359 
360 void AstInterface::addVisibleInterface(
361     AstInterface const * ifc, bool direct, bool optional)
362 {
363     InterfaceKind kind = optional
364         ? direct ? INTERFACE_DIRECT_OPTIONAL : INTERFACE_INDIRECT_OPTIONAL
365         : direct ? INTERFACE_DIRECT_MANDATORY : INTERFACE_INDIRECT_MANDATORY;
366     std::pair< VisibleInterfaces::iterator, bool > result(
367         m_visibleInterfaces.insert(
368             VisibleInterfaces::value_type(ifc->getScopedName(), kind)));
369     bool seen = !result.second
370         && result.first->second >= INTERFACE_INDIRECT_MANDATORY;
371     if (!result.second && kind > result.first->second) {
372         result.first->second = kind;
373     }
374     if (!optional && !seen) {
375         {for (DeclList::const_iterator i(ifc->getIteratorBegin());
376               i != ifc->getIteratorEnd(); ++i)
377         {
378             m_visibleMembers.insert(
379                 VisibleMembers::value_type(
380                     (*i)->getLocalName(), VisibleMember(*i)));
381         }}
382         {for (InheritedInterfaces::const_iterator i(
383                   ifc->m_inheritedInterfaces.begin());
384               i != ifc->m_inheritedInterfaces.end(); ++i)
385         {
386             addVisibleInterface(i->getResolved(), false, i->isOptional());
387         }}
388     }
389 }
390 
391 void AstInterface::addOptionalVisibleMembers(AstInterface const * ifc) {
392     {for (DeclList::const_iterator i(ifc->getIteratorBegin());
393           i != ifc->getIteratorEnd(); ++i)
394     {
395         VisibleMembers::iterator visible(
396             m_visibleMembers.find((*i)->getLocalName()));
397         if (visible == m_visibleMembers.end()) {
398             visible = m_visibleMembers.insert(
399                 VisibleMembers::value_type(
400                     (*i)->getLocalName(), VisibleMember())).first;
401         }
402         if (visible->second.mandatory == 0) {
403             visible->second.optionals.insert(
404                 VisibleMember::Optionals::value_type(ifc->getScopedName(), *i));
405         }
406     }}
407     {for (InheritedInterfaces::const_iterator i(
408               ifc->m_inheritedInterfaces.begin());
409           i != ifc->m_inheritedInterfaces.end(); ++i)
410     {
411         if (!i->isOptional()) {
412             addOptionalVisibleMembers(i->getResolved());
413         }
414     }}
415 }
416 
417 bool AstInterface::increment(sal_uInt16 * counter, char const * sort) const {
418     if (*counter == SAL_MAX_UINT16) {
419         fprintf(
420             stderr, "%s: interface %s has too many direct %s\n",
421             idlc()->getOptions()->getProgramName().getStr(),
422             getScopedName().getStr(), sort);
423         return false;
424     }
425     ++*counter;
426     return true;
427 }
428