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_codemaker.hxx"
30 
31 #include "includes.hxx"
32 
33 #include "dumputils.hxx"
34 
35 #include "codemaker/dependencies.hxx"
36 #include "codemaker/global.hxx"
37 #include "codemaker/typemanager.hxx"
38 #include "codemaker/unotype.hxx"
39 
40 #include "osl/diagnose.h"
41 #include "rtl/string.hxx"
42 #include "rtl/ustring.hxx"
43 #include "sal/types.h"
44 
45 #include <vector>
46 
47 using codemaker::cppumaker::Includes;
48 
49 Includes::Includes(
50     TypeManager const & manager, codemaker::Dependencies const & dependencies,
51     bool hpp):
52     m_manager(manager), m_map(dependencies.getMap()), m_hpp(hpp),
53     m_includeAny(dependencies.hasAnyDependency()), m_includeReference(false),
54     m_includeSequence(dependencies.hasSequenceDependency()),
55     m_includeType(dependencies.hasTypeDependency()),
56     m_includeCppuMacrosHxx(false), m_includeCppuUnotypeHxx(false),
57     m_includeOslDoublecheckedlockingH(false), m_includeOslMutexHxx(false),
58     m_includeRtlStrbufHxx(false), m_includeRtlStringH(false),
59     m_includeRtlTextencH(false), m_includeRtlUstrbufHxx(false),
60     m_includeRtlUstringH(false),
61     m_includeRtlUstringHxx(dependencies.hasStringDependency()),
62     m_includeSalTypesH(
63         dependencies.hasBooleanDependency() || dependencies.hasByteDependency()
64         || dependencies.hasShortDependency()
65         || dependencies.hasUnsignedShortDependency()
66         || dependencies.hasLongDependency()
67         || dependencies.hasUnsignedShortDependency()
68         || dependencies.hasHyperDependency()
69         || dependencies.hasUnsignedHyperDependency()
70         || dependencies.hasCharDependency()),
71     m_includeTypelibTypeclassH(false),
72     m_includeTypelibTypedescriptionH(false)
73 {}
74 
75 Includes::~Includes()
76 {}
77 
78 void Includes::add(rtl::OString const & registryType) {
79     sal_Int32 rank;
80     std::vector< rtl::OString > args;
81     rtl::OString type(
82         codemaker::UnoType::decompose(registryType, &rank, &args));
83     if (rank > 0) {
84         m_includeSequence = true;
85     }
86     switch (codemaker::UnoType::getSort(type)) {
87     case codemaker::UnoType::SORT_VOID:
88         OSL_ASSERT(args.empty());
89         OSL_ASSERT(false);
90         break;
91 
92     case codemaker::UnoType::SORT_BOOLEAN:
93     case codemaker::UnoType::SORT_BYTE:
94     case codemaker::UnoType::SORT_SHORT:
95     case codemaker::UnoType::SORT_UNSIGNED_SHORT:
96     case codemaker::UnoType::SORT_LONG:
97     case codemaker::UnoType::SORT_UNSIGNED_LONG:
98     case codemaker::UnoType::SORT_HYPER:
99     case codemaker::UnoType::SORT_UNSIGNED_HYPER:
100     case codemaker::UnoType::SORT_CHAR:
101         OSL_ASSERT(args.empty());
102         m_includeSalTypesH = true;
103         break;
104 
105     case codemaker::UnoType::SORT_FLOAT:
106     case codemaker::UnoType::SORT_DOUBLE:
107         OSL_ASSERT(args.empty());
108         break;
109 
110     case codemaker::UnoType::SORT_STRING:
111         OSL_ASSERT(args.empty());
112         m_includeRtlUstringHxx = true;
113         break;
114 
115     case codemaker::UnoType::SORT_TYPE:
116         OSL_ASSERT(args.empty());
117         m_includeType = true;
118         break;
119 
120     case codemaker::UnoType::SORT_ANY:
121         OSL_ASSERT(args.empty());
122         m_includeAny = true;
123         break;
124 
125     case codemaker::UnoType::SORT_COMPLEX:
126         m_map.insert(
127             codemaker::Dependencies::Map::value_type(
128                 type, codemaker::Dependencies::KIND_NO_BASE));
129         {for (std::vector< rtl::OString >::iterator i(args.begin());
130               i != args.end(); ++i)
131         {
132             add(*i);
133         }}
134         break;
135 
136     default:
137         OSL_ASSERT(false);
138         break;
139     }
140 }
141 
142 namespace {
143 
144 void dumpEmptyLineBeforeFirst(FileStream & out, bool * first) {
145     OSL_ASSERT(first != 0);
146     if (*first) {
147         out << "\n";
148         *first = false;
149     }
150 }
151 
152 }
153 
154 void Includes::dump(FileStream & out, rtl::OString const * companionHdl) {
155     OSL_ASSERT(companionHdl == 0 || m_hpp);
156     if (!m_includeReference) {
157         for (codemaker::Dependencies::Map::iterator i(m_map.begin());
158              i != m_map.end(); ++i)
159         {
160             if (isInterfaceType(i->first)) {
161                 m_includeReference = true;
162                 break;
163             }
164         }
165     }
166     out << "#include \"sal/config.h\"\n";
167     if (companionHdl) {
168         out << "\n";
169         dumpInclude(out, *companionHdl, false);
170     }
171     bool first = true;
172     for (codemaker::Dependencies::Map::iterator i(m_map.begin());
173          i != m_map.end(); ++i)
174     {
175         dumpEmptyLineBeforeFirst(out, &first);
176         if (m_hpp || i->second == codemaker::Dependencies::KIND_BASE
177             || !isInterfaceType(i->first))
178         {
179             dumpInclude(out, i->first, m_hpp);
180         } else {
181             bool ns = dumpNamespaceOpen(out, i->first, false);
182             if (ns) {
183                 out << " ";
184             }
185             out << "class ";
186             dumpTypeIdentifier(out, i->first);
187             out << ";";
188             if (ns) {
189                 out << " ";
190             }
191             dumpNamespaceClose(out, i->first, false);
192             out << "\n";
193         }
194     }
195     static char const * hxxExtension[2] = { "h", "hxx" };
196     if (m_includeAny) {
197         dumpEmptyLineBeforeFirst(out, &first);
198         out << "#include \"com/sun/star/uno/Any." << hxxExtension[m_hpp] << "\"\n";
199     }
200     if (m_includeReference) {
201         dumpEmptyLineBeforeFirst(out, &first);
202         out << "#include \"com/sun/star/uno/Reference." << hxxExtension[m_hpp] << "\"\n";
203     }
204     if (m_includeSequence) {
205         dumpEmptyLineBeforeFirst(out, &first);
206         out << "#include \"com/sun/star/uno/Sequence." << hxxExtension[m_hpp] << "\"\n";
207     }
208     if (m_includeType) {
209         dumpEmptyLineBeforeFirst(out, &first);
210         out << "#include \"com/sun/star/uno/Type." << hxxExtension[m_hpp] << "\"\n";
211     }
212     if (m_includeCppuMacrosHxx) {
213         dumpEmptyLineBeforeFirst(out, &first);
214         out << ("#include \"cppu/macros.hxx\"\n");
215     }
216     if (m_includeCppuUnotypeHxx) {
217         dumpEmptyLineBeforeFirst(out, &first);
218         out << ("#include \"cppu/unotype.hxx\"\n");
219     }
220     if (m_includeOslDoublecheckedlockingH) {
221         dumpEmptyLineBeforeFirst(out, &first);
222         out << ("#include \"osl/doublecheckedlocking.h\"\n");
223     }
224     if (m_includeOslMutexHxx) {
225         dumpEmptyLineBeforeFirst(out, &first);
226         out << "#include \"osl/mutex.hxx\"\n";
227     }
228     if (m_includeRtlStrbufHxx) {
229         dumpEmptyLineBeforeFirst(out, &first);
230         out << ("#include \"rtl/strbuf.hxx\"\n");
231     }
232     if (m_includeRtlStringH) {
233         dumpEmptyLineBeforeFirst(out, &first);
234         out << "#include \"rtl/string.h\"\n";
235     }
236     if (m_includeRtlTextencH) {
237         dumpEmptyLineBeforeFirst(out, &first);
238         out << "#include \"rtl/textenc.h\"\n";
239     }
240     if (m_includeRtlUstrbufHxx) {
241         dumpEmptyLineBeforeFirst(out, &first);
242         out << ("#include \"rtl/ustrbuf.hxx\"\n");
243     }
244     if (m_includeRtlUstringH) {
245         dumpEmptyLineBeforeFirst(out, &first);
246         out << "#include \"rtl/ustring.h\"\n";
247     }
248     if (m_includeRtlUstringHxx) {
249         dumpEmptyLineBeforeFirst(out, &first);
250         out << ("#include \"rtl/ustring.hxx\"\n");
251     }
252     if (m_includeSalTypesH) {
253         dumpEmptyLineBeforeFirst(out, &first);
254         out << "#include \"sal/types.h\"\n";
255     }
256     if (m_includeTypelibTypeclassH) {
257         dumpEmptyLineBeforeFirst(out, &first);
258         out << ("#include \"typelib/typeclass.h\"\n");
259     }
260     if (m_includeTypelibTypedescriptionH) {
261         dumpEmptyLineBeforeFirst(out, &first);
262         out << ("#include \"typelib/typedescription.h\"\n");
263     }
264 }
265 
266 void Includes::dumpInclude(
267     FileStream & out, rtl::OString const & registryType, bool hpp,
268     rtl::OString const & suffix)
269 {
270     static char const * extension[2] = { "hdl", "hpp" };
271     out << "#include \"" << registryType;
272     if (suffix.getLength() > 0) {
273         out << "/" << suffix;
274     }
275     out << "." << extension[hpp] << "\"\n";
276 }
277 
278 bool Includes::isInterfaceType(rtl::OString const & registryType) const {
279     return m_manager.getTypeClass(registryType) == RT_TYPE_INTERFACE;
280 }
281