Bump version to 4.3-4
[LibreOffice.git] / idlc / source / idlc.cxx
blobbf7594eee46741d3699d56ca42b59f841cc682b5
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/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() )
49 case NT_service:
50 case NT_singleton:
51 return (AstService*)(pScope);
52 case NT_module:
53 case NT_root:
54 return (AstModule*)(pScope);
55 case NT_constants:
56 return (AstConstants*)(pScope);
57 case NT_interface:
58 return (AstInterface*)(pScope);
59 case NT_operation:
60 return (AstOperation*)(pScope);
61 case NT_exception:
62 return (AstException*)(pScope);
63 case NT_struct:
64 return (AstStruct*)(pScope);
65 case NT_enum:
66 return (AstEnum*)(pScope);
67 default:
68 return NULL;
72 AstScope* SAL_CALL declAsScope(AstDeclaration* pDecl)
74 if (pDecl == NULL) return NULL;
76 switch(pDecl->getNodeType())
78 case NT_interface:
79 return (AstInterface*)(pDecl);
80 case NT_service:
81 case NT_singleton:
82 return (AstService*)(pDecl);
83 case NT_module:
84 case NT_root:
85 return (AstModule*)(pDecl);
86 case NT_constants:
87 return (AstConstants*)(pDecl);
88 case NT_exception:
89 return (AstException*)(pDecl);
90 case NT_struct:
91 return (AstStruct*)(pDecl);
92 case NT_enum:
93 return (AstEnum*)(pDecl);
94 case NT_operation:
95 return (AstOperation*)(pDecl);
96 default:
97 return NULL;
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;
122 // define XInterface
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)
151 if ( 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)
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 = new AstStack();
213 // init root object after construction
214 m_pRoot = NULL;
215 m_pErrorHandler = new ErrorHandler();
216 m_bGenerateDoc = m_pOptions->isValid("-C");
219 Idlc::~Idlc()
221 if (m_pRoot)
222 delete m_pRoot;
223 if (m_pScopes)
224 delete m_pScopes;
225 if (m_pErrorHandler)
226 delete m_pErrorHandler;
229 void Idlc::init()
231 if ( m_pRoot )
232 delete m_pRoot;
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);
242 void Idlc::reset()
244 m_bIsDocValid = false;
245 m_bIsInMainfile = true;
246 m_published = false;
248 m_errorCount = 0;
249 m_warningCount = 0;
250 m_lineNumber = 0;
251 m_parseState = PS_NoState;
253 m_fileName = OString();
254 m_mainFileName = OString();
255 m_realFileName = OString();
256 m_documentation = OString();
258 m_pScopes->clear();
259 if ( m_pRoot)
260 delete m_pRoot;
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);
268 m_includes.clear();
271 OUString Idlc::processDocumentation()
273 OUString doc;
274 if (m_bIsDocValid) {
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
280 doc = "@deprecated";
283 return doc;
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; //?
298 struct WriteDep
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
313 struct WriteDummy
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");
326 bool
327 Idlc::dumpDeps(OString const& rDepFile, OString const& rTarget)
329 ::osl::File depFile(
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) {
334 return false;
336 lcl_writeString(depFile, rc, rTarget);
337 if (::osl::FileBase::E_None != rc) {
338 return false;
340 lcl_writeString(depFile, rc, " :");
341 if (::osl::FileBase::E_None != rc) {
342 return false;
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) {
351 return false;
353 rc = depFile.close();
354 return ::osl::FileBase::E_None == rc;
357 static Idlc* pStaticIdlc = NULL;
359 Idlc* SAL_CALL idlc()
361 return pStaticIdlc;
364 Idlc* SAL_CALL setIdlc(Options* pOptions)
366 if ( pStaticIdlc )
368 delete pStaticIdlc;
370 pStaticIdlc = new Idlc(pOptions);
371 pStaticIdlc->init();
372 return pStaticIdlc;
375 AstDeclaration const * resolveTypedefs(AstDeclaration const * type) {
376 if (type != 0) {
377 while (type->getNodeType() == NT_typedef) {
378 type = static_cast< AstTypeDef const * >(type)->getBaseType();
381 return type;
384 AstDeclaration const * deconstructAndResolveTypedefs(
385 AstDeclaration const * type, sal_Int32 * rank)
387 *rank = 0;
388 for (;;) {
389 if (type == 0) {
390 return 0;
392 switch (type->getNodeType()) {
393 case NT_typedef:
394 type = static_cast< AstTypeDef const * >(type)->getBaseType();
395 break;
396 case NT_sequence:
397 ++(*rank);
398 type = static_cast< AstSequence const * >(type)->getMemberType();
399 break;
400 default:
401 return type;
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: */