Teach symstore more duplicated DLLs
[LibreOffice.git] / idl / source / prj / database.cxx
blob2629c2d457cb4fdd42af9237d323430e5408d488
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 <sal/config.h>
22 #include <algorithm>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <database.hxx>
26 #include <globals.hxx>
27 #include <rtl/strbuf.hxx>
28 #include <osl/file.hxx>
31 SvParseException::SvParseException( SvTokenStream const & rInStm, const OString& rError )
33 SvToken& rTok = rInStm.GetToken();
34 aError = SvIdlError( rTok.GetLine(), rTok.GetColumn() );
35 aError.SetText( rError );
38 SvParseException::SvParseException( const OString& rError, SvToken const & rTok )
40 aError = SvIdlError( rTok.GetLine(), rTok.GetColumn() );
41 aError.SetText( rError );
45 SvIdlDataBase::SvIdlDataBase( const SvCommand& rCmd )
46 : bExport( false )
47 , nUniqueId( 0 )
48 , nVerbosity( rCmd.nVerbosity )
50 sSlotMapFile = rCmd.aSlotMapFile;
53 SvIdlDataBase::~SvIdlDataBase()
55 aIdFileList.clear();
58 #define ADD_TYPE( Name ) \
59 aTypeList.push_back( new SvMetaType( SvHash_##Name()->GetName() ) );
61 SvRefMemberList<SvMetaType *>& SvIdlDataBase::GetTypeList()
63 if( aTypeList.empty() )
64 { // fill initially
65 aTypeList.push_back( new SvMetaTypeString() );
66 aTypeList.push_back( new SvMetaTypevoid() );
68 // MI: IDispatch::Invoke can not unsigned
69 ADD_TYPE( UINT16 );
70 ADD_TYPE( INT16 );
71 ADD_TYPE( UINT32 );
72 ADD_TYPE( INT32 );
73 ADD_TYPE( BOOL );
74 ADD_TYPE( BYTE );
75 ADD_TYPE( float );
76 ADD_TYPE( double );
77 ADD_TYPE( SbxObject );
79 // Attention! When adding types all binary data bases get incompatible
82 return aTypeList;
85 void SvIdlDataBase::SetError( const OString& rError, SvToken const & rTok )
87 if( rTok.GetLine() > 10000 )
88 aError.SetText( "line count overflow" );
90 if( aError.nLine < rTok.GetLine()
91 || (aError.nLine == rTok.GetLine() && aError.nColumn < rTok.GetColumn()) )
93 aError = SvIdlError( rTok.GetLine(), rTok.GetColumn() );
94 aError.SetText( rError );
98 void SvIdlDataBase::SetAndWriteError( SvTokenStream & rInStm, const OString& rError )
100 SetError( rError, rInStm.GetToken() );
101 WriteError( rInStm );
104 void SvIdlDataBase::Push( SvMetaObject * pObj )
106 GetStack().push_back( pObj );
109 bool SvIdlDataBase::FindId( const OString& rIdName, sal_uLong * pVal )
111 if( pIdTable )
113 sal_uInt32 nHash;
114 if( pIdTable->Test( rIdName, &nHash ) )
116 *pVal = pIdTable->Get( nHash )->GetValue();
117 return true;
120 return false;
123 void SvIdlDataBase::InsertId( const OString& rIdName, sal_uLong nVal )
125 if( !pIdTable )
126 pIdTable.reset( new SvStringHashTable );
128 sal_uInt32 nHash;
129 pIdTable->Insert( rIdName, &nHash )->SetValue( nVal );
132 bool SvIdlDataBase::ReadIdFile( const OString& rOFileName )
134 OUString rFileName = OStringToOUString(rOFileName, RTL_TEXTENCODING_ASCII_US);
135 OUString aFullName;
136 osl::File::searchFileURL( rFileName, GetPath(), aFullName);
137 osl::FileBase::getSystemPathFromFileURL( aFullName, aFullName );
139 for ( size_t i = 0, n = aIdFileList.size(); i < n; ++i )
140 if ( aIdFileList[ i ] == rFileName )
141 return true;
143 aIdFileList.push_back( rFileName );
144 AddDepFile( aFullName );
145 SvTokenStream aTokStm( aFullName );
146 if( aTokStm.GetStream().GetError() != ERRCODE_NONE )
147 return false;
149 SvToken& rTok = aTokStm.GetToken_Next();
151 while( !rTok.IsEof() )
153 if( rTok.IsChar() && rTok.GetChar() == '#' )
155 rTok = aTokStm.GetToken_Next();
156 if( rTok.Is( SvHash_define() ) )
158 rTok = aTokStm.GetToken_Next();
159 OString aDefName;
160 if( !rTok.IsIdentifier() )
161 throw SvParseException( "unexpected token after define", rTok );
162 aDefName = rTok.GetString();
164 sal_uLong nVal = 0;
165 bool bOk = true;
166 while( bOk )
168 rTok = aTokStm.GetToken_Next();
169 if (rTok.GetTokenAsString().startsWith("TypedWhichId"))
171 rTok = aTokStm.GetToken_Next();
172 if( !rTok.IsChar() || rTok.GetChar() != '<')
173 throw SvParseException( "expected '<'", rTok );
174 rTok = aTokStm.GetToken_Next();
175 if( !rTok.IsIdentifier() )
176 throw SvParseException( "expected identifier", rTok );
177 rTok = aTokStm.GetToken_Next();
178 if( !rTok.IsChar() || rTok.GetChar() != '>')
179 throw SvParseException( "expected '<'", rTok );
180 rTok = aTokStm.GetToken_Next();
182 else if( rTok.IsIdentifier() )
184 sal_uLong n;
185 if( FindId( rTok.GetString(), &n ) )
186 nVal += n;
187 else
188 bOk = false;
190 else if( rTok.IsChar() )
192 if( rTok.GetChar() == '-'
193 || rTok.GetChar() == '/'
194 || rTok.GetChar() == '*'
195 || rTok.GetChar() == '&'
196 || rTok.GetChar() == '|'
197 || rTok.GetChar() == '^'
198 || rTok.GetChar() == '~' )
200 throw SvParseException( "unknown operator '" + OStringChar(rTok.GetChar()) + "'in define", rTok );
202 if( rTok.GetChar() != '+'
203 && rTok.GetChar() != '('
204 && rTok.GetChar() != ')' )
205 // only + is allowed, parentheses are immaterial
206 // because + is commutative
207 break;
209 else if( rTok.IsInteger() )
211 nVal += rTok.GetNumber();
213 else
214 break;
216 if( bOk )
218 InsertId( aDefName, nVal );
221 else if( rTok.Is( SvHash_include() ) )
223 rTok = aTokStm.GetToken_Next();
224 OStringBuffer aNameBuf(128);
225 if( rTok.IsString() )
226 aNameBuf.append(rTok.GetString());
227 else if( rTok.IsChar() && rTok.GetChar() == '<' )
229 rTok = aTokStm.GetToken_Next();
230 while( !rTok.IsEof()
231 && !(rTok.IsChar() && rTok.GetChar() == '>') )
233 aNameBuf.append(rTok.GetTokenAsString());
234 rTok = aTokStm.GetToken_Next();
236 if( rTok.IsEof() )
238 throw SvParseException("unexpected eof in #include", rTok);
241 OString aName(aNameBuf.makeStringAndClear());
242 if (aName == "sfx2/groupid.hxx")
244 // contains C++ code which we cannot parse
245 // we special-case this by defining a macro internally in...
247 else if (aName == "svl/typedwhich.hxx")
249 // contains C++ code which we cannot parse
251 else if (!ReadIdFile(aName))
253 throw SvParseException("cannot read file: " + aName, rTok);
257 else
258 rTok = aTokStm.GetToken_Next();
260 return true;
263 SvMetaType * SvIdlDataBase::FindType( const SvMetaType * pPType,
264 SvRefMemberList<SvMetaType *>& rList )
266 for (auto const& elem : rList)
267 if( elem == pPType )
268 return elem;
269 return nullptr;
272 SvMetaType * SvIdlDataBase::FindType( const OString& rName )
274 for (auto const& elem : aTypeList)
275 if( rName == elem->GetName() )
276 return elem;
277 return nullptr;
280 SvMetaType * SvIdlDataBase::ReadKnownType( SvTokenStream & rInStm )
282 sal_uInt32 nTokPos = rInStm.Tell();
283 SvToken& rTok = rInStm.GetToken_Next();
285 if( rTok.IsIdentifier() )
287 const OString& aName = rTok.GetString();
288 for( const auto& aType : GetTypeList() )
290 if( aType->GetName() == aName )
292 return aType;
296 rInStm.Seek( nTokPos );
297 return nullptr;
300 SvMetaAttribute * SvIdlDataBase::ReadKnownAttr
302 SvTokenStream & rInStm,
303 SvMetaType * pType /* If pType == NULL, then the type has
304 still to be read. */
307 sal_uInt32 nTokPos = rInStm.Tell();
309 if( !pType )
310 pType = ReadKnownType( rInStm );
312 if( !pType )
314 // otherwise SlotId?
315 SvToken& rTok = rInStm.GetToken_Next();
316 if( rTok.IsIdentifier() )
318 sal_uLong n;
319 if( FindId( rTok.GetString(), &n ) )
321 for( sal_uLong i = 0; i < aSlotList.size(); i++ )
323 SvMetaSlot * pSlot = aSlotList[i];
324 if( pSlot->GetSlotId().getString() == rTok.GetString() )
325 return pSlot;
329 OStringBuffer aStr("Not found : ");
330 aStr.append(rTok.GetString());
331 OSL_FAIL(aStr.getStr());
335 rInStm.Seek( nTokPos );
336 return nullptr;
339 SvMetaAttribute* SvIdlDataBase::FindKnownAttr( const SvIdentifier& rId )
341 sal_uLong n;
342 if( FindId( rId.getString(), &n ) )
344 for( sal_uLong i = 0; i < aSlotList.size(); i++ )
346 SvMetaSlot * pSlot = aSlotList[i];
347 if( pSlot->GetSlotId().getString() == rId.getString() )
348 return pSlot;
352 return nullptr;
355 SvMetaClass * SvIdlDataBase::ReadKnownClass( SvTokenStream & rInStm )
357 sal_uInt32 nTokPos = rInStm.Tell();
358 SvToken& rTok = rInStm.GetToken_Next();
360 if( rTok.IsIdentifier() )
362 SvMetaClass* p = FindKnownClass(rTok.GetString());
363 if (p)
364 return p;
367 rInStm.Seek( nTokPos );
368 return nullptr;
371 SvMetaClass * SvIdlDataBase::FindKnownClass( const OString& aName )
373 for( sal_uLong n = 0; n < aClassList.size(); n++ )
375 SvMetaClass * pClass = aClassList[n];
376 if( pClass->GetName() == aName )
377 return pClass;
379 return nullptr;
382 void SvIdlDataBase::Write(const OString& rText) const
384 if( nVerbosity != 0 )
385 fprintf( stdout, "%s", rText.getStr() );
388 void SvIdlDataBase::WriteError( SvTokenStream & rInStm )
390 // error treatment
391 OUString aFileName( rInStm.GetFileName() );
392 OStringBuffer aErrorText;
393 sal_uLong nRow = 0, nColumn = 0;
395 rInStm.SeekToMax();
396 SvToken& rTok = rInStm.GetToken();
398 // error position
399 nRow = rTok.GetLine();
400 nColumn = rTok.GetColumn();
402 if( aError.IsError() )
403 { // error set
404 // search error token
405 // error text
406 if( !aError.GetText().isEmpty() )
408 aErrorText.append("may be <");
409 aErrorText.append(aError.GetText());
411 SvToken * pPrevTok = nullptr;
412 while( &rTok != pPrevTok )
414 pPrevTok = &rTok;
415 if( rTok.GetLine() == aError.nLine
416 && rTok.GetColumn() == aError.nColumn )
417 break;
418 rTok = rInStm.GetToken_PrevAll();
421 // error position
422 aErrorText.append("> at ( ");
423 aErrorText.append(static_cast<sal_Int64>(aError.nLine));
424 aErrorText.append(", ");
425 aErrorText.append(static_cast<sal_Int64>(aError.nColumn));
426 aErrorText.append(" )");
428 // reset error
429 aError = SvIdlError();
432 // error treatment
433 fprintf( stderr, "\n%s --- %s: ( %" SAL_PRIuUINTPTR ", %" SAL_PRIuUINTPTR " )\n",
434 OUStringToOString(aFileName, RTL_TEXTENCODING_UTF8).getStr(),
435 "error", nRow, nColumn );
437 if( !aErrorText.isEmpty() )
438 { // error set
439 fprintf( stderr, "\t%s\n", aErrorText.getStr() );
442 // look for identifier close by
443 if( !rTok.IsIdentifier() )
445 rInStm.GetToken_PrevAll();
446 rTok = rInStm.GetToken();
448 if( rTok.IsIdentifier() )
450 OString aN = GetIdlApp().pHashTable->GetNearString( rTok.GetString() );
451 if( !aN.isEmpty() )
452 fprintf( stderr, "%s versus %s\n", rTok.GetString().getStr(), aN.getStr() );
456 SvIdlWorkingBase::SvIdlWorkingBase(const SvCommand& rCmd) : SvIdlDataBase(rCmd)
461 bool SvIdlWorkingBase::WriteSfx( SvStream & rOutStm )
463 if( rOutStm.GetError() != ERRCODE_NONE )
464 return false;
466 // reset all tmp variables for writing
467 WriteReset();
468 SvMemoryStream aTmpStm( 256000, 256000 );
469 sal_uLong n;
470 for( n = 0; n < GetModuleList().size(); n++ )
472 SvMetaModule * pModule = GetModuleList()[n];
473 pModule->WriteSfx( *this, aTmpStm );
474 aTmpStm.Seek( 0 );
476 for( n = 0; n < aUsedTypes.size(); n++ )
478 SvMetaType * pType = aUsedTypes[n];
479 pType->WriteSfx( *this, rOutStm );
481 aUsedTypes.clear();
482 rOutStm.WriteStream( aTmpStm );
483 return true;
486 void SvIdlDataBase::StartNewFile( const OUString& rName )
488 bExport = aExportFile.equalsIgnoreAsciiCase( rName );
489 assert ( !bExport );
492 void SvIdlDataBase::AppendSlot( SvMetaSlot *pSlot )
494 aSlotList.push_back( pSlot );
495 assert ( !bExport );
498 void SvIdlDataBase::AddDepFile(OUString const& rFileName)
500 m_DepFiles.insert(rFileName);
503 struct WriteDep
505 SvFileStream & m_rStream;
506 explicit WriteDep(SvFileStream & rStream) : m_rStream(rStream) { }
507 void operator() (OUString const& rItem)
509 m_rStream.WriteCharPtr( " \\\n " );
510 m_rStream.WriteOString( OUStringToOString(rItem, RTL_TEXTENCODING_UTF8) );
514 // write a dummy target for one included file, so the incremental build does
515 // not break with "No rule to make target" if the included file is removed
516 struct WriteDummy
518 SvFileStream & m_rStream;
519 explicit WriteDummy(SvFileStream & rStream) : m_rStream(rStream) { }
520 void operator() (OUString const& rItem)
522 m_rStream.WriteOString( OUStringToOString(rItem, RTL_TEXTENCODING_UTF8) );
523 m_rStream.WriteCharPtr( " :\n\n" );
527 void SvIdlDataBase::WriteDepFile(
528 SvFileStream & rStream, OUString const& rTarget)
530 rStream.WriteOString( OUStringToOString(rTarget, RTL_TEXTENCODING_UTF8) );
531 rStream.WriteCharPtr( " :" );
532 ::std::for_each(m_DepFiles.begin(), m_DepFiles.end(), WriteDep(rStream));
533 rStream.WriteCharPtr( "\n\n" );
534 ::std::for_each(m_DepFiles.begin(), m_DepFiles.end(), WriteDummy(rStream));
537 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */