summaryrefslogtreecommitdiffstats
path: root/idl/source/prj/database.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'idl/source/prj/database.cxx')
-rw-r--r--idl/source/prj/database.cxx553
1 files changed, 553 insertions, 0 deletions
diff --git a/idl/source/prj/database.cxx b/idl/source/prj/database.cxx
new file mode 100644
index 000000000..9aba715ed
--- /dev/null
+++ b/idl/source/prj/database.cxx
@@ -0,0 +1,553 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <algorithm>
+#include <stdio.h>
+#include <string_view>
+
+#include <command.hxx>
+#include <database.hxx>
+#include <globals.hxx>
+#include <slot.hxx>
+#include <rtl/strbuf.hxx>
+#include <osl/file.hxx>
+
+
+SvParseException::SvParseException( SvTokenStream const & rInStm, const OString& rError )
+{
+ SvToken& rTok = rInStm.GetToken();
+ aError = SvIdlError( rTok.GetLine(), rTok.GetColumn() );
+ aError.SetText( rError );
+};
+
+SvParseException::SvParseException( const OString& rError, SvToken const & rTok )
+{
+ aError = SvIdlError( rTok.GetLine(), rTok.GetColumn() );
+ aError.SetText( rError );
+};
+
+
+SvIdlDataBase::SvIdlDataBase( const SvCommand& rCmd )
+ : bExport( false )
+ , nUniqueId( 0 )
+ , nVerbosity( rCmd.nVerbosity )
+{
+ sSlotMapFile = rCmd.aSlotMapFile;
+}
+
+SvIdlDataBase::~SvIdlDataBase()
+{
+ aIdFileList.clear();
+}
+
+#define ADD_TYPE( Name ) \
+ aTypeList.push_back( new SvMetaType( SvHash_##Name()->GetName() ) );
+
+SvRefMemberList<SvMetaType *>& SvIdlDataBase::GetTypeList()
+{
+ if( aTypeList.empty() )
+ { // fill initially
+ aTypeList.push_back( new SvMetaTypeString() );
+ aTypeList.push_back( new SvMetaTypevoid() );
+
+ // MI: IDispatch::Invoke can not unsigned
+ ADD_TYPE( UINT16 );
+ ADD_TYPE( INT16 );
+ ADD_TYPE( UINT32 );
+ ADD_TYPE( INT32 );
+ ADD_TYPE( BOOL );
+ ADD_TYPE( BYTE );
+ ADD_TYPE( float );
+ ADD_TYPE( double );
+ ADD_TYPE( SbxObject );
+
+ // Attention! When adding types all binary data bases get incompatible
+
+ }
+ return aTypeList;
+}
+
+void SvIdlDataBase::SetError( const OString& rError, SvToken const & rTok )
+{
+ if( rTok.GetLine() > 10000 )
+ aError.SetText( "line count overflow" );
+
+ if( aError.nLine < rTok.GetLine()
+ || (aError.nLine == rTok.GetLine() && aError.nColumn < rTok.GetColumn()) )
+ {
+ aError = SvIdlError( rTok.GetLine(), rTok.GetColumn() );
+ aError.SetText( rError );
+ }
+}
+
+void SvIdlDataBase::SetAndWriteError( SvTokenStream & rInStm, const OString& rError )
+{
+ SetError( rError, rInStm.GetToken() );
+ WriteError( rInStm );
+}
+
+void SvIdlDataBase::Push( SvMetaObject * pObj )
+{
+ GetStack().push_back( pObj );
+}
+
+bool SvIdlDataBase::FindId( const OString& rIdName, sal_uInt32 * pVal )
+{
+ if( pIdTable )
+ {
+ sal_uInt32 nHash;
+ if( pIdTable->Test( rIdName, &nHash ) )
+ {
+ *pVal = pIdTable->Get( nHash )->GetValue();
+ return true;
+ }
+ }
+ return false;
+}
+
+void SvIdlDataBase::InsertId( const OString& rIdName, sal_uInt32 nVal )
+{
+ if( !pIdTable )
+ pIdTable.reset( new SvStringHashTable );
+
+ sal_uInt32 nHash;
+ pIdTable->Insert( rIdName, &nHash )->SetValue( nVal );
+}
+
+bool SvIdlDataBase::ReadIdFile( std::string_view rOFileName )
+{
+ OUString rFileName = OStringToOUString(rOFileName, RTL_TEXTENCODING_ASCII_US);
+ OUString aFullName;
+ osl::File::searchFileURL( rFileName, GetPath(), aFullName);
+ osl::FileBase::getSystemPathFromFileURL( aFullName, aFullName );
+
+ for ( size_t i = 0, n = aIdFileList.size(); i < n; ++i )
+ if ( aIdFileList[ i ] == rFileName )
+ return true;
+
+ aIdFileList.push_back( rFileName );
+ AddDepFile( aFullName );
+ SvTokenStream aTokStm( aFullName );
+ if( aTokStm.GetStream().GetError() != ERRCODE_NONE )
+ return false;
+
+ SvToken& rTok = aTokStm.GetToken_Next();
+
+ while( !rTok.IsEof() )
+ {
+ if( rTok.IsChar() && rTok.GetChar() == '#' )
+ {
+ rTok = aTokStm.GetToken_Next();
+ if( rTok.Is( SvHash_define() ) )
+ {
+ rTok = aTokStm.GetToken_Next();
+ OString aDefName;
+ if( !rTok.IsIdentifier() )
+ throw SvParseException( "unexpected token after define", rTok );
+ aDefName = rTok.GetString();
+
+ sal_uInt32 nVal = 0;
+ bool bOk = true;
+ while( bOk )
+ {
+ rTok = aTokStm.GetToken_Next();
+ if (rTok.GetTokenAsString().startsWith("TypedWhichId"))
+ {
+ rTok = aTokStm.GetToken_Next();
+ if( !rTok.IsChar() || rTok.GetChar() != '<')
+ throw SvParseException( "expected '<'", rTok );
+ rTok = aTokStm.GetToken_Next();
+ if (rTok.IsChar() && rTok.GetChar() == ':')
+ {
+ // add support for "::avmedia::MediaItem" namespaced identifier
+ rTok = aTokStm.GetToken_Next();
+ if( !rTok.IsChar() || rTok.GetChar() != ':')
+ throw SvParseException( "expected ':'", rTok );
+ // the lexer reads "avmedia::MediaItem" as an identifier
+ rTok = aTokStm.GetToken_Next();
+ if( !rTok.IsIdentifier() )
+ throw SvParseException( "expected identifier", rTok );
+ }
+ else if( !rTok.IsIdentifier() )
+ throw SvParseException( "expected identifier", rTok );
+ rTok = aTokStm.GetToken_Next();
+ if( !rTok.IsChar() || rTok.GetChar() != '>')
+ throw SvParseException( "expected '<'", rTok );
+ rTok = aTokStm.GetToken_Next();
+ }
+ else if( rTok.IsIdentifier() )
+ {
+ sal_uInt32 n;
+ if( FindId( rTok.GetString(), &n ) )
+ nVal += n;
+ else
+ bOk = false;
+ }
+ else if( rTok.IsChar() )
+ {
+ if( rTok.GetChar() == '-'
+ || rTok.GetChar() == '/'
+ || rTok.GetChar() == '*'
+ || rTok.GetChar() == '&'
+ || rTok.GetChar() == '|'
+ || rTok.GetChar() == '^'
+ || rTok.GetChar() == '~' )
+ {
+ throw SvParseException( "unknown operator '" + OStringChar(rTok.GetChar()) + "'in define", rTok );
+ }
+ if( rTok.GetChar() != '+'
+ && rTok.GetChar() != '('
+ && rTok.GetChar() != ')' )
+ // only + is allowed, parentheses are immaterial
+ // because + is commutative
+ break;
+ }
+ else if( rTok.IsInteger() )
+ {
+ nVal += rTok.GetNumber();
+ }
+ else
+ break;
+ }
+ if( bOk )
+ {
+ InsertId( aDefName, nVal );
+ }
+ }
+ else if( rTok.Is( SvHash_include() ) )
+ {
+ rTok = aTokStm.GetToken_Next();
+ OStringBuffer aNameBuf(128);
+ if( rTok.IsString() )
+ aNameBuf.append(rTok.GetString());
+ else if( rTok.IsChar() && rTok.GetChar() == '<' )
+ {
+ rTok = aTokStm.GetToken_Next();
+ while( !rTok.IsEof()
+ && !(rTok.IsChar() && rTok.GetChar() == '>') )
+ {
+ aNameBuf.append(rTok.GetTokenAsString());
+ rTok = aTokStm.GetToken_Next();
+ }
+ if( rTok.IsEof() )
+ {
+ throw SvParseException("unexpected eof in #include", rTok);
+ }
+ }
+ OString aName(aNameBuf.makeStringAndClear());
+ if (aName == "sfx2/groupid.hxx")
+ {
+ // contains C++ code which we cannot parse
+ // we special-case this by defining a macro internally in...
+ }
+ else if (aName == "svl/typedwhich.hxx")
+ {
+ // contains C++ code which we cannot parse
+ }
+ else if (!ReadIdFile(aName))
+ {
+ throw SvParseException("cannot read file: " + aName, rTok);
+ }
+ }
+ }
+ else
+ rTok = aTokStm.GetToken_Next();
+ }
+ return true;
+}
+
+SvMetaType * SvIdlDataBase::FindType( const SvMetaType * pPType,
+ SvRefMemberList<SvMetaType *>& rList )
+{
+ for (auto const& elem : rList)
+ if( elem == pPType )
+ return elem;
+ return nullptr;
+}
+
+SvMetaType * SvIdlDataBase::FindType( std::string_view rName )
+{
+ for (auto const& elem : aTypeList)
+ if( rName == elem->GetName() )
+ return elem;
+ return nullptr;
+}
+
+SvMetaType * SvIdlDataBase::ReadKnownType( SvTokenStream & rInStm )
+{
+ sal_uInt32 nTokPos = rInStm.Tell();
+ SvToken& rTok = rInStm.GetToken_Next();
+
+ if( rTok.IsIdentifier() )
+ {
+ const OString& aName = rTok.GetString();
+ for( const auto& aType : GetTypeList() )
+ {
+ if( aType->GetName() == aName )
+ {
+ return aType;
+ }
+ }
+ }
+ rInStm.Seek( nTokPos );
+ return nullptr;
+}
+
+SvMetaAttribute * SvIdlDataBase::ReadKnownAttr
+(
+ SvTokenStream & rInStm,
+ SvMetaType * pType /* If pType == NULL, then the type has
+ still to be read. */
+)
+{
+ sal_uInt32 nTokPos = rInStm.Tell();
+
+ if( !pType )
+ pType = ReadKnownType( rInStm );
+
+ if( !pType )
+ {
+ // otherwise SlotId?
+ SvToken& rTok = rInStm.GetToken_Next();
+ if( rTok.IsIdentifier() )
+ {
+ sal_uInt32 n;
+ if( FindId( rTok.GetString(), &n ) )
+ {
+ for( size_t i = 0; i < aSlotList.size(); i++ )
+ {
+ SvMetaSlot * pSlot = aSlotList[i];
+ if( pSlot->GetSlotId().getString() == rTok.GetString() )
+ return pSlot;
+ }
+ }
+
+ OSL_FAIL(OString("Not found : " + rTok.GetString()).getStr());
+ }
+ }
+
+ rInStm.Seek( nTokPos );
+ return nullptr;
+}
+
+SvMetaAttribute* SvIdlDataBase::FindKnownAttr( const SvIdentifier& rId )
+{
+ sal_uInt32 n;
+ if( FindId( rId.getString(), &n ) )
+ {
+ for( size_t i = 0; i < aSlotList.size(); i++ )
+ {
+ SvMetaSlot * pSlot = aSlotList[i];
+ if( pSlot->GetSlotId().getString() == rId.getString() )
+ return pSlot;
+ }
+ }
+
+ return nullptr;
+}
+
+SvMetaClass * SvIdlDataBase::ReadKnownClass( SvTokenStream & rInStm )
+{
+ sal_uInt32 nTokPos = rInStm.Tell();
+ SvToken& rTok = rInStm.GetToken_Next();
+
+ if( rTok.IsIdentifier() )
+ {
+ SvMetaClass* p = FindKnownClass(rTok.GetString());
+ if (p)
+ return p;
+ }
+
+ rInStm.Seek( nTokPos );
+ return nullptr;
+}
+
+SvMetaClass * SvIdlDataBase::FindKnownClass( std::string_view aName )
+{
+ for( size_t n = 0; n < aClassList.size(); n++ )
+ {
+ SvMetaClass * pClass = aClassList[n];
+ if( pClass->GetName() == aName )
+ return pClass;
+ }
+ return nullptr;
+}
+
+void SvIdlDataBase::Write(const OString& rText) const
+{
+ if( nVerbosity != 0 )
+ fprintf( stdout, "%s", rText.getStr() );
+}
+
+void SvIdlDataBase::WriteError( SvTokenStream & rInStm )
+{
+ // error treatment
+ OUString aFileName( rInStm.GetFileName() );
+ OStringBuffer aErrorText;
+ sal_uInt64 nRow = 0, nColumn = 0;
+
+ rInStm.SeekToMax();
+ SvToken& rTok = rInStm.GetToken();
+
+ // error position
+ nRow = rTok.GetLine();
+ nColumn = rTok.GetColumn();
+
+ if( aError.IsError() )
+ { // error set
+ // search error token
+ // error text
+ if( !aError.GetText().isEmpty() )
+ {
+ aErrorText.append("may be <");
+ aErrorText.append(aError.GetText());
+ }
+ SvToken * pPrevTok = nullptr;
+ while( &rTok != pPrevTok )
+ {
+ pPrevTok = &rTok;
+ if( rTok.GetLine() == aError.nLine
+ && rTok.GetColumn() == aError.nColumn )
+ break;
+ rTok = rInStm.GetToken_PrevAll();
+ }
+
+ // error position
+ aErrorText.append("> at ( ");
+ aErrorText.append(static_cast<sal_Int64>(aError.nLine));
+ aErrorText.append(", ");
+ aErrorText.append(static_cast<sal_Int64>(aError.nColumn));
+ aErrorText.append(" )");
+
+ // reset error
+ aError = SvIdlError();
+ }
+
+ // error treatment
+ fprintf( stderr, "\n%s --- %s: ( %" SAL_PRIuUINT64 ", %" SAL_PRIuUINT64 " )\n",
+ OUStringToOString(aFileName, RTL_TEXTENCODING_UTF8).getStr(),
+ "error", nRow, nColumn );
+
+ if( !aErrorText.isEmpty() )
+ { // error set
+ fprintf( stderr, "\t%s\n", aErrorText.getStr() );
+ }
+
+ // look for identifier close by
+ if( !rTok.IsIdentifier() )
+ {
+ rInStm.GetToken_PrevAll();
+ rTok = rInStm.GetToken();
+ }
+ if( rTok.IsIdentifier() )
+ {
+ OString aN = GetIdlApp().pHashTable->GetNearString( rTok.GetString() );
+ if( !aN.isEmpty() )
+ fprintf( stderr, "%s versus %s\n", rTok.GetString().getStr(), aN.getStr() );
+ }
+}
+
+SvIdlWorkingBase::SvIdlWorkingBase(const SvCommand& rCmd) : SvIdlDataBase(rCmd)
+{
+}
+
+
+bool SvIdlWorkingBase::WriteSfx( SvStream & rOutStm )
+{
+ if( rOutStm.GetError() != ERRCODE_NONE )
+ return false;
+
+ // reset all tmp variables for writing
+ WriteReset();
+ SvMemoryStream aTmpStm( 256000, 256000 );
+ size_t n;
+ for( n = 0; n < GetModuleList().size(); n++ )
+ {
+ SvMetaModule * pModule = GetModuleList()[n];
+ pModule->WriteSfx( *this, aTmpStm );
+ aTmpStm.Seek( 0 );
+ }
+ for( n = 0; n < aUsedTypes.size(); n++ )
+ {
+ SvMetaType * pType = aUsedTypes[n];
+ pType->WriteSfx( *this, rOutStm );
+ }
+ aUsedTypes.clear();
+ rOutStm.WriteStream( aTmpStm );
+ return true;
+}
+
+void SvIdlDataBase::StartNewFile( std::u16string_view rName )
+{
+ bExport = aExportFile.equalsIgnoreAsciiCase( rName );
+ assert ( !bExport );
+}
+
+void SvIdlDataBase::AppendSlot( SvMetaSlot *pSlot )
+{
+ aSlotList.push_back( pSlot );
+ assert ( !bExport );
+}
+
+void SvIdlDataBase::AddDepFile(OUString const& rFileName)
+{
+ m_DepFiles.insert(rFileName);
+}
+
+namespace {
+
+struct WriteDep
+{
+ SvFileStream & m_rStream;
+ explicit WriteDep(SvFileStream & rStream) : m_rStream(rStream) { }
+ void operator() (std::u16string_view rItem)
+ {
+ m_rStream.WriteCharPtr( " \\\n " );
+ m_rStream.WriteOString( OUStringToOString(rItem, RTL_TEXTENCODING_UTF8) );
+ }
+};
+
+// write a dummy target for one included file, so the incremental build does
+// not break with "No rule to make target" if the included file is removed
+struct WriteDummy
+{
+ SvFileStream & m_rStream;
+ explicit WriteDummy(SvFileStream & rStream) : m_rStream(rStream) { }
+ void operator() (std::u16string_view rItem)
+ {
+ m_rStream.WriteOString( OUStringToOString(rItem, RTL_TEXTENCODING_UTF8) );
+ m_rStream.WriteCharPtr( " :\n\n" );
+ }
+};
+
+}
+
+void SvIdlDataBase::WriteDepFile(
+ SvFileStream & rStream, std::u16string_view rTarget)
+{
+ rStream.WriteOString( OUStringToOString(rTarget, RTL_TEXTENCODING_UTF8) );
+ rStream.WriteCharPtr( " :" );
+ ::std::for_each(m_DepFiles.begin(), m_DepFiles.end(), WriteDep(rStream));
+ rStream.WriteCharPtr( "\n\n" );
+ ::std::for_each(m_DepFiles.begin(), m_DepFiles.end(), WriteDummy(rStream));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */