Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
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"
36 :
37 : #include <osl/diagnose.h>
38 : #include <osl/file.hxx>
39 : #include <osl/thread.h>
40 :
41 33604 : AstDeclaration* SAL_CALL scopeAsDecl(AstScope* pScope)
42 : {
43 33604 : if (pScope == NULL) return NULL;
44 :
45 33604 : switch( pScope->getScopeNodeType() )
46 : {
47 : case NT_service:
48 : case NT_singleton:
49 178 : return static_cast<AstService*>(pScope);
50 : case NT_module:
51 : case NT_root:
52 28880 : return static_cast<AstModule*>(pScope);
53 : case NT_constants:
54 162 : return static_cast<AstConstants*>(pScope);
55 : case NT_interface:
56 2778 : return static_cast<AstInterface*>(pScope);
57 : case NT_operation:
58 764 : return static_cast<AstOperation*>(pScope);
59 : case NT_exception:
60 22 : return static_cast<AstException*>(pScope);
61 : case NT_struct:
62 738 : return static_cast<AstStruct*>(pScope);
63 : case NT_enum:
64 82 : return static_cast<AstEnum*>(pScope);
65 : default:
66 0 : return NULL;
67 : }
68 : }
69 :
70 2248 : AstScope* SAL_CALL declAsScope(AstDeclaration* pDecl)
71 : {
72 2248 : if (pDecl == NULL) return NULL;
73 :
74 2248 : switch(pDecl->getNodeType())
75 : {
76 : case NT_interface:
77 0 : return static_cast<AstInterface*>(pDecl);
78 : case NT_service:
79 : case NT_singleton:
80 0 : return static_cast<AstService*>(pDecl);
81 : case NT_module:
82 : case NT_root:
83 2208 : return static_cast<AstModule*>(pDecl);
84 : case NT_constants:
85 40 : return static_cast<AstConstants*>(pDecl);
86 : case NT_exception:
87 0 : return static_cast<AstException*>(pDecl);
88 : case NT_struct:
89 0 : return static_cast<AstStruct*>(pDecl);
90 : case NT_enum:
91 0 : return static_cast<AstEnum*>(pDecl);
92 : case NT_operation:
93 0 : return static_cast<AstOperation*>(pDecl);
94 : default:
95 0 : return NULL;
96 : }
97 : }
98 :
99 658 : static void SAL_CALL predefineXInterface(AstModule* pRoot)
100 : {
101 : // define the modules com::sun::star::uno
102 658 : AstModule* pParentScope = pRoot;
103 658 : AstModule* pModule = new AstModule(OString("com"), pParentScope);
104 658 : pModule->setPredefined(true);
105 658 : pParentScope->addDeclaration(pModule);
106 658 : pParentScope = pModule;
107 658 : pModule = new AstModule(OString("sun"), pParentScope);
108 658 : pModule->setPredefined(true);
109 658 : pParentScope->addDeclaration(pModule);
110 658 : pParentScope = pModule;
111 658 : pModule = new AstModule(OString("star"), pParentScope);
112 658 : pModule->setPredefined(true);
113 658 : pParentScope->addDeclaration(pModule);
114 658 : pParentScope = pModule;
115 658 : pModule = new AstModule(OString("uno"), pParentScope);
116 658 : pModule->setPredefined(true);
117 658 : pParentScope->addDeclaration(pModule);
118 658 : pParentScope = pModule;
119 :
120 : // define XInterface
121 658 : AstInterface* pInterface = new AstInterface(OString("XInterface"), NULL, pParentScope);
122 658 : pInterface->setDefined();
123 658 : pInterface->setPredefined(true);
124 658 : pInterface->setPublished();
125 658 : pParentScope->addDeclaration(pInterface);
126 :
127 : // define XInterface::queryInterface
128 658 : AstOperation* pOp = new AstOperation(static_cast<AstType*>(pRoot->lookupPrimitiveType(ET_any)),
129 658 : OString("queryInterface"), pInterface);
130 : AstParameter* pParam = new AstParameter(DIR_IN, false,
131 658 : static_cast<AstType*>(pRoot->lookupPrimitiveType(ET_type)),
132 658 : OString("aType"), pOp);
133 658 : pOp->addDeclaration(pParam);
134 658 : pInterface->addMember(pOp);
135 :
136 : // define XInterface::acquire
137 658 : pOp = new AstOperation(static_cast<AstType*>(pRoot->lookupPrimitiveType(ET_void)),
138 658 : OString("acquire"), pInterface);
139 658 : pInterface->addMember(pOp);
140 :
141 : // define XInterface::release
142 658 : pOp = new AstOperation(static_cast<AstType*>(pRoot->lookupPrimitiveType(ET_void)),
143 658 : OString("release"), pInterface);
144 658 : pInterface->addMember(pOp);
145 658 : }
146 :
147 1316 : static void SAL_CALL initializePredefinedTypes(AstModule* pRoot)
148 : {
149 1316 : if ( pRoot )
150 : {
151 1316 : AstBaseType* pPredefined = new AstBaseType(ET_long, OString("long"), pRoot);
152 1316 : pRoot->addDeclaration(pPredefined);
153 :
154 1316 : pPredefined = new AstBaseType(ET_ulong, OString("unsigned long"), pRoot);
155 1316 : pRoot->addDeclaration(pPredefined);
156 :
157 1316 : pPredefined = new AstBaseType(ET_hyper, OString("hyper"), pRoot);
158 1316 : pRoot->addDeclaration(pPredefined);
159 :
160 1316 : pPredefined = new AstBaseType(ET_uhyper, OString("unsigned hyper"), pRoot);
161 1316 : pRoot->addDeclaration(pPredefined);
162 :
163 1316 : pPredefined = new AstBaseType(ET_short, OString("short"), pRoot);
164 1316 : pRoot->addDeclaration(pPredefined);
165 :
166 1316 : pPredefined = new AstBaseType(ET_ushort, OString("unsigned short"), pRoot);
167 1316 : pRoot->addDeclaration(pPredefined);
168 :
169 1316 : pPredefined = new AstBaseType(ET_float, OString("float"), pRoot);
170 1316 : pRoot->addDeclaration(pPredefined);
171 :
172 1316 : pPredefined = new AstBaseType(ET_double, OString("double"), pRoot);
173 1316 : pRoot->addDeclaration(pPredefined);
174 :
175 1316 : pPredefined = new AstBaseType(ET_char, OString("char"), pRoot);
176 1316 : pRoot->addDeclaration(pPredefined);
177 :
178 1316 : pPredefined = new AstBaseType(ET_byte, OString("byte"), pRoot);
179 1316 : pRoot->addDeclaration(pPredefined);
180 :
181 1316 : pPredefined = new AstBaseType(ET_any, OString("any"), pRoot);
182 1316 : pRoot->addDeclaration(pPredefined);
183 :
184 1316 : pPredefined = new AstBaseType(ET_string, OString("string"), pRoot);
185 1316 : pRoot->addDeclaration(pPredefined);
186 :
187 1316 : pPredefined = new AstBaseType(ET_type, OString("type"), pRoot);
188 1316 : pRoot->addDeclaration(pPredefined);
189 :
190 1316 : pPredefined = new AstBaseType(ET_boolean, OString("boolean"), pRoot);
191 1316 : pRoot->addDeclaration(pPredefined);
192 :
193 1316 : pPredefined = new AstBaseType(ET_void, OString("void"), pRoot);
194 1316 : pRoot->addDeclaration(pPredefined);
195 : }
196 1316 : }
197 :
198 658 : Idlc::Idlc(Options* pOptions)
199 : : m_pOptions(pOptions)
200 : , m_bIsDocValid(false)
201 : , m_bIsInMainfile(true)
202 : , m_published(false)
203 : , m_errorCount(0)
204 : , m_warningCount(0)
205 : , m_lineNumber(0)
206 : , m_offsetStart(0)
207 : , m_offsetEnd(0)
208 658 : , m_parseState(PS_NoState)
209 : {
210 658 : m_pScopes = new AstStack();
211 : // init root object after construction
212 658 : m_pRoot = NULL;
213 658 : m_pErrorHandler = new ErrorHandler();
214 658 : m_bGenerateDoc = m_pOptions->isValid("-C");
215 658 : }
216 :
217 0 : Idlc::~Idlc()
218 : {
219 0 : if (m_pRoot)
220 0 : delete m_pRoot;
221 0 : if (m_pScopes)
222 0 : delete m_pScopes;
223 0 : if (m_pErrorHandler)
224 0 : delete m_pErrorHandler;
225 0 : }
226 :
227 658 : void Idlc::init()
228 : {
229 658 : if ( m_pRoot )
230 0 : delete m_pRoot;
231 :
232 658 : m_pRoot = new AstModule(NT_root, OString(), NULL);
233 :
234 : // push the root node on the stack
235 658 : m_pScopes->push(m_pRoot);
236 658 : initializePredefinedTypes(m_pRoot);
237 658 : predefineXInterface(m_pRoot);
238 658 : }
239 :
240 658 : void Idlc::reset()
241 : {
242 658 : m_bIsDocValid = false;
243 658 : m_bIsInMainfile = true;
244 658 : m_published = false;
245 :
246 658 : m_errorCount = 0;
247 658 : m_warningCount = 0;
248 658 : m_lineNumber = 0;
249 658 : m_parseState = PS_NoState;
250 :
251 658 : m_fileName = OString();
252 658 : m_mainFileName = OString();
253 658 : m_realFileName = OString();
254 658 : m_documentation = OString();
255 :
256 658 : m_pScopes->clear();
257 658 : if ( m_pRoot)
258 658 : delete m_pRoot;
259 :
260 658 : m_pRoot = new AstModule(NT_root, OString(), NULL);
261 :
262 : // push the root node on the stack
263 658 : m_pScopes->push(m_pRoot);
264 658 : initializePredefinedTypes(m_pRoot);
265 :
266 658 : m_includes.clear();
267 658 : }
268 :
269 29540 : OUString Idlc::processDocumentation()
270 : {
271 29540 : OUString doc;
272 29540 : if (m_bIsDocValid) {
273 0 : OString raw(getDocumentation());
274 0 : if (m_bGenerateDoc) {
275 0 : doc = OStringToOUString(raw, RTL_TEXTENCODING_UTF8);
276 0 : } else if (raw.indexOf("@deprecated") != -1) {
277 : //TODO: this check is somewhat crude
278 0 : doc = "@deprecated";
279 0 : }
280 : }
281 29540 : return doc;
282 : }
283 :
284 0 : static void lcl_writeString(::osl::File & rFile, ::osl::FileBase::RC & o_rRC,
285 : OString const& rString)
286 : {
287 0 : sal_uInt64 nWritten(0);
288 0 : if (::osl::FileBase::E_None == o_rRC) {
289 0 : o_rRC = rFile.write(rString.getStr(), rString.getLength(), nWritten);
290 0 : if (static_cast<sal_uInt64>(rString.getLength()) != nWritten) {
291 0 : o_rRC = ::osl::FileBase::E_INVAL; //?
292 : }
293 : }
294 0 : }
295 :
296 : struct WriteDep
297 : {
298 : ::osl::File& m_rFile;
299 : ::osl::FileBase::RC & m_rRC;
300 0 : explicit WriteDep(::osl::File & rFile, ::osl::FileBase::RC & rRC)
301 0 : : m_rFile(rFile), m_rRC(rRC) { }
302 0 : void operator() (OString const& rEntry)
303 : {
304 0 : lcl_writeString(m_rFile, m_rRC, " \\\n ");
305 0 : lcl_writeString(m_rFile, m_rRC, rEntry);
306 0 : }
307 : };
308 :
309 : // write a dummy target for one included file, so the incremental build does
310 : // not break with "No rule to make target" if the included file is removed
311 : struct WriteDummy
312 : {
313 : ::osl::File& m_rFile;
314 : ::osl::FileBase::RC & m_rRC;
315 0 : explicit WriteDummy(::osl::File & rFile, ::osl::FileBase::RC & rRC)
316 0 : : m_rFile(rFile), m_rRC(rRC) { }
317 0 : void operator() (OString const& rEntry)
318 : {
319 0 : lcl_writeString(m_rFile, m_rRC, rEntry);
320 0 : lcl_writeString(m_rFile, m_rRC, ":\n\n");
321 0 : }
322 : };
323 :
324 : bool
325 0 : Idlc::dumpDeps(OString const& rDepFile, OString const& rTarget)
326 : {
327 : ::osl::File depFile(
328 0 : OStringToOUString(rDepFile, osl_getThreadTextEncoding()));
329 : ::osl::FileBase::RC rc =
330 0 : depFile.open(osl_File_OpenFlag_Write | osl_File_OpenFlag_Create);
331 0 : if (::osl::FileBase::E_None != rc) {
332 0 : return false;
333 : }
334 0 : lcl_writeString(depFile, rc, rTarget);
335 0 : if (::osl::FileBase::E_None != rc) {
336 0 : return false;
337 : }
338 0 : lcl_writeString(depFile, rc, " :");
339 0 : if (::osl::FileBase::E_None != rc) {
340 0 : return false;
341 : }
342 0 : m_includes.erase(getRealFileName()); // eeek, that is a temp file...
343 : ::std::for_each(m_includes.begin(), m_includes.end(),
344 0 : WriteDep(depFile, rc));
345 0 : lcl_writeString(depFile, rc, "\n\n");
346 : ::std::for_each(m_includes.begin(), m_includes.end(),
347 0 : WriteDummy(depFile, rc));
348 0 : if (::osl::FileBase::E_None != rc) {
349 0 : return false;
350 : }
351 0 : rc = depFile.close();
352 0 : return ::osl::FileBase::E_None == rc;
353 : }
354 :
355 : static Idlc* pStaticIdlc = NULL;
356 :
357 224086 : Idlc* SAL_CALL idlc()
358 : {
359 224086 : return pStaticIdlc;
360 : }
361 :
362 658 : Idlc* SAL_CALL setIdlc(Options* pOptions)
363 : {
364 658 : if ( pStaticIdlc )
365 : {
366 0 : delete pStaticIdlc;
367 : }
368 658 : pStaticIdlc = new Idlc(pOptions);
369 658 : pStaticIdlc->init();
370 658 : return pStaticIdlc;
371 : }
372 :
373 2688 : AstDeclaration const * resolveTypedefs(AstDeclaration const * type) {
374 2688 : if (type != 0) {
375 4066 : while (type->getNodeType() == NT_typedef) {
376 74 : type = static_cast< AstTypeDef const * >(type)->getBaseType();
377 : }
378 : }
379 2688 : return type;
380 : }
381 :
382 32 : AstDeclaration const * deconstructAndResolveTypedefs(
383 : AstDeclaration const * type, sal_Int32 * rank)
384 : {
385 24 : *rank = 0;
386 : for (;;) {
387 32 : if (type == 0) {
388 0 : return 0;
389 : }
390 32 : switch (type->getNodeType()) {
391 : case NT_typedef:
392 2 : type = static_cast< AstTypeDef const * >(type)->getBaseType();
393 2 : break;
394 : case NT_sequence:
395 6 : ++(*rank);
396 6 : type = static_cast< AstSequence const * >(type)->getMemberType();
397 6 : break;
398 : default:
399 24 : return type;
400 : }
401 : }
402 : }
403 :
404 910 : AstInterface const * resolveInterfaceTypedefs(AstType const * type) {
405 910 : AstDeclaration const * decl = resolveTypedefs(type);
406 : OSL_ASSERT(decl->getNodeType() == NT_interface);
407 910 : return static_cast< AstInterface const * >(decl);
408 : }
409 :
410 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|