bump product version to 6.4.0.3
[LibreOffice.git] / idlc / source / idlc.cxx
blobcd532f91320f4479e00052a8f56b84e4df9ec562
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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.hxx>
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>
41 #include <algorithm>
43 AstDeclaration* scopeAsDecl(AstScope* pScope)
45 if (pScope == nullptr) return nullptr;
47 switch( pScope->getScopeNodeType() )
49 case NT_service:
50 case NT_singleton:
51 return static_cast<AstService*>(pScope);
52 case NT_module:
53 case NT_root:
54 return static_cast<AstModule*>(pScope);
55 case NT_constants:
56 return static_cast<AstConstants*>(pScope);
57 case NT_interface:
58 return static_cast<AstInterface*>(pScope);
59 case NT_operation:
60 return static_cast<AstOperation*>(pScope);
61 case NT_exception:
62 return static_cast<AstException*>(pScope);
63 case NT_struct:
64 return static_cast<AstStruct*>(pScope);
65 case NT_enum:
66 return static_cast<AstEnum*>(pScope);
67 default:
68 return nullptr;
72 AstScope* declAsScope(AstDeclaration* pDecl)
74 if (pDecl == nullptr) return nullptr;
76 switch(pDecl->getNodeType())
78 case NT_interface:
79 return static_cast<AstInterface*>(pDecl);
80 case NT_service:
81 case NT_singleton:
82 return static_cast<AstService*>(pDecl);
83 case NT_module:
84 case NT_root:
85 return static_cast<AstModule*>(pDecl);
86 case NT_constants:
87 return static_cast<AstConstants*>(pDecl);
88 case NT_exception:
89 return static_cast<AstException*>(pDecl);
90 case NT_struct:
91 return static_cast<AstStruct*>(pDecl);
92 case NT_enum:
93 return static_cast<AstEnum*>(pDecl);
94 case NT_operation:
95 return static_cast<AstOperation*>(pDecl);
96 default:
97 return nullptr;
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;
122 // define XInterface
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)),
134 "aType", pOp);
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)
151 if ( 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)
204 , m_published(false)
205 , m_errorCount(0)
206 , m_warningCount(0)
207 , m_lineNumber(0)
208 , m_offsetStart(0)
209 , m_offsetEnd(0)
210 , m_parseState(PS_NoState)
212 m_pScopes.reset( new AstStack() );
213 // init root object after construction
214 m_pRoot = nullptr;
215 m_bGenerateDoc = m_pOptions->isValid("-C");
218 Idlc::~Idlc()
222 void Idlc::init()
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());
232 void Idlc::reset()
234 m_bIsDocValid = false;
235 m_bIsInMainfile = true;
236 m_published = false;
238 m_errorCount = 0;
239 m_warningCount = 0;
240 m_lineNumber = 0;
241 m_parseState = PS_NoState;
243 m_fileName.clear();
244 m_mainFileName.clear();
245 m_realFileName.clear();
246 m_documentation.clear();
248 m_pScopes->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());
255 m_includes.clear();
258 OUString Idlc::processDocumentation()
260 OUString doc;
261 if (m_bIsDocValid) {
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
267 doc = "@deprecated";
270 return doc;
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; //?
285 struct WriteDep
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
300 struct WriteDummy
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");
313 bool
314 Idlc::dumpDeps(OString const& rDepFile, OString const& rTarget)
316 ::osl::File depFile(
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) {
321 return false;
323 lcl_writeString(depFile, rc, rTarget);
324 if (::osl::FileBase::E_None != rc) {
325 return false;
327 lcl_writeString(depFile, rc, " :");
328 if (::osl::FileBase::E_None != rc) {
329 return false;
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) {
338 return false;
340 rc = depFile.close();
341 return ::osl::FileBase::E_None == rc;
344 static Idlc* pStaticIdlc = nullptr;
346 Idlc* idlc()
348 return pStaticIdlc;
351 Idlc* setIdlc(Options* pOptions)
353 delete pStaticIdlc;
354 pStaticIdlc = new Idlc(pOptions);
355 pStaticIdlc->init();
356 return pStaticIdlc;
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();
365 return type;
368 AstDeclaration const * deconstructAndResolveTypedefs(
369 AstDeclaration const * type, sal_Int32 * rank)
371 *rank = 0;
372 for (;;) {
373 if (type == nullptr) {
374 return nullptr;
376 switch (type->getNodeType()) {
377 case NT_typedef:
378 type = static_cast< AstTypeDef const * >(type)->getBaseType();
379 break;
380 case NT_sequence:
381 ++(*rank);
382 type = static_cast< AstSequence const * >(type)->getMemberType();
383 break;
384 default:
385 return type;
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: */