bump product version to 4.1.6.2
[LibreOffice.git] / idlc / source / idlc.cxx
blob7e880261a8aeef234b0a4266905e7e67205fdec5
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/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() )
50 case NT_service:
51 case NT_singleton:
52 return (AstService*)(pScope);
53 case NT_module:
54 case NT_root:
55 return (AstModule*)(pScope);
56 case NT_constants:
57 return (AstConstants*)(pScope);
58 case NT_interface:
59 return (AstInterface*)(pScope);
60 case NT_operation:
61 return (AstOperation*)(pScope);
62 case NT_exception:
63 return (AstException*)(pScope);
64 case NT_union:
65 return (AstUnion*)(pScope);
66 case NT_struct:
67 return (AstStruct*)(pScope);
68 case NT_enum:
69 return (AstEnum*)(pScope);
70 default:
71 return NULL;
75 AstScope* SAL_CALL declAsScope(AstDeclaration* pDecl)
77 if (pDecl == NULL) return NULL;
79 switch(pDecl->getNodeType())
81 case NT_interface:
82 return (AstInterface*)(pDecl);
83 case NT_service:
84 case NT_singleton:
85 return (AstService*)(pDecl);
86 case NT_module:
87 case NT_root:
88 return (AstModule*)(pDecl);
89 case NT_constants:
90 return (AstConstants*)(pDecl);
91 case NT_exception:
92 return (AstException*)(pDecl);
93 case NT_union:
94 return (AstUnion*)(pDecl);
95 case NT_struct:
96 return (AstStruct*)(pDecl);
97 case NT_enum:
98 return (AstEnum*)(pDecl);
99 case NT_operation:
100 return (AstOperation*)(pDecl);
101 default:
102 return NULL;
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;
127 // define XInterface
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)
156 if ( 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)
209 , m_published(false)
210 , m_errorCount(0)
211 , m_warningCount(0)
212 , m_lineNumber(0)
213 , m_offsetStart(0)
214 , m_offsetEnd(0)
215 , m_parseState(PS_NoState)
217 m_pScopes = new AstStack();
218 // init root object after construction
219 m_pRoot = NULL;
220 m_pErrorHandler = new ErrorHandler();
221 m_bGenerateDoc = m_pOptions->isValid("-C");
224 Idlc::~Idlc()
226 if (m_pRoot)
227 delete m_pRoot;
228 if (m_pScopes)
229 delete m_pScopes;
230 if (m_pErrorHandler)
231 delete m_pErrorHandler;
234 void Idlc::init()
236 if ( m_pRoot )
237 delete m_pRoot;
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);
247 void Idlc::reset()
249 m_bIsDocValid = sal_False;
250 m_bIsInMainfile = sal_True;
251 m_published = false;
253 m_errorCount = 0;
254 m_warningCount = 0;
255 m_lineNumber = 0;
256 m_parseState = PS_NoState;
258 m_fileName = OString();
259 m_mainFileName = OString();
260 m_realFileName = OString();
261 m_documentation = OString();
263 m_pScopes->clear();
264 if ( m_pRoot)
265 delete m_pRoot;
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);
273 m_includes.clear();
276 OUString Idlc::processDocumentation()
278 OUString doc;
279 if (m_bIsDocValid) {
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
285 doc = "@deprecated";
288 return doc;
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; //?
303 struct WriteDep
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
318 struct WriteDummy
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");
331 bool
332 Idlc::dumpDeps(OString const& rDepFile, OString const& rTarget)
334 ::osl::File depFile(
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) {
339 return false;
341 lcl_writeString(depFile, rc, rTarget);
342 if (::osl::FileBase::E_None != rc) {
343 return false;
345 lcl_writeString(depFile, rc, " :");
346 if (::osl::FileBase::E_None != rc) {
347 return false;
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) {
356 return false;
358 rc = depFile.close();
359 return ::osl::FileBase::E_None == rc;
362 static Idlc* pStaticIdlc = NULL;
364 Idlc* SAL_CALL idlc()
366 return pStaticIdlc;
369 Idlc* SAL_CALL setIdlc(Options* pOptions)
371 if ( pStaticIdlc )
373 delete pStaticIdlc;
375 pStaticIdlc = new Idlc(pOptions);
376 pStaticIdlc->init();
377 return pStaticIdlc;
380 AstDeclaration const * resolveTypedefs(AstDeclaration const * type) {
381 if (type != 0) {
382 while (type->getNodeType() == NT_typedef) {
383 type = static_cast< AstTypeDef const * >(type)->getBaseType();
386 return type;
389 AstDeclaration const * deconstructAndResolveTypedefs(
390 AstDeclaration const * type, sal_Int32 * rank)
392 *rank = 0;
393 for (;;) {
394 if (type == 0) {
395 return 0;
397 switch (type->getNodeType()) {
398 case NT_typedef:
399 type = static_cast< AstTypeDef const * >(type)->getBaseType();
400 break;
401 case NT_sequence:
402 ++(*rank);
403 type = static_cast< AstSequence const * >(type)->getMemberType();
404 break;
405 default:
406 return type;
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: */