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/astenum.hxx>
28 #include <idlc/astinterface.hxx>
29 #include <idlc/astoperation.hxx>
30 #include <idlc/astbasetype.hxx>
31 #include "idlc/astdeclaration.hxx"
32 #include "idlc/astparameter.hxx"
33 #include "idlc/astsequence.hxx"
34 #include "idlc/asttype.hxx"
35 #include "idlc/asttypedef.hxx"
37 #include <osl/diagnose.h>
38 #include <osl/file.hxx>
39 #include <osl/thread.h>
41 using namespace ::rtl
;
43 AstDeclaration
* SAL_CALL
scopeAsDecl(AstScope
* pScope
)
45 if (pScope
== NULL
) return NULL
;
47 switch( pScope
->getScopeNodeType() )
51 return (AstService
*)(pScope
);
54 return (AstModule
*)(pScope
);
56 return (AstConstants
*)(pScope
);
58 return (AstInterface
*)(pScope
);
60 return (AstOperation
*)(pScope
);
62 return (AstException
*)(pScope
);
64 return (AstStruct
*)(pScope
);
66 return (AstEnum
*)(pScope
);
72 AstScope
* SAL_CALL
declAsScope(AstDeclaration
* pDecl
)
74 if (pDecl
== NULL
) return NULL
;
76 switch(pDecl
->getNodeType())
79 return (AstInterface
*)(pDecl
);
82 return (AstService
*)(pDecl
);
85 return (AstModule
*)(pDecl
);
87 return (AstConstants
*)(pDecl
);
89 return (AstException
*)(pDecl
);
91 return (AstStruct
*)(pDecl
);
93 return (AstEnum
*)(pDecl
);
95 return (AstOperation
*)(pDecl
);
101 static void SAL_CALL
predefineXInterface(AstModule
* pRoot
)
103 // define the modules com::sun::star::uno
104 AstModule
* pParentScope
= pRoot
;
105 AstModule
* pModule
= new AstModule(OString("com"), pParentScope
);
106 pModule
->setPredefined(true);
107 pParentScope
->addDeclaration(pModule
);
108 pParentScope
= pModule
;
109 pModule
= new AstModule(OString("sun"), pParentScope
);
110 pModule
->setPredefined(true);
111 pParentScope
->addDeclaration(pModule
);
112 pParentScope
= pModule
;
113 pModule
= new AstModule(OString("star"), pParentScope
);
114 pModule
->setPredefined(true);
115 pParentScope
->addDeclaration(pModule
);
116 pParentScope
= pModule
;
117 pModule
= new AstModule(OString("uno"), pParentScope
);
118 pModule
->setPredefined(true);
119 pParentScope
->addDeclaration(pModule
);
120 pParentScope
= pModule
;
123 AstInterface
* pInterface
= new AstInterface(OString("XInterface"), NULL
, pParentScope
);
124 pInterface
->setDefined();
125 pInterface
->setPredefined(true);
126 pInterface
->setPublished();
127 pParentScope
->addDeclaration(pInterface
);
129 // define XInterface::queryInterface
130 AstOperation
* pOp
= new AstOperation((AstType
*)(pRoot
->lookupPrimitiveType(ET_any
)),
131 OString("queryInterface"), pInterface
);
132 AstParameter
* pParam
= new AstParameter(DIR_IN
, false,
133 (AstType
*)(pRoot
->lookupPrimitiveType(ET_type
)),
134 OString("aType"), pOp
);
135 pOp
->addDeclaration(pParam
);
136 pInterface
->addMember(pOp
);
138 // define XInterface::acquire
139 pOp
= new AstOperation((AstType
*)(pRoot
->lookupPrimitiveType(ET_void
)),
140 OString("acquire"), pInterface
);
141 pInterface
->addMember(pOp
);
143 // define XInterface::release
144 pOp
= new AstOperation((AstType
*)(pRoot
->lookupPrimitiveType(ET_void
)),
145 OString("release"), pInterface
);
146 pInterface
->addMember(pOp
);
149 static void SAL_CALL
initializePredefinedTypes(AstModule
* pRoot
)
153 AstBaseType
* pPredefined
= new AstBaseType(ET_long
, OString("long"), pRoot
);
154 pRoot
->addDeclaration(pPredefined
);
156 pPredefined
= new AstBaseType(ET_ulong
, OString("unsigned long"), pRoot
);
157 pRoot
->addDeclaration(pPredefined
);
159 pPredefined
= new AstBaseType(ET_hyper
, OString("hyper"), pRoot
);
160 pRoot
->addDeclaration(pPredefined
);
162 pPredefined
= new AstBaseType(ET_uhyper
, OString("unsigned hyper"), pRoot
);
163 pRoot
->addDeclaration(pPredefined
);
165 pPredefined
= new AstBaseType(ET_short
, OString("short"), pRoot
);
166 pRoot
->addDeclaration(pPredefined
);
168 pPredefined
= new AstBaseType(ET_ushort
, OString("unsigned short"), pRoot
);
169 pRoot
->addDeclaration(pPredefined
);
171 pPredefined
= new AstBaseType(ET_float
, OString("float"), pRoot
);
172 pRoot
->addDeclaration(pPredefined
);
174 pPredefined
= new AstBaseType(ET_double
, OString("double"), pRoot
);
175 pRoot
->addDeclaration(pPredefined
);
177 pPredefined
= new AstBaseType(ET_char
, OString("char"), pRoot
);
178 pRoot
->addDeclaration(pPredefined
);
180 pPredefined
= new AstBaseType(ET_byte
, OString("byte"), pRoot
);
181 pRoot
->addDeclaration(pPredefined
);
183 pPredefined
= new AstBaseType(ET_any
, OString("any"), pRoot
);
184 pRoot
->addDeclaration(pPredefined
);
186 pPredefined
= new AstBaseType(ET_string
, OString("string"), pRoot
);
187 pRoot
->addDeclaration(pPredefined
);
189 pPredefined
= new AstBaseType(ET_type
, OString("type"), pRoot
);
190 pRoot
->addDeclaration(pPredefined
);
192 pPredefined
= new AstBaseType(ET_boolean
, OString("boolean"), pRoot
);
193 pRoot
->addDeclaration(pPredefined
);
195 pPredefined
= new AstBaseType(ET_void
, OString("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
= new AstStack();
213 // init root object after construction
215 m_pErrorHandler
= new ErrorHandler();
216 m_bGenerateDoc
= m_pOptions
->isValid("-C");
226 delete m_pErrorHandler
;
234 m_pRoot
= new AstModule(NT_root
, OString(), NULL
);
236 // push the root node on the stack
237 m_pScopes
->push(m_pRoot
);
238 initializePredefinedTypes(m_pRoot
);
239 predefineXInterface(m_pRoot
);
244 m_bIsDocValid
= false;
245 m_bIsInMainfile
= true;
251 m_parseState
= PS_NoState
;
253 m_fileName
= OString();
254 m_mainFileName
= OString();
255 m_realFileName
= OString();
256 m_documentation
= OString();
262 m_pRoot
= new AstModule(NT_root
, OString(), NULL
);
264 // push the root node on the stack
265 m_pScopes
->push(m_pRoot
);
266 initializePredefinedTypes(m_pRoot
);
271 OUString
Idlc::processDocumentation()
275 OString
raw(getDocumentation());
276 if (m_bGenerateDoc
) {
277 doc
= OStringToOUString(raw
, RTL_TEXTENCODING_UTF8
);
278 } else if (raw
.indexOf("@deprecated") != -1) {
279 //TODO: this check is somewhat crude
286 static void lcl_writeString(::osl::File
& rFile
, ::osl::FileBase::RC
& o_rRC
,
287 OString
const& rString
)
289 sal_uInt64
nWritten(0);
290 if (::osl::FileBase::E_None
== o_rRC
) {
291 o_rRC
= rFile
.write(rString
.getStr(), rString
.getLength(), nWritten
);
292 if (static_cast<sal_uInt64
>(rString
.getLength()) != nWritten
) {
293 o_rRC
= ::osl::FileBase::E_INVAL
; //?
300 ::osl::File
& m_rFile
;
301 ::osl::FileBase::RC
& m_rRC
;
302 explicit WriteDep(::osl::File
& rFile
, ::osl::FileBase::RC
& rRC
)
303 : m_rFile(rFile
), m_rRC(rRC
) { }
304 void operator() (OString
const& rEntry
)
306 lcl_writeString(m_rFile
, m_rRC
, " \\\n ");
307 lcl_writeString(m_rFile
, m_rRC
, rEntry
);
311 // write a dummy target for one included file, so the incremental build does
312 // not break with "No rule to make target" if the included file is removed
315 ::osl::File
& m_rFile
;
316 ::osl::FileBase::RC
& m_rRC
;
317 explicit WriteDummy(::osl::File
& rFile
, ::osl::FileBase::RC
& rRC
)
318 : m_rFile(rFile
), m_rRC(rRC
) { }
319 void operator() (OString
const& rEntry
)
321 lcl_writeString(m_rFile
, m_rRC
, rEntry
);
322 lcl_writeString(m_rFile
, m_rRC
, ":\n\n");
327 Idlc::dumpDeps(OString
const& rDepFile
, OString
const& rTarget
)
330 OStringToOUString(rDepFile
, osl_getThreadTextEncoding()));
331 ::osl::FileBase::RC rc
=
332 depFile
.open(osl_File_OpenFlag_Write
| osl_File_OpenFlag_Create
);
333 if (::osl::FileBase::E_None
!= rc
) {
336 lcl_writeString(depFile
, rc
, rTarget
);
337 if (::osl::FileBase::E_None
!= rc
) {
340 lcl_writeString(depFile
, rc
, " :");
341 if (::osl::FileBase::E_None
!= rc
) {
344 m_includes
.erase(getRealFileName()); // eeek, that is a temp file...
345 ::std::for_each(m_includes
.begin(), m_includes
.end(),
346 WriteDep(depFile
, rc
));
347 lcl_writeString(depFile
, rc
, "\n\n");
348 ::std::for_each(m_includes
.begin(), m_includes
.end(),
349 WriteDummy(depFile
, rc
));
350 if (::osl::FileBase::E_None
!= rc
) {
353 rc
= depFile
.close();
354 return ::osl::FileBase::E_None
== rc
;
357 static Idlc
* pStaticIdlc
= NULL
;
359 Idlc
* SAL_CALL
idlc()
364 Idlc
* SAL_CALL
setIdlc(Options
* pOptions
)
370 pStaticIdlc
= new Idlc(pOptions
);
375 AstDeclaration
const * resolveTypedefs(AstDeclaration
const * type
) {
377 while (type
->getNodeType() == NT_typedef
) {
378 type
= static_cast< AstTypeDef
const * >(type
)->getBaseType();
384 AstDeclaration
const * deconstructAndResolveTypedefs(
385 AstDeclaration
const * type
, sal_Int32
* rank
)
392 switch (type
->getNodeType()) {
394 type
= static_cast< AstTypeDef
const * >(type
)->getBaseType();
398 type
= static_cast< AstSequence
const * >(type
)->getMemberType();
406 AstInterface
const * resolveInterfaceTypedefs(AstType
const * type
) {
407 AstDeclaration
const * decl
= resolveTypedefs(type
);
408 OSL_ASSERT(decl
->getNodeType() == NT_interface
);
409 return static_cast< AstInterface
const * >(decl
);
412 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */