Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / idl / source / prj / database.cxx
blob699d90e0f91333cdb0bf1311a5ba422c1d41f6fe
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 <string_view>
26 #include <command.hxx>
27 #include <database.hxx>
28 #include <globals.hxx>
29 #include <slot.hxx>
30 #include <rtl/strbuf.hxx>
31 #include <osl/file.hxx>
34 SvParseException::SvParseException( SvTokenStream const & rInStm, const OString& rError )
36 SvToken& rTok = rInStm.GetToken();
37 aError = SvIdlError( rTok.GetLine(), rTok.GetColumn() );
38 aError.SetText( rError );
41 SvParseException::SvParseException( const OString& rError, SvToken const & rTok )
43 aError = SvIdlError( rTok.GetLine(), rTok.GetColumn() );
44 aError.SetText( rError );
48 SvIdlDataBase::SvIdlDataBase( const SvCommand& rCmd )
49 : bExport( false )
50 , nUniqueId( 0 )
51 , nVerbosity( rCmd.nVerbosity )
53 sSlotMapFile = rCmd.aSlotMapFile;
56 SvIdlDataBase::~SvIdlDataBase()
58 aIdFileList.clear();
61 #define ADD_TYPE( Name ) \
62 aTypeList.push_back( new SvMetaType( SvHash_##Name()->GetName() ) );
64 SvRefMemberList<SvMetaType *>& SvIdlDataBase::GetTypeList()
66 if( aTypeList.empty() )
67 { // fill initially
68 aTypeList.push_back( new SvMetaTypeString() );
69 aTypeList.push_back( new SvMetaTypevoid() );
71 // MI: IDispatch::Invoke can not unsigned
72 ADD_TYPE( UINT16 );
73 ADD_TYPE( INT16 );
74 ADD_TYPE( UINT32 );
75 ADD_TYPE( INT32 );
76 ADD_TYPE( BOOL );
77 ADD_TYPE( BYTE );
78 ADD_TYPE( float );
79 ADD_TYPE( double );
80 ADD_TYPE( SbxObject );
82 // Attention! When adding types all binary data bases get incompatible
85 return aTypeList;
88 void SvIdlDataBase::SetError( const OString& rError, SvToken const & rTok )
90 if( rTok.GetLine() > 10000 )
91 aError.SetText( "line count overflow" );
93 if( aError.nLine < rTok.GetLine()
94 || (aError.nLine == rTok.GetLine() && aError.nColumn < rTok.GetColumn()) )
96 aError = SvIdlError( rTok.GetLine(), rTok.GetColumn() );
97 aError.SetText( rError );
101 void SvIdlDataBase::SetAndWriteError( SvTokenStream & rInStm, const OString& rError )
103 SetError( rError, rInStm.GetToken() );
104 WriteError( rInStm );
107 void SvIdlDataBase::Push( SvMetaObject * pObj )
109 GetStack().push_back( pObj );
112 bool SvIdlDataBase::FindId( const OString& rIdName, sal_uInt32 * pVal )
114 if( pIdTable )
116 sal_uInt32 nHash;
117 if( pIdTable->Test( rIdName, &nHash ) )
119 *pVal = pIdTable->Get( nHash )->GetValue();
120 return true;
123 return false;
126 void SvIdlDataBase::InsertId( const OString& rIdName, sal_uInt32 nVal )
128 if( !pIdTable )
129 pIdTable.reset( new SvStringHashTable );
131 sal_uInt32 nHash;
132 pIdTable->Insert( rIdName, &nHash )->SetValue( nVal );
135 bool SvIdlDataBase::ReadIdFile( std::string_view rOFileName )
137 OUString rFileName = OStringToOUString(rOFileName, RTL_TEXTENCODING_ASCII_US);
138 OUString aFullName;
139 osl::File::searchFileURL( rFileName, GetPath(), aFullName);
140 osl::FileBase::getSystemPathFromFileURL( aFullName, aFullName );
142 for ( size_t i = 0, n = aIdFileList.size(); i < n; ++i )
143 if ( aIdFileList[ i ] == rFileName )
144 return true;
146 aIdFileList.push_back( rFileName );
147 AddDepFile( aFullName );
148 SvTokenStream aTokStm( aFullName );
149 if( aTokStm.GetStream().GetError() != ERRCODE_NONE )
150 return false;
152 SvToken& rTok = aTokStm.GetToken_Next();
154 while( !rTok.IsEof() )
156 if( rTok.IsChar() && rTok.GetChar() == '#' )
158 rTok = aTokStm.GetToken_Next();
159 if( rTok.Is( SvHash_define() ) )
161 rTok = aTokStm.GetToken_Next();
162 OString aDefName;
163 if( !rTok.IsIdentifier() )
164 throw SvParseException( "unexpected token after define", rTok );
165 aDefName = rTok.GetString();
167 sal_uInt32 nVal = 0;
168 bool bOk = true;
169 while( bOk )
171 rTok = aTokStm.GetToken_Next();
172 if (rTok.GetTokenAsString().startsWith("TypedWhichId"))
174 rTok = aTokStm.GetToken_Next();
175 if( !rTok.IsChar() || rTok.GetChar() != '<')
176 throw SvParseException( "expected '<'", rTok );
177 rTok = aTokStm.GetToken_Next();
178 if (rTok.IsChar() && rTok.GetChar() == ':')
180 // add support for "::avmedia::MediaItem" namespaced identifier
181 rTok = aTokStm.GetToken_Next();
182 if( !rTok.IsChar() || rTok.GetChar() != ':')
183 throw SvParseException( "expected ':'", rTok );
184 // the lexer reads "avmedia::MediaItem" as an identifier
185 rTok = aTokStm.GetToken_Next();
186 if( !rTok.IsIdentifier() )
187 throw SvParseException( "expected identifier", rTok );
189 else if( !rTok.IsIdentifier() )
190 throw SvParseException( "expected identifier", rTok );
191 rTok = aTokStm.GetToken_Next();
192 if( !rTok.IsChar() || rTok.GetChar() != '>')
193 throw SvParseException( "expected '<'", rTok );
194 rTok = aTokStm.GetToken_Next();
196 else if( rTok.IsIdentifier() )
198 sal_uInt32 n;
199 if( FindId( rTok.GetString(), &n ) )
200 nVal += n;
201 else
202 bOk = false;
204 else if( rTok.IsChar() )
206 if( rTok.GetChar() == '-'
207 || rTok.GetChar() == '/'
208 || rTok.GetChar() == '*'
209 || rTok.GetChar() == '&'
210 || rTok.GetChar() == '|'
211 || rTok.GetChar() == '^'
212 || rTok.GetChar() == '~' )
214 throw SvParseException( "unknown operator '" + OStringChar(rTok.GetChar()) + "'in define", rTok );
216 if( rTok.GetChar() != '+'
217 && rTok.GetChar() != '('
218 && rTok.GetChar() != ')' )
219 // only + is allowed, parentheses are immaterial
220 // because + is commutative
221 break;
223 else if( rTok.IsInteger() )
225 nVal += rTok.GetNumber();
227 else
228 break;
230 if( bOk )
232 InsertId( aDefName, nVal );
235 else if( rTok.Is( SvHash_include() ) )
237 rTok = aTokStm.GetToken_Next();
238 OStringBuffer aNameBuf(128);
239 if( rTok.IsString() )
240 aNameBuf.append(rTok.GetString());
241 else if( rTok.IsChar() && rTok.GetChar() == '<' )
243 rTok = aTokStm.GetToken_Next();
244 while( !rTok.IsEof()
245 && !(rTok.IsChar() && rTok.GetChar() == '>') )
247 aNameBuf.append(rTok.GetTokenAsString());
248 rTok = aTokStm.GetToken_Next();
250 if( rTok.IsEof() )
252 throw SvParseException("unexpected eof in #include", rTok);
255 OString aName(aNameBuf.makeStringAndClear());
256 if (aName == "sfx2/groupid.hxx")
258 // contains C++ code which we cannot parse
259 // we special-case this by defining a macro internally in...
261 else if (aName == "svl/typedwhich.hxx")
263 // contains C++ code which we cannot parse
265 else if (!ReadIdFile(aName))
267 throw SvParseException("cannot read file: " + aName, rTok);
271 else
272 rTok = aTokStm.GetToken_Next();
274 return true;
277 SvMetaType * SvIdlDataBase::FindType( const SvMetaType * pPType,
278 SvRefMemberList<SvMetaType *>& rList )
280 for (auto const& elem : rList)
281 if( elem == pPType )
282 return elem;
283 return nullptr;
286 SvMetaType * SvIdlDataBase::FindType( std::string_view rName )
288 for (auto const& elem : aTypeList)
289 if( rName == elem->GetName() )
290 return elem;
291 return nullptr;
294 SvMetaType * SvIdlDataBase::ReadKnownType( SvTokenStream & rInStm )
296 sal_uInt32 nTokPos = rInStm.Tell();
297 SvToken& rTok = rInStm.GetToken_Next();
299 if( rTok.IsIdentifier() )
301 const OString& aName = rTok.GetString();
302 for( const auto& aType : GetTypeList() )
304 if( aType->GetName() == aName )
306 return aType;
310 rInStm.Seek( nTokPos );
311 return nullptr;
314 SvMetaAttribute * SvIdlDataBase::ReadKnownAttr
316 SvTokenStream & rInStm,
317 SvMetaType * pType /* If pType == NULL, then the type has
318 still to be read. */
321 sal_uInt32 nTokPos = rInStm.Tell();
323 if( !pType )
324 pType = ReadKnownType( rInStm );
326 if( !pType )
328 // otherwise SlotId?
329 SvToken& rTok = rInStm.GetToken_Next();
330 if( rTok.IsIdentifier() )
332 sal_uInt32 n;
333 if( FindId( rTok.GetString(), &n ) )
335 for( size_t i = 0; i < aSlotList.size(); i++ )
337 SvMetaSlot * pSlot = aSlotList[i];
338 if( pSlot->GetSlotId().getString() == rTok.GetString() )
339 return pSlot;
343 OSL_FAIL(OString("Not found : " + rTok.GetString()).getStr());
347 rInStm.Seek( nTokPos );
348 return nullptr;
351 SvMetaAttribute* SvIdlDataBase::FindKnownAttr( const SvIdentifier& rId )
353 sal_uInt32 n;
354 if( FindId( rId.getString(), &n ) )
356 for( size_t i = 0; i < aSlotList.size(); i++ )
358 SvMetaSlot * pSlot = aSlotList[i];
359 if( pSlot->GetSlotId().getString() == rId.getString() )
360 return pSlot;
364 return nullptr;
367 SvMetaClass * SvIdlDataBase::ReadKnownClass( SvTokenStream & rInStm )
369 sal_uInt32 nTokPos = rInStm.Tell();
370 SvToken& rTok = rInStm.GetToken_Next();
372 if( rTok.IsIdentifier() )
374 SvMetaClass* p = FindKnownClass(rTok.GetString());
375 if (p)
376 return p;
379 rInStm.Seek( nTokPos );
380 return nullptr;
383 SvMetaClass * SvIdlDataBase::FindKnownClass( std::string_view aName )
385 for( size_t n = 0; n < aClassList.size(); n++ )
387 SvMetaClass * pClass = aClassList[n];
388 if( pClass->GetName() == aName )
389 return pClass;
391 return nullptr;
394 void SvIdlDataBase::Write(const OString& rText) const
396 if( nVerbosity != 0 )
397 fprintf( stdout, "%s", rText.getStr() );
400 void SvIdlDataBase::WriteError( SvTokenStream & rInStm )
402 // error treatment
403 OUString aFileName( rInStm.GetFileName() );
404 OStringBuffer aErrorText;
405 sal_uInt64 nRow = 0, nColumn = 0;
407 rInStm.SeekToMax();
408 SvToken& rTok = rInStm.GetToken();
410 // error position
411 nRow = rTok.GetLine();
412 nColumn = rTok.GetColumn();
414 if( aError.IsError() )
415 { // error set
416 // search error token
417 // error text
418 if( !aError.GetText().isEmpty() )
420 aErrorText.append("may be <" + aError.GetText());
422 SvToken * pPrevTok = nullptr;
423 while( &rTok != pPrevTok )
425 pPrevTok = &rTok;
426 if( rTok.GetLine() == aError.nLine
427 && rTok.GetColumn() == aError.nColumn )
428 break;
429 rTok = rInStm.GetToken_PrevAll();
432 // error position
433 aErrorText.append("> at ( "
434 + OString::number(static_cast<sal_Int64>(aError.nLine))
435 + ", "
436 + OString::number(static_cast<sal_Int64>(aError.nColumn))
437 + " )");
439 // reset error
440 aError = SvIdlError();
443 // error treatment
444 fprintf( stderr, "\n%s --- %s: ( %" SAL_PRIuUINT64 ", %" SAL_PRIuUINT64 " )\n",
445 OUStringToOString(aFileName, RTL_TEXTENCODING_UTF8).getStr(),
446 "error", nRow, nColumn );
448 if( !aErrorText.isEmpty() )
449 { // error set
450 fprintf( stderr, "\t%s\n", aErrorText.getStr() );
453 // look for identifier close by
454 if( !rTok.IsIdentifier() )
456 rInStm.GetToken_PrevAll();
457 rTok = rInStm.GetToken();
459 if( rTok.IsIdentifier() )
461 OString aN = GetIdlApp().pHashTable->GetNearString( rTok.GetString() );
462 if( !aN.isEmpty() )
463 fprintf( stderr, "%s versus %s\n", rTok.GetString().getStr(), aN.getStr() );
467 SvIdlWorkingBase::SvIdlWorkingBase(const SvCommand& rCmd) : SvIdlDataBase(rCmd)
472 bool SvIdlWorkingBase::WriteSfx( SvStream & rOutStm )
474 if( rOutStm.GetError() != ERRCODE_NONE )
475 return false;
477 // reset all tmp variables for writing
478 WriteReset();
479 SvMemoryStream aTmpStm( 256000, 256000 );
480 size_t n;
481 for( n = 0; n < GetModuleList().size(); n++ )
483 SvMetaModule * pModule = GetModuleList()[n];
484 pModule->WriteSfx( *this, aTmpStm );
485 aTmpStm.Seek( 0 );
487 for( n = 0; n < aUsedTypes.size(); n++ )
489 SvMetaType * pType = aUsedTypes[n];
490 pType->WriteSfx( *this, rOutStm );
492 aUsedTypes.clear();
493 rOutStm.WriteStream( aTmpStm );
494 return true;
497 void SvIdlDataBase::StartNewFile( std::u16string_view rName )
499 bExport = aExportFile.equalsIgnoreAsciiCase( rName );
500 assert ( !bExport );
503 void SvIdlDataBase::AppendSlot( SvMetaSlot *pSlot )
505 aSlotList.push_back( pSlot );
506 assert ( !bExport );
509 void SvIdlDataBase::AddDepFile(OUString const& rFileName)
511 m_DepFiles.insert(rFileName);
514 namespace {
516 struct WriteDep
518 SvFileStream & m_rStream;
519 explicit WriteDep(SvFileStream & rStream) : m_rStream(rStream) { }
520 void operator() (std::u16string_view rItem)
522 m_rStream.WriteOString( " \\\n " );
523 m_rStream.WriteOString( OUStringToOString(rItem, RTL_TEXTENCODING_UTF8) );
527 // write a dummy target for one included file, so the incremental build does
528 // not break with "No rule to make target" if the included file is removed
529 struct WriteDummy
531 SvFileStream & m_rStream;
532 explicit WriteDummy(SvFileStream & rStream) : m_rStream(rStream) { }
533 void operator() (std::u16string_view rItem)
535 m_rStream.WriteOString( OUStringToOString(rItem, RTL_TEXTENCODING_UTF8) );
536 m_rStream.WriteOString( " :\n\n" );
542 void SvIdlDataBase::WriteDepFile(
543 SvFileStream & rStream, std::u16string_view rTarget)
545 rStream.WriteOString( OUStringToOString(rTarget, RTL_TEXTENCODING_UTF8) );
546 rStream.WriteOString( " :" );
547 ::std::for_each(m_DepFiles.begin(), m_DepFiles.end(), WriteDep(rStream));
548 rStream.WriteOString( "\n\n" );
549 ::std::for_each(m_DepFiles.begin(), m_DepFiles.end(), WriteDummy(rStream));
552 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */