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 .
20 #include <idlc/idlc.hxx>
21 #include <idlc/errorhandler.hxx>
22 #include <idlc/astscope.hxx>
23 #include <idlc/astmodule.hxx>
24 #include <idlc/astservice.hxx>
25 #include <idlc/astconstants.hxx>
26 #include <idlc/astexception.hxx>
27 #include <idlc/astunion.hxx>
28 #include <idlc/astenum.hxx>
29 #include <idlc/astinterface.hxx>
30 #include <idlc/astoperation.hxx>
31 #include <idlc/astbasetype.hxx>
32 #include "idlc/astdeclaration.hxx"
33 #include "idlc/astparameter.hxx"
34 #include "idlc/astsequence.hxx"
35 #include "idlc/asttype.hxx"
36 #include "idlc/asttypedef.hxx"
38 #include <osl/diagnose.h>
39 #include <osl/file.hxx>
40 #include <osl/thread.h>
42 using namespace ::rtl
;
44 AstDeclaration
* SAL_CALL
scopeAsDecl(AstScope
* pScope
)
46 if (pScope
== NULL
) return NULL
;
48 switch( pScope
->getScopeNodeType() )
52 return (AstService
*)(pScope
);
55 return (AstModule
*)(pScope
);
57 return (AstConstants
*)(pScope
);
59 return (AstInterface
*)(pScope
);
61 return (AstOperation
*)(pScope
);
63 return (AstException
*)(pScope
);
65 return (AstUnion
*)(pScope
);
67 return (AstStruct
*)(pScope
);
69 return (AstEnum
*)(pScope
);
75 AstScope
* SAL_CALL
declAsScope(AstDeclaration
* pDecl
)
77 if (pDecl
== NULL
) return NULL
;
79 switch(pDecl
->getNodeType())
82 return (AstInterface
*)(pDecl
);
85 return (AstService
*)(pDecl
);
88 return (AstModule
*)(pDecl
);
90 return (AstConstants
*)(pDecl
);
92 return (AstException
*)(pDecl
);
94 return (AstUnion
*)(pDecl
);
96 return (AstStruct
*)(pDecl
);
98 return (AstEnum
*)(pDecl
);
100 return (AstOperation
*)(pDecl
);
106 static void SAL_CALL
predefineXInterface(AstModule
* pRoot
)
108 // define the modules com::sun::star::uno
109 AstModule
* pParentScope
= pRoot
;
110 AstModule
* pModule
= new AstModule(OString("com"), pParentScope
);
111 pModule
->setPredefined(true);
112 pParentScope
->addDeclaration(pModule
);
113 pParentScope
= pModule
;
114 pModule
= new AstModule(OString("sun"), pParentScope
);
115 pModule
->setPredefined(true);
116 pParentScope
->addDeclaration(pModule
);
117 pParentScope
= pModule
;
118 pModule
= new AstModule(OString("star"), pParentScope
);
119 pModule
->setPredefined(true);
120 pParentScope
->addDeclaration(pModule
);
121 pParentScope
= pModule
;
122 pModule
= new AstModule(OString("uno"), pParentScope
);
123 pModule
->setPredefined(true);
124 pParentScope
->addDeclaration(pModule
);
125 pParentScope
= pModule
;
128 AstInterface
* pInterface
= new AstInterface(OString("XInterface"), NULL
, pParentScope
);
129 pInterface
->setDefined();
130 pInterface
->setPredefined(true);
131 pInterface
->setPublished();
132 pParentScope
->addDeclaration(pInterface
);
134 // define XInterface::queryInterface
135 AstOperation
* pOp
= new AstOperation((AstType
*)(pRoot
->lookupPrimitiveType(ET_any
)),
136 OString("queryInterface"), pInterface
);
137 AstParameter
* pParam
= new AstParameter(DIR_IN
, false,
138 (AstType
*)(pRoot
->lookupPrimitiveType(ET_type
)),
139 OString("aType"), pOp
);
140 pOp
->addDeclaration(pParam
);
141 pInterface
->addMember(pOp
);
143 // define XInterface::acquire
144 pOp
= new AstOperation((AstType
*)(pRoot
->lookupPrimitiveType(ET_void
)),
145 OString("acquire"), pInterface
);
146 pInterface
->addMember(pOp
);
148 // define XInterface::release
149 pOp
= new AstOperation((AstType
*)(pRoot
->lookupPrimitiveType(ET_void
)),
150 OString("release"), pInterface
);
151 pInterface
->addMember(pOp
);
154 static void SAL_CALL
initializePredefinedTypes(AstModule
* pRoot
)
158 AstBaseType
* pPredefined
= new AstBaseType(ET_long
, OString("long"), pRoot
);
159 pRoot
->addDeclaration(pPredefined
);
161 pPredefined
= new AstBaseType(ET_ulong
, OString("unsigned long"), pRoot
);
162 pRoot
->addDeclaration(pPredefined
);
164 pPredefined
= new AstBaseType(ET_hyper
, OString("hyper"), pRoot
);
165 pRoot
->addDeclaration(pPredefined
);
167 pPredefined
= new AstBaseType(ET_uhyper
, OString("unsigned hyper"), pRoot
);
168 pRoot
->addDeclaration(pPredefined
);
170 pPredefined
= new AstBaseType(ET_short
, OString("short"), pRoot
);
171 pRoot
->addDeclaration(pPredefined
);
173 pPredefined
= new AstBaseType(ET_ushort
, OString("unsigned short"), pRoot
);
174 pRoot
->addDeclaration(pPredefined
);
176 pPredefined
= new AstBaseType(ET_float
, OString("float"), pRoot
);
177 pRoot
->addDeclaration(pPredefined
);
179 pPredefined
= new AstBaseType(ET_double
, OString("double"), pRoot
);
180 pRoot
->addDeclaration(pPredefined
);
182 pPredefined
= new AstBaseType(ET_char
, OString("char"), pRoot
);
183 pRoot
->addDeclaration(pPredefined
);
185 pPredefined
= new AstBaseType(ET_byte
, OString("byte"), pRoot
);
186 pRoot
->addDeclaration(pPredefined
);
188 pPredefined
= new AstBaseType(ET_any
, OString("any"), pRoot
);
189 pRoot
->addDeclaration(pPredefined
);
191 pPredefined
= new AstBaseType(ET_string
, OString("string"), pRoot
);
192 pRoot
->addDeclaration(pPredefined
);
194 pPredefined
= new AstBaseType(ET_type
, OString("type"), pRoot
);
195 pRoot
->addDeclaration(pPredefined
);
197 pPredefined
= new AstBaseType(ET_boolean
, OString("boolean"), pRoot
);
198 pRoot
->addDeclaration(pPredefined
);
200 pPredefined
= new AstBaseType(ET_void
, OString("void"), pRoot
);
201 pRoot
->addDeclaration(pPredefined
);
205 Idlc::Idlc(Options
* pOptions
)
206 : m_pOptions(pOptions
)
207 , m_bIsDocValid(sal_False
)
208 , m_bIsInMainfile(sal_True
)
215 , m_parseState(PS_NoState
)
217 m_pScopes
= new AstStack();
218 // init root object after construction
220 m_pErrorHandler
= new ErrorHandler();
221 m_bGenerateDoc
= m_pOptions
->isValid("-C");
231 delete m_pErrorHandler
;
239 m_pRoot
= new AstModule(NT_root
, OString(), NULL
);
241 // push the root node on the stack
242 m_pScopes
->push(m_pRoot
);
243 initializePredefinedTypes(m_pRoot
);
244 predefineXInterface(m_pRoot
);
249 m_bIsDocValid
= sal_False
;
250 m_bIsInMainfile
= sal_True
;
256 m_parseState
= PS_NoState
;
258 m_fileName
= OString();
259 m_mainFileName
= OString();
260 m_realFileName
= OString();
261 m_documentation
= OString();
267 m_pRoot
= new AstModule(NT_root
, OString(), NULL
);
269 // push the root node on the stack
270 m_pScopes
->push(m_pRoot
);
271 initializePredefinedTypes(m_pRoot
);
276 OUString
Idlc::processDocumentation()
280 OString
raw(getDocumentation());
281 if (m_bGenerateDoc
) {
282 doc
= OStringToOUString(raw
, RTL_TEXTENCODING_UTF8
);
283 } else if (raw
.indexOf("@deprecated") != -1) {
284 //TODO: this check is somewhat crude
291 static void lcl_writeString(::osl::File
& rFile
, ::osl::FileBase::RC
& o_rRC
,
292 OString
const& rString
)
294 sal_uInt64
nWritten(0);
295 if (::osl::FileBase::E_None
== o_rRC
) {
296 o_rRC
= rFile
.write(rString
.getStr(), rString
.getLength(), nWritten
);
297 if (static_cast<sal_uInt64
>(rString
.getLength()) != nWritten
) {
298 o_rRC
= ::osl::FileBase::E_INVAL
; //?
305 ::osl::File
& m_rFile
;
306 ::osl::FileBase::RC
& m_rRC
;
307 explicit WriteDep(::osl::File
& rFile
, ::osl::FileBase::RC
& rRC
)
308 : m_rFile(rFile
), m_rRC(rRC
) { }
309 void operator() (OString
const& rEntry
)
311 lcl_writeString(m_rFile
, m_rRC
, " \\\n ");
312 lcl_writeString(m_rFile
, m_rRC
, rEntry
);
316 // write a dummy target for one included file, so the incremental build does
317 // not break with "No rule to make target" if the included file is removed
320 ::osl::File
& m_rFile
;
321 ::osl::FileBase::RC
& m_rRC
;
322 explicit WriteDummy(::osl::File
& rFile
, ::osl::FileBase::RC
& rRC
)
323 : m_rFile(rFile
), m_rRC(rRC
) { }
324 void operator() (OString
const& rEntry
)
326 lcl_writeString(m_rFile
, m_rRC
, rEntry
);
327 lcl_writeString(m_rFile
, m_rRC
, ":\n\n");
332 Idlc::dumpDeps(OString
const& rDepFile
, OString
const& rTarget
)
335 OStringToOUString(rDepFile
, osl_getThreadTextEncoding()));
336 ::osl::FileBase::RC rc
=
337 depFile
.open(osl_File_OpenFlag_Write
| osl_File_OpenFlag_Create
);
338 if (::osl::FileBase::E_None
!= rc
) {
341 lcl_writeString(depFile
, rc
, rTarget
);
342 if (::osl::FileBase::E_None
!= rc
) {
345 lcl_writeString(depFile
, rc
, " :");
346 if (::osl::FileBase::E_None
!= rc
) {
349 m_includes
.erase(getRealFileName()); // eeek, that is a temp file...
350 ::std::for_each(m_includes
.begin(), m_includes
.end(),
351 WriteDep(depFile
, rc
));
352 lcl_writeString(depFile
, rc
, "\n\n");
353 ::std::for_each(m_includes
.begin(), m_includes
.end(),
354 WriteDummy(depFile
, rc
));
355 if (::osl::FileBase::E_None
!= rc
) {
358 rc
= depFile
.close();
359 return ::osl::FileBase::E_None
== rc
;
362 static Idlc
* pStaticIdlc
= NULL
;
364 Idlc
* SAL_CALL
idlc()
369 Idlc
* SAL_CALL
setIdlc(Options
* pOptions
)
375 pStaticIdlc
= new Idlc(pOptions
);
380 AstDeclaration
const * resolveTypedefs(AstDeclaration
const * type
) {
382 while (type
->getNodeType() == NT_typedef
) {
383 type
= static_cast< AstTypeDef
const * >(type
)->getBaseType();
389 AstDeclaration
const * deconstructAndResolveTypedefs(
390 AstDeclaration
const * type
, sal_Int32
* rank
)
397 switch (type
->getNodeType()) {
399 type
= static_cast< AstTypeDef
const * >(type
)->getBaseType();
403 type
= static_cast< AstSequence
const * >(type
)->getMemberType();
411 AstInterface
const * resolveInterfaceTypedefs(AstType
const * type
) {
412 AstDeclaration
const * decl
= resolveTypedefs(type
);
413 OSL_ASSERT(decl
->getNodeType() == NT_interface
);
414 return static_cast< AstInterface
const * >(decl
);
417 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */