nss: upgrade to release 3.73
[LibreOffice.git] / idlc / source / idlc.cxx
blobc1d09b4c1b2e72a45f2f55d13e98d38334da45e4
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 )
152 return;
154 AstBaseType* pPredefined = new AstBaseType(ET_long, "long", pRoot);
155 pRoot->addDeclaration(pPredefined);
157 pPredefined = new AstBaseType(ET_ulong, "unsigned long", pRoot);
158 pRoot->addDeclaration(pPredefined);
160 pPredefined = new AstBaseType(ET_hyper, "hyper", pRoot);
161 pRoot->addDeclaration(pPredefined);
163 pPredefined = new AstBaseType(ET_uhyper, "unsigned hyper", pRoot);
164 pRoot->addDeclaration(pPredefined);
166 pPredefined = new AstBaseType(ET_short, "short", pRoot);
167 pRoot->addDeclaration(pPredefined);
169 pPredefined = new AstBaseType(ET_ushort, "unsigned short", pRoot);
170 pRoot->addDeclaration(pPredefined);
172 pPredefined = new AstBaseType(ET_float, "float", pRoot);
173 pRoot->addDeclaration(pPredefined);
175 pPredefined = new AstBaseType(ET_double, "double", pRoot);
176 pRoot->addDeclaration(pPredefined);
178 pPredefined = new AstBaseType(ET_char, "char", pRoot);
179 pRoot->addDeclaration(pPredefined);
181 pPredefined = new AstBaseType(ET_byte, "byte", pRoot);
182 pRoot->addDeclaration(pPredefined);
184 pPredefined = new AstBaseType(ET_any, "any", pRoot);
185 pRoot->addDeclaration(pPredefined);
187 pPredefined = new AstBaseType(ET_string, "string", pRoot);
188 pRoot->addDeclaration(pPredefined);
190 pPredefined = new AstBaseType(ET_type, "type", pRoot);
191 pRoot->addDeclaration(pPredefined);
193 pPredefined = new AstBaseType(ET_boolean, "boolean", pRoot);
194 pRoot->addDeclaration(pPredefined);
196 pPredefined = new AstBaseType(ET_void, "void", pRoot);
197 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 if (::osl::FileBase::E_None == o_rRC) {
277 sal_uInt64 nWritten(0);
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 namespace {
287 struct WriteDep
289 ::osl::File& m_rFile;
290 ::osl::FileBase::RC & m_rRC;
291 explicit WriteDep(::osl::File & rFile, ::osl::FileBase::RC & rRC)
292 : m_rFile(rFile), m_rRC(rRC) { }
293 void operator() (OString const& rEntry)
295 lcl_writeString(m_rFile, m_rRC, " \\\n ");
296 lcl_writeString(m_rFile, m_rRC, rEntry);
300 // write a dummy target for one included file, so the incremental build does
301 // not break with "No rule to make target" if the included file is removed
302 struct WriteDummy
304 ::osl::File& m_rFile;
305 ::osl::FileBase::RC & m_rRC;
306 explicit WriteDummy(::osl::File & rFile, ::osl::FileBase::RC & rRC)
307 : m_rFile(rFile), m_rRC(rRC) { }
308 void operator() (OString const& rEntry)
310 lcl_writeString(m_rFile, m_rRC, rEntry);
311 lcl_writeString(m_rFile, m_rRC, ":\n\n");
317 bool
318 Idlc::dumpDeps(OString const& rDepFile, OString const& rTarget)
320 ::osl::File depFile(
321 OStringToOUString(rDepFile, osl_getThreadTextEncoding()));
322 ::osl::FileBase::RC rc =
323 depFile.open(osl_File_OpenFlag_Write | osl_File_OpenFlag_Create);
324 if (::osl::FileBase::E_None != rc) {
325 return false;
327 lcl_writeString(depFile, rc, rTarget);
328 if (::osl::FileBase::E_None != rc) {
329 return false;
331 lcl_writeString(depFile, rc, " :");
332 if (::osl::FileBase::E_None != rc) {
333 return false;
335 m_includes.erase(getRealFileName()); // eeek, that is a temp file...
336 ::std::for_each(m_includes.begin(), m_includes.end(),
337 WriteDep(depFile, rc));
338 lcl_writeString(depFile, rc, "\n\n");
339 ::std::for_each(m_includes.begin(), m_includes.end(),
340 WriteDummy(depFile, rc));
341 if (::osl::FileBase::E_None != rc) {
342 return false;
344 rc = depFile.close();
345 return ::osl::FileBase::E_None == rc;
348 static Idlc* pStaticIdlc = nullptr;
350 Idlc* idlc()
352 return pStaticIdlc;
355 Idlc* setIdlc(Options* pOptions)
357 delete pStaticIdlc;
358 pStaticIdlc = new Idlc(pOptions);
359 pStaticIdlc->init();
360 return pStaticIdlc;
363 AstDeclaration const * resolveTypedefs(AstDeclaration const * type) {
364 if (type != nullptr) {
365 while (type->getNodeType() == NT_typedef) {
366 type = static_cast< AstTypeDef const * >(type)->getBaseType();
369 return type;
372 AstDeclaration const * deconstructAndResolveTypedefs(
373 AstDeclaration const * type, sal_Int32 * rank)
375 *rank = 0;
376 for (;;) {
377 if (type == nullptr) {
378 return nullptr;
380 switch (type->getNodeType()) {
381 case NT_typedef:
382 type = static_cast< AstTypeDef const * >(type)->getBaseType();
383 break;
384 case NT_sequence:
385 ++(*rank);
386 type = static_cast< AstSequence const * >(type)->getMemberType();
387 break;
388 default:
389 return type;
394 AstInterface const * resolveInterfaceTypedefs(AstType const * type) {
395 AstDeclaration const * decl = resolveTypedefs(type);
396 OSL_ASSERT(decl->getNodeType() == NT_interface);
397 return static_cast< AstInterface const * >(decl);
400 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */