1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <errorhandler.hxx>
22 #include <astscope.hxx>
23 #include <astmodule.hxx>
24 #include <astservice.hxx>
25 #include <astconstants.hxx>
26 #include <astexception.hxx>
27 #include <astenum.hxx>
28 #include <astinterface.hxx>
29 #include <astoperation.hxx>
30 #include <astbasetype.hxx>
31 #include <astdeclaration.hxx>
32 #include <astparameter.hxx>
33 #include <astsequence.hxx>
34 #include <asttype.hxx>
35 #include <asttypedef.hxx>
37 #include <osl/diagnose.h>
38 #include <osl/file.hxx>
39 #include <osl/thread.h>
43 AstDeclaration
* scopeAsDecl(AstScope
* pScope
)
45 if (pScope
== nullptr) return nullptr;
47 switch( pScope
->getScopeNodeType() )
51 return static_cast<AstService
*>(pScope
);
54 return static_cast<AstModule
*>(pScope
);
56 return static_cast<AstConstants
*>(pScope
);
58 return static_cast<AstInterface
*>(pScope
);
60 return static_cast<AstOperation
*>(pScope
);
62 return static_cast<AstException
*>(pScope
);
64 return static_cast<AstStruct
*>(pScope
);
66 return static_cast<AstEnum
*>(pScope
);
72 AstScope
* declAsScope(AstDeclaration
* pDecl
)
74 if (pDecl
== nullptr) return nullptr;
76 switch(pDecl
->getNodeType())
79 return static_cast<AstInterface
*>(pDecl
);
82 return static_cast<AstService
*>(pDecl
);
85 return static_cast<AstModule
*>(pDecl
);
87 return static_cast<AstConstants
*>(pDecl
);
89 return static_cast<AstException
*>(pDecl
);
91 return static_cast<AstStruct
*>(pDecl
);
93 return static_cast<AstEnum
*>(pDecl
);
95 return static_cast<AstOperation
*>(pDecl
);
101 static void predefineXInterface(AstModule
* pRoot
)
103 // define the modules com::sun::star::uno
104 AstModule
* pParentScope
= pRoot
;
105 AstModule
* pModule
= new AstModule("com", pParentScope
);
106 pModule
->setPredefined(true);
107 pParentScope
->addDeclaration(pModule
);
108 pParentScope
= pModule
;
109 pModule
= new AstModule("sun", pParentScope
);
110 pModule
->setPredefined(true);
111 pParentScope
->addDeclaration(pModule
);
112 pParentScope
= pModule
;
113 pModule
= new AstModule("star", pParentScope
);
114 pModule
->setPredefined(true);
115 pParentScope
->addDeclaration(pModule
);
116 pParentScope
= pModule
;
117 pModule
= new AstModule("uno", pParentScope
);
118 pModule
->setPredefined(true);
119 pParentScope
->addDeclaration(pModule
);
120 pParentScope
= pModule
;
123 AstInterface
* pInterface
= new AstInterface("XInterface", nullptr, pParentScope
);
124 pInterface
->setDefined();
125 pInterface
->setPredefined(true);
126 pInterface
->setPublished();
127 pParentScope
->addDeclaration(pInterface
);
129 // define XInterface::queryInterface
130 AstOperation
* pOp
= new AstOperation(static_cast<AstType
*>(pRoot
->lookupPrimitiveType(ET_any
)),
131 "queryInterface", pInterface
);
132 AstParameter
* pParam
= new AstParameter(DIR_IN
, false,
133 static_cast<AstType
*>(pRoot
->lookupPrimitiveType(ET_type
)),
135 pOp
->addDeclaration(pParam
);
136 pInterface
->addMember(pOp
);
138 // define XInterface::acquire
139 pOp
= new AstOperation(static_cast<AstType
*>(pRoot
->lookupPrimitiveType(ET_void
)),
140 "acquire", pInterface
);
141 pInterface
->addMember(pOp
);
143 // define XInterface::release
144 pOp
= new AstOperation(static_cast<AstType
*>(pRoot
->lookupPrimitiveType(ET_void
)),
145 "release", pInterface
);
146 pInterface
->addMember(pOp
);
149 static void initializePredefinedTypes(AstModule
* pRoot
)
153 AstBaseType
* pPredefined
= new AstBaseType(ET_long
, "long", pRoot
);
154 pRoot
->addDeclaration(pPredefined
);
156 pPredefined
= new AstBaseType(ET_ulong
, "unsigned long", pRoot
);
157 pRoot
->addDeclaration(pPredefined
);
159 pPredefined
= new AstBaseType(ET_hyper
, "hyper", pRoot
);
160 pRoot
->addDeclaration(pPredefined
);
162 pPredefined
= new AstBaseType(ET_uhyper
, "unsigned hyper", pRoot
);
163 pRoot
->addDeclaration(pPredefined
);
165 pPredefined
= new AstBaseType(ET_short
, "short", pRoot
);
166 pRoot
->addDeclaration(pPredefined
);
168 pPredefined
= new AstBaseType(ET_ushort
, "unsigned short", pRoot
);
169 pRoot
->addDeclaration(pPredefined
);
171 pPredefined
= new AstBaseType(ET_float
, "float", pRoot
);
172 pRoot
->addDeclaration(pPredefined
);
174 pPredefined
= new AstBaseType(ET_double
, "double", pRoot
);
175 pRoot
->addDeclaration(pPredefined
);
177 pPredefined
= new AstBaseType(ET_char
, "char", pRoot
);
178 pRoot
->addDeclaration(pPredefined
);
180 pPredefined
= new AstBaseType(ET_byte
, "byte", pRoot
);
181 pRoot
->addDeclaration(pPredefined
);
183 pPredefined
= new AstBaseType(ET_any
, "any", pRoot
);
184 pRoot
->addDeclaration(pPredefined
);
186 pPredefined
= new AstBaseType(ET_string
, "string", pRoot
);
187 pRoot
->addDeclaration(pPredefined
);
189 pPredefined
= new AstBaseType(ET_type
, "type", pRoot
);
190 pRoot
->addDeclaration(pPredefined
);
192 pPredefined
= new AstBaseType(ET_boolean
, "boolean", pRoot
);
193 pRoot
->addDeclaration(pPredefined
);
195 pPredefined
= new AstBaseType(ET_void
, "void", pRoot
);
196 pRoot
->addDeclaration(pPredefined
);
200 Idlc::Idlc(Options
* pOptions
)
201 : m_pOptions(pOptions
)
202 , m_bIsDocValid(false)
203 , m_bIsInMainfile(true)
210 , m_parseState(PS_NoState
)
212 m_pScopes
.reset( new AstStack() );
213 // init root object after construction
215 m_bGenerateDoc
= m_pOptions
->isValid("-C");
224 m_pRoot
.reset(new AstModule(NT_root
, OString(), nullptr));
226 // push the root node on the stack
227 m_pScopes
->push(m_pRoot
.get());
228 initializePredefinedTypes(m_pRoot
.get());
229 predefineXInterface(m_pRoot
.get());
234 m_bIsDocValid
= false;
235 m_bIsInMainfile
= true;
241 m_parseState
= PS_NoState
;
244 m_mainFileName
.clear();
245 m_realFileName
.clear();
246 m_documentation
.clear();
249 m_pRoot
.reset( new AstModule(NT_root
, OString(), nullptr) );
251 // push the root node on the stack
252 m_pScopes
->push(m_pRoot
.get());
253 initializePredefinedTypes(m_pRoot
.get());
258 OUString
Idlc::processDocumentation()
262 OString
raw(getDocumentation());
263 if (m_bGenerateDoc
) {
264 doc
= OStringToOUString(raw
, RTL_TEXTENCODING_UTF8
);
265 } else if (raw
.indexOf("@deprecated") != -1) {
266 //TODO: this check is somewhat crude
273 static void lcl_writeString(::osl::File
& rFile
, ::osl::FileBase::RC
& o_rRC
,
274 OString
const& rString
)
276 sal_uInt64
nWritten(0);
277 if (::osl::FileBase::E_None
== o_rRC
) {
278 o_rRC
= rFile
.write(rString
.getStr(), rString
.getLength(), nWritten
);
279 if (static_cast<sal_uInt64
>(rString
.getLength()) != nWritten
) {
280 o_rRC
= ::osl::FileBase::E_INVAL
; //?
287 ::osl::File
& m_rFile
;
288 ::osl::FileBase::RC
& m_rRC
;
289 explicit WriteDep(::osl::File
& rFile
, ::osl::FileBase::RC
& rRC
)
290 : m_rFile(rFile
), m_rRC(rRC
) { }
291 void operator() (OString
const& rEntry
)
293 lcl_writeString(m_rFile
, m_rRC
, " \\\n ");
294 lcl_writeString(m_rFile
, m_rRC
, rEntry
);
298 // write a dummy target for one included file, so the incremental build does
299 // not break with "No rule to make target" if the included file is removed
302 ::osl::File
& m_rFile
;
303 ::osl::FileBase::RC
& m_rRC
;
304 explicit WriteDummy(::osl::File
& rFile
, ::osl::FileBase::RC
& rRC
)
305 : m_rFile(rFile
), m_rRC(rRC
) { }
306 void operator() (OString
const& rEntry
)
308 lcl_writeString(m_rFile
, m_rRC
, rEntry
);
309 lcl_writeString(m_rFile
, m_rRC
, ":\n\n");
314 Idlc::dumpDeps(OString
const& rDepFile
, OString
const& rTarget
)
317 OStringToOUString(rDepFile
, osl_getThreadTextEncoding()));
318 ::osl::FileBase::RC rc
=
319 depFile
.open(osl_File_OpenFlag_Write
| osl_File_OpenFlag_Create
);
320 if (::osl::FileBase::E_None
!= rc
) {
323 lcl_writeString(depFile
, rc
, rTarget
);
324 if (::osl::FileBase::E_None
!= rc
) {
327 lcl_writeString(depFile
, rc
, " :");
328 if (::osl::FileBase::E_None
!= rc
) {
331 m_includes
.erase(getRealFileName()); // eeek, that is a temp file...
332 ::std::for_each(m_includes
.begin(), m_includes
.end(),
333 WriteDep(depFile
, rc
));
334 lcl_writeString(depFile
, rc
, "\n\n");
335 ::std::for_each(m_includes
.begin(), m_includes
.end(),
336 WriteDummy(depFile
, rc
));
337 if (::osl::FileBase::E_None
!= rc
) {
340 rc
= depFile
.close();
341 return ::osl::FileBase::E_None
== rc
;
344 static Idlc
* pStaticIdlc
= nullptr;
351 Idlc
* setIdlc(Options
* pOptions
)
354 pStaticIdlc
= new Idlc(pOptions
);
359 AstDeclaration
const * resolveTypedefs(AstDeclaration
const * type
) {
360 if (type
!= nullptr) {
361 while (type
->getNodeType() == NT_typedef
) {
362 type
= static_cast< AstTypeDef
const * >(type
)->getBaseType();
368 AstDeclaration
const * deconstructAndResolveTypedefs(
369 AstDeclaration
const * type
, sal_Int32
* rank
)
373 if (type
== nullptr) {
376 switch (type
->getNodeType()) {
378 type
= static_cast< AstTypeDef
const * >(type
)->getBaseType();
382 type
= static_cast< AstSequence
const * >(type
)->getMemberType();
390 AstInterface
const * resolveInterfaceTypedefs(AstType
const * type
) {
391 AstDeclaration
const * decl
= resolveTypedefs(type
);
392 OSL_ASSERT(decl
->getNodeType() == NT_interface
);
393 return static_cast< AstInterface
const * >(decl
);
396 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */