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