diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:06:44 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:06:44 +0000 |
commit | ed5640d8b587fbcfed7dd7967f3de04b37a76f26 (patch) | |
tree | 7a5f7c6c9d02226d7471cb3cc8fbbf631b415303 /idl/source/prj | |
parent | Initial commit. (diff) | |
download | libreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.tar.xz libreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.zip |
Adding upstream version 4:7.4.7.upstream/4%7.4.7upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'idl/source/prj')
-rw-r--r-- | idl/source/prj/command.cxx | 296 | ||||
-rw-r--r-- | idl/source/prj/database.cxx | 553 | ||||
-rw-r--r-- | idl/source/prj/globals.cxx | 84 | ||||
-rw-r--r-- | idl/source/prj/parser.cxx | 590 | ||||
-rw-r--r-- | idl/source/prj/svidl.cxx | 213 |
5 files changed, 1736 insertions, 0 deletions
diff --git a/idl/source/prj/command.cxx b/idl/source/prj/command.cxx new file mode 100644 index 000000000..0c9436ce3 --- /dev/null +++ b/idl/source/prj/command.cxx @@ -0,0 +1,296 @@ +/* -*- 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 <stdlib.h> +#include <stdio.h> + +#include <osl/diagnose.h> +#include <rtl/character.hxx> + +#include <command.hxx> +#include <globals.hxx> +#include <database.hxx> +#include <parser.hxx> + +char const * const SyntaxStrings[] = { +"basic-type:", +"\tvoid| char| int| float| double|", +"\tUINT16| INT16| UINT32| INT32| BOOL|", +"\tBYTE| String| SbxObject", +"", +"{ import \"filename\" }\n", +"module definition:", +"module", +"\tunique id range (ask MM)", +"modul-name", +"'['", +"\tSlotIdFile( \"filename\" )", +"']'", +"'{'", +"\t{ include \"filename\" }\n", + +"\titem definition:", +"\titem type item-name;\n", + +"\ttype definition:", +"\tstruct identifier", +"\t'{'", +"\t\t{ type identifier }", +"\t'}'", +"\t|", +"\tenum identifier", +"\t'{'", +"\t\t{ identifier, }", +"\t'}'", +"\t|", +"\ttypedef type identifier\n", + +"\titem-method-args:", +"\t( { item parameter-name SLOT_ID } )\n", + +"\tslot definition:", +"\titem identifier SLOT_ID [ item-method-args ]", +"\t'['", +"\t\tAccelConfig, MenuConfig, ToolbarConfig", +"\t\tAutoUpdate", +"\t\tContainer", +"\t\tExecMethod = Identifier", +"\t\tFastCall", +"\t\tGroupId = Identifier", +"\t\tReadOnlyDoc*", +"\t\tRecordPerSet*, RecordPerItem, NoRecord", +"\t\tRecordAbsolute", +"\t\tStateMethod = Identifier", +"\t\tAsynchron", +"\t\tToggle", +"\t']'\n", + +"\tinterface definition:", +"\tshell | interface identifier ':' interface", +"\t'{'", +"\t\t{ slot }", +"\t'}'\n", +"---syntax example is sfx.idl---\n", +nullptr }; + +char const CommandLineSyntax[] = +"-fs<slotmap file>\n" +"-fm<makefile target file>\n" +"-help, ? @<file> response file\n" +" <filenames>\n"; + +void Init() +{ + if( !GetIdlApp().pHashTable ) + GetIdlApp().pHashTable.reset( new SvStringHashTable ); + if( !GetIdlApp().pGlobalNames ) + GetIdlApp().pGlobalNames.reset( new SvGlobalHashNames() ); +} + +bool ReadIdl( SvIdlWorkingBase * pDataBase, const SvCommand & rCommand ) +{ + for( size_t n = 0; n < rCommand.aInFileList.size(); ++n ) + { + OUString aFileName ( rCommand.aInFileList[ n ] ); + pDataBase->AddDepFile(aFileName); + SvTokenStream aTokStm( aFileName ); + try { + SvIdlParser aParser(*pDataBase, aTokStm); + aParser.ReadSvIdl( rCommand.aPath ); + } catch (const SvParseException& ex) { + pDataBase->SetError(ex.aError); + pDataBase->WriteError(aTokStm); + return false; + } + } + return true; +} + +static bool ResponseFile( std::vector<OUString> * pList, int argc, char ** argv ) +{ + // program name + pList->push_back( OUString::createFromAscii(*argv) ); + for( int i = 1; i < argc; i++ ) + { + if( '@' == **(argv +i) ) + { // when @, then response file + SvFileStream aStm( OUString::createFromAscii((*(argv +i)) +1), StreamMode::STD_READ ); + if( aStm.GetError() != ERRCODE_NONE ) + return false; + + OStringBuffer aStr; + while( aStm.ReadLine( aStr ) ) + { + sal_uInt16 n = 0; + sal_uInt16 nPos = 1; + while( n != nPos ) + { + while( aStr[n] + && rtl::isAsciiWhiteSpace( + static_cast<unsigned char>(aStr[n]) ) ) + n++; + nPos = n; + while( aStr[n] + && !rtl::isAsciiWhiteSpace( + static_cast<unsigned char>(aStr[n]) ) ) + n++; + if( n != nPos ) + pList->push_back( OStringToOUString(std::string_view(aStr).substr(nPos, n - nPos), RTL_TEXTENCODING_ASCII_US) ); + } + } + } + else if( argv[ i ] ) + pList->push_back( OUString::createFromAscii( argv[ i ] ) ); + } + return true; +} + +SvCommand::SvCommand( int argc, char ** argv ) + : nVerbosity(1) +{ + std::vector<OUString> aList; + + if( ResponseFile( &aList, argc, argv ) ) + { + for( size_t i = 1; i < aList.size(); i++ ) + { + OUString aParam( aList[ i ] ); + sal_Unicode aFirstChar( aParam[0] ); + if( '-' == aFirstChar ) + { + aParam = aParam.copy( 1 ); + aFirstChar = aParam[0]; + if( aFirstChar == 'F' || aFirstChar == 'f' ) + { + aParam = aParam.copy( 1 ); + aFirstChar = aParam[0]; + OUString aName( aParam.copy( 1 ) ); + if( 's' == aFirstChar ) + { // name of slot output + aSlotMapFile = aName; + } + else if( 'm' == aFirstChar ) + { // name of info file + aTargetFile = aName; + } + else if( 'x' == aFirstChar ) + { // name of IDL file for the CSV file + aExportFile = aName; + } + else if( 'M' == aFirstChar ) + { + m_DepFile = aName; + } + else + { + printf( + "unknown switch: %s\n", + OUStringToOString( + aParam, RTL_TEXTENCODING_UTF8).getStr()); + exit( -1 ); + } + } + else if( aParam.equalsIgnoreAsciiCase( "help" ) || aParam.equalsIgnoreAsciiCase( "?" ) ) + { // help + printf( "%s", CommandLineSyntax ); + } + else if( aParam.equalsIgnoreAsciiCase( "quiet" ) ) + { + nVerbosity = 0; + } + else if( aParam.equalsIgnoreAsciiCase( "verbose" ) ) + { + nVerbosity = 2; + } + else if( aParam.equalsIgnoreAsciiCase( "syntax" ) ) + { // help + int j = 0; + while(SyntaxStrings[j]) + printf("%s\n",SyntaxStrings[j++]); + } + else if (aParam == "isystem") + { + // ignore "-isystem" and following arg + if (i < aList.size()) + { + ++i; + } + } + else if (aParam.startsWith("isystem")) + { + // ignore args starting with "-isystem" + } + else if( aParam.startsWithIgnoreAsciiCase( "i" ) ) + { // define include paths + OUString aName( aParam.copy( 1 ) ); + if( !aPath.isEmpty() ) + aPath += OUStringChar(SAL_PATHSEPARATOR); + aPath += aName; + } + else if( aParam.startsWithIgnoreAsciiCase( "rsc" ) ) + { // first line in *.srs file + OSL_ENSURE(false, "does anything use this option, doesn't look like it belong here"); + if( !aList[ i + 1 ].isEmpty() ) + { + i++; + } + } + else + { + // temporary compatibility hack + printf( + "unknown switch: %s\n", + OUStringToOString( + aParam, RTL_TEXTENCODING_UTF8).getStr()); + exit( -1 ); + } + } + else + { + aInFileList.push_back( aParam ); + } + } + } + else + { + printf( "%s", CommandLineSyntax ); + } + + aList.clear(); + + auto const env = getenv("INCLUDE"); + OString aInc(env == nullptr ? "" : env); + // append include environment variable + if( aInc.getLength() ) + { + if( !aPath.isEmpty() ) + aPath += OUStringChar(SAL_PATHSEPARATOR); + aPath += OStringToOUString(aInc, RTL_TEXTENCODING_ASCII_US); + } +} + +SvCommand::~SvCommand() +{ + // release String list + aInFileList.clear(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 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: */ diff --git a/idl/source/prj/globals.cxx b/idl/source/prj/globals.cxx new file mode 100644 index 000000000..cf8d2ad44 --- /dev/null +++ b/idl/source/prj/globals.cxx @@ -0,0 +1,84 @@ +/* -*- 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 <globals.hxx> + +IdlDll & GetIdlApp() +{ + static IdlDll aIdlDll; + return aIdlDll; +} + +IdlDll::IdlDll() +{} + +IdlDll::~IdlDll() +{ +} + +static SvStringHashEntry * INS( const OString& rName ) +{ + sal_uInt32 nIdx; + GetIdlApp().pHashTable->Insert( rName, &nIdx ); + return GetIdlApp().pHashTable->Get( nIdx ); +} +#define A_ENTRY( Name ) , MM_##Name( INS( #Name ) ) + +SvGlobalHashNames::SvGlobalHashNames() + : MM_module( INS( "module" ) ) + , MM_interface( INS( "interface" ) ) + , MM_shell( INS( "shell" ) ) + , MM_Toggle( INS( "Toggle" ) ) + , MM_AutoUpdate( INS( "AutoUpdate" ) ) + , MM_Asynchron( INS( "Asynchron" ) ) + A_ENTRY(RecordPerSet) + A_ENTRY(RecordPerItem) + A_ENTRY(NoRecord) + A_ENTRY(RecordAbsolute) + A_ENTRY(enum) + A_ENTRY(UINT16) + A_ENTRY(INT16) + A_ENTRY(UINT32) + A_ENTRY(INT32) + A_ENTRY(BOOL) + A_ENTRY(BYTE) + A_ENTRY(float) + A_ENTRY(double) + A_ENTRY(item) + A_ENTRY(import) + A_ENTRY(SlotIdFile) + A_ENTRY(include) + A_ENTRY(ExecMethod) + A_ENTRY(StateMethod) + A_ENTRY(GroupId) + A_ENTRY(define) + A_ENTRY(MenuConfig) + A_ENTRY(ToolBoxConfig) + A_ENTRY(AccelConfig) + A_ENTRY(FastCall) + A_ENTRY(SbxObject) + A_ENTRY(Container) + A_ENTRY(ReadOnlyDoc) + A_ENTRY(struct) + A_ENTRY(DisableFlags) +{} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idl/source/prj/parser.cxx b/idl/source/prj/parser.cxx new file mode 100644 index 000000000..31bbee9a9 --- /dev/null +++ b/idl/source/prj/parser.cxx @@ -0,0 +1,590 @@ +/* -*- 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 <parser.hxx> +#include <database.hxx> +#include <globals.hxx> +#include <slot.hxx> +#include <osl/file.hxx> + +void SvIdlParser::ReadSvIdl( const OUString & rPath ) +{ + rBase.SetPath(rPath); // only valid for this iteration + SvToken& rTok = rInStm.GetToken(); + + while( true ) + { + rTok = rInStm.GetToken(); + if( rTok.IsEof() ) + return; + + Read( SvHash_module() ); + tools::SvRef<SvMetaModule> aModule = new SvMetaModule; + ReadModuleHeader(*aModule); + rBase.GetModuleList().push_back( aModule.get() ); + } +} + +void SvIdlParser::ReadModuleHeader(SvMetaModule& rModule) +{ + OString aName = ReadIdentifier(); + rModule.SetName( aName ); + rBase.Push( &rModule ); // onto the context stack + ReadModuleBody(rModule); + rBase.GetStack().pop_back(); // remove from stack +} + +void SvIdlParser::ReadModuleBody(SvMetaModule& rModule) +{ + if( ReadIf( '[' ) ) + { + while( true ) + { + OString aSlotIdFile; + if( !ReadStringSvIdl( SvHash_SlotIdFile(), rInStm, aSlotIdFile ) ) + break; + if( !rBase.ReadIdFile( aSlotIdFile ) ) + { + throw SvParseException( rInStm, "cannot read file: " + aSlotIdFile ); + } + ReadIfDelimiter(); + } + Read( ']' ); + } + + if( !ReadIf( '{' ) ) + return; + + sal_uInt32 nBeginPos = 0; + while( nBeginPos != rInStm.Tell() ) + { + nBeginPos = rInStm.Tell(); + ReadModuleElement( rModule ); + ReadIfDelimiter(); + } + Read( '}' ); +} + +void SvIdlParser::ReadModuleElement( SvMetaModule& rModule ) +{ + if( ReadIf( SvHash_interface() ) ) + { + ReadInterfaceOrShell(rModule, MetaTypeType::Interface); + } + else if( ReadIf( SvHash_shell() ) ) + { + ReadInterfaceOrShell(rModule, MetaTypeType::Shell); + } + else if( ReadIf( SvHash_enum() ) ) + { + ReadEnum(); + } + else if( ReadIf( SvHash_item() ) ) + { + ReadItem(); + } + else if( ReadIf( SvHash_struct() ) ) + { + ReadStruct(); + } + else if( ReadIf( SvHash_include() ) ) + { + ReadInclude(rModule); + } + else + { + tools::SvRef<SvMetaSlot> xSlot( new SvMetaSlot() ); + + if (ReadSlot(*xSlot)) + { + if( xSlot->Test( rInStm ) ) + { + // announce globally + rBase.AppendSlot( xSlot.get() ); + } + } + } +} + +void SvIdlParser::ReadInclude( SvMetaModule& rModule ) +{ + sal_uInt32 nTokPos = rInStm.Tell(); + bool bOk = false; + OUString aFullName(OStringToOUString(ReadString(), RTL_TEXTENCODING_ASCII_US)); + rBase.StartNewFile( aFullName ); + osl::FileBase::RC searchError = osl::File::searchFileURL(aFullName, rBase.GetPath(), aFullName); + if( osl::FileBase::E_None != searchError ) + { + OString aStr = "cannot find file:" + + OUStringToOString(aFullName, RTL_TEXTENCODING_UTF8); + throw SvParseException(aStr, rInStm.GetToken()); + } + osl::FileBase::getSystemPathFromFileURL( aFullName, aFullName ); + rBase.AddDepFile( aFullName ); + SvTokenStream aTokStm( aFullName ); + if( ERRCODE_NONE != aTokStm.GetStream().GetError() ) + { + OString aStr = "cannot open file: " + + OUStringToOString(aFullName, RTL_TEXTENCODING_UTF8); + throw SvParseException(aStr, rInStm.GetToken()); + } + // rescue error from old file + SvIdlError aOldErr = rBase.GetError(); + // reset error + rBase.SetError( SvIdlError() ); + + try { + SvIdlParser aIncludeParser( rBase, aTokStm ); + sal_uInt32 nBeginPos = 0xFFFFFFFF; // can not happen with Tell + while( nBeginPos != aTokStm.Tell() ) + { + nBeginPos = aTokStm.Tell(); + aIncludeParser.ReadModuleElement(rModule); + aTokStm.ReadIfDelimiter(); + } + } catch (const SvParseException& ex) { + rBase.SetError(ex.aError); + rBase.WriteError(aTokStm); + } + bOk = aTokStm.GetToken().IsEof(); + if( !bOk ) + { + rBase.WriteError( aTokStm ); + } + // recover error from old file + rBase.SetError( aOldErr ); + if( !bOk ) + rInStm.Seek( nTokPos ); +} + +void SvIdlParser::ReadStruct() +{ + tools::SvRef<SvMetaType> xStruct(new SvMetaType() ); + xStruct->SetType( MetaTypeType::Struct ); + xStruct->SetName( ReadIdentifier() ); + Read( '{' ); + while( true ) + { + tools::SvRef<SvMetaAttribute> xAttr( new SvMetaAttribute() ); + xAttr->aType = ReadKnownType(); + xAttr->SetName(ReadIdentifier()); + xAttr->aSlotId.setString(ReadIdentifier()); + sal_uInt32 n; + if( !rBase.FindId( xAttr->aSlotId.getString(), &n ) ) + throw SvParseException( rInStm, "no value for identifier <" + xAttr->aSlotId.getString() + "> " ); + xAttr->aSlotId.SetValue(n); + xStruct->GetAttrList().push_back( xAttr.get() ); + if( !ReadIfDelimiter() ) + break; + if( rInStm.GetToken().IsChar() && rInStm.GetToken().GetChar() == '}') + break; + } + Read( '}' ); + ReadDelimiter(); + // announce globally + rBase.GetTypeList().push_back( xStruct.get() ); +} + +void SvIdlParser::ReadItem() +{ + tools::SvRef<SvMetaType> xItem(new SvMetaType() ); + xItem->SetItem(true); + xItem->SetRef( ReadKnownType() ); + xItem->SetName( ReadIdentifier() ); + // announce globally + rBase.GetTypeList().push_back( xItem.get() ); +} + +void SvIdlParser::ReadEnum() +{ + tools::SvRef<SvMetaTypeEnum> xEnum( new SvMetaTypeEnum() ); + xEnum->SetType( MetaTypeType::Enum ); + xEnum->SetName( ReadIdentifier() ); + + Read('{'); + while( true ) + { + ReadEnumValue( *xEnum ); + if( !ReadIfDelimiter() ) + break; + } + Read( '}' ); + // announce globally + rBase.GetTypeList().push_back( xEnum.get() ); +} + +static std::string_view getCommonSubPrefix(std::string_view rA, std::string_view rB) +{ + sal_Int32 nMax = std::min(rA.size(), rB.size()); + sal_Int32 nI = 0; + while (nI < nMax) + { + if (rA[nI] != rB[nI]) + break; + ++nI; + } + return rA.substr(0, nI); +} + +void SvIdlParser::ReadEnumValue( SvMetaTypeEnum& rEnum ) +{ + tools::SvRef<SvMetaEnumValue> aEnumVal = new SvMetaEnumValue(); + aEnumVal->SetName( ReadIdentifier() ); + if( rEnum.aEnumValueList.empty() ) + { + // the first + rEnum.aPrefix = aEnumVal->GetName(); + } + else + { + rEnum.aPrefix = OString(getCommonSubPrefix(rEnum.aPrefix, aEnumVal->GetName())); + } + rEnum.aEnumValueList.push_back( aEnumVal.get() ); +} + +void SvIdlParser::ReadInterfaceOrShell( SvMetaModule& rModule, MetaTypeType aMetaTypeType ) +{ + tools::SvRef<SvMetaClass> aClass( new SvMetaClass() ); + + aClass->SetType( aMetaTypeType ); + + aClass->SetName( ReadIdentifier() ); + + if( ReadIf( ':' ) ) + { + aClass->aSuperClass = ReadKnownClass(); + } + if( ReadIf( '{' ) ) + { + sal_uInt32 nBeginPos = 0; // can not happen with Tell + while( nBeginPos != rInStm.Tell() ) + { + nBeginPos = rInStm.Tell(); + ReadInterfaceOrShellEntry(*aClass); + ReadIfDelimiter(); + } + Read( '}' ); + } + rModule.aClassList.push_back( aClass.get() ); + // announce globally + rBase.GetClassList().push_back( aClass.get() ); +} + +void SvIdlParser::ReadInterfaceOrShellEntry(SvMetaClass& rClass) +{ + if( ReadIf( SvHash_import() ) ) + { + SvMetaClass * pClass = ReadKnownClass(); + SvClassElement aEle(pClass); + SvToken& rTok = rInStm.GetToken(); + if( rTok.IsString() ) + { + aEle.SetPrefix( rTok.GetString() ); + rInStm.GetToken_Next(); + } + rClass.aClassElementList.push_back( aEle ); + } + else + { + SvMetaType * pType = rBase.ReadKnownType( rInStm ); + tools::SvRef<SvMetaAttribute> xAttr; + bool bOk = false; + if( !pType || pType->IsItem() ) + { + xAttr = new SvMetaSlot( pType ); + bOk = ReadSlot(static_cast<SvMetaSlot&>(*xAttr)); + } + else + { + xAttr = new SvMetaAttribute( pType ); + ReadInterfaceOrShellMethod(*xAttr); + bOk = true; + } + if( bOk ) + bOk = xAttr->Test( rInStm ); + if( bOk ) + bOk = rClass.TestAttribute( rBase, rInStm, *xAttr ); + if( bOk ) + { + if( !xAttr->GetSlotId().IsSet() ) + xAttr->SetSlotId( SvIdentifier(rBase.GetUniqueId()) ); + rClass.aAttrList.push_back( xAttr.get() ); + } + } +} + +bool SvIdlParser::ReadSlot(SvMetaSlot& rSlot) +{ + sal_uInt32 nTokPos = rInStm.Tell(); + bool bOk = true; + + SvMetaAttribute * pAttr = rBase.ReadKnownAttr( rInStm, rSlot.GetType() ); + if( pAttr ) + { + SvMetaSlot * pKnownSlot = dynamic_cast<SvMetaSlot*>( pAttr ); + if( !pKnownSlot ) + throw SvParseException( rInStm, "attribute " + pAttr->GetName() + " is method or variable but not a slot" ); + rSlot.SetRef( pKnownSlot ); + rSlot.SetName( pKnownSlot->GetName() ); + if( ReadIf( '[' ) ) + { + sal_uInt32 nBeginPos = 0; // can not happen with Tell + while( nBeginPos != rInStm.Tell() ) + { + nBeginPos = rInStm.Tell(); + ReadSlotAttribute(rSlot); + ReadIfDelimiter(); + } + Read( ']' ); + } + } + else + { + bOk = rSlot.SvMetaAttribute::ReadSvIdl( rBase, rInStm ); + SvMetaAttribute *pAttr2 = rBase.FindKnownAttr( rSlot.GetSlotId() ); + if( pAttr2 ) + { + SvMetaSlot * pKnownSlot = dynamic_cast<SvMetaSlot*>( pAttr2 ); + if( !pKnownSlot ) + throw SvParseException( rInStm, "attribute " + pAttr2->GetName() + " is method or variable but not a slot" ); + rSlot.SetRef( pKnownSlot ); + // names may differ, because explicitly given + if ( pKnownSlot->GetName() != rSlot.GetName() ) + throw SvParseException( rInStm, "Illegal definition!" ); + } + } + + if( !bOk ) + rInStm.Seek( nTokPos ); + + return bOk; +} + +void SvIdlParser::ReadSlotAttribute( SvMetaSlot& rSlot ) +{ + ReadIfIdAttribute(rSlot.aGroupId, SvHash_GroupId() ); + ReadIfIdAttribute(rSlot.aExecMethod, SvHash_ExecMethod() ); + ReadIfIdAttribute(rSlot.aStateMethod, SvHash_StateMethod() ); + ReadStringSvIdl( SvHash_DisableFlags(), rInStm, rSlot.aDisableFlags ); + ReadIfBoolAttribute(rSlot.aReadOnlyDoc, SvHash_ReadOnlyDoc() ); + + ReadIfBoolAttribute(rSlot.aToggle, SvHash_Toggle() ); + ReadIfBoolAttribute(rSlot.aAutoUpdate, SvHash_AutoUpdate() ); + ReadIfBoolAttribute(rSlot.aAsynchron, SvHash_Asynchron() ); + ReadIfBoolAttribute(rSlot.aRecordAbsolute, SvHash_RecordAbsolute() ); + + if( ReadIfBoolAttribute(rSlot.aRecordPerItem, SvHash_RecordPerItem()) ) + { + if (rSlot.aRecordPerSet.IsSet() || rSlot.aNoRecord.IsSet()) + throw SvParseException(rInStm, "conflicting attributes"); + rSlot.SetRecordPerItem( rSlot.aRecordPerItem ); + } + if( ReadIfBoolAttribute(rSlot.aRecordPerSet, SvHash_RecordPerSet() ) ) + { + if (rSlot.aRecordPerItem.IsSet() || rSlot.aNoRecord.IsSet()) + throw SvParseException(rInStm, "conflicting attributes"); + rSlot.SetRecordPerSet( rSlot.aRecordPerSet ); + } + if( ReadIfBoolAttribute(rSlot.aNoRecord, SvHash_NoRecord() ) ) + { + if (rSlot.aRecordPerItem.IsSet() || rSlot.aRecordPerSet.IsSet()) + throw SvParseException(rInStm, "conflicting attributes"); + rSlot.SetNoRecord( rSlot.aNoRecord ); + } + + ReadIfBoolAttribute(rSlot.aMenuConfig, SvHash_MenuConfig() ); + ReadIfBoolAttribute(rSlot.aToolBoxConfig, SvHash_ToolBoxConfig() ); + ReadIfBoolAttribute(rSlot.aAccelConfig, SvHash_AccelConfig() ); + + ReadIfBoolAttribute(rSlot.aFastCall, SvHash_FastCall() ); + ReadIfBoolAttribute(rSlot.aContainer, SvHash_Container() ); +} + +void SvIdlParser::ReadInterfaceOrShellMethod( SvMetaAttribute& rAttr ) +{ + rAttr.SetName( ReadIdentifier() ); + ReadSlotId( rAttr.aSlotId ); + + // read method arguments + Read( '(' ); + tools::SvRef<SvMetaType> xT(new SvMetaType() ); + xT->SetRef(rAttr.GetType() ); + rAttr.aType = xT; + rAttr.aType->SetType( MetaTypeType::Method ); + if (ReadIf(')')) + return; + + while (true) + { + tools::SvRef<SvMetaAttribute> xParamAttr( new SvMetaAttribute() ); + xParamAttr->aType = ReadKnownType(); + xParamAttr->SetName( ReadIdentifier() ); + ReadSlotId(xParamAttr->aSlotId); + rAttr.aType->GetAttrList().push_back( xParamAttr.get() ); + if (!ReadIfDelimiter()) + break; + } + Read(')'); +} + +void SvIdlParser::ReadSlotId(SvIdentifier& rSlotId) +{ + rSlotId.setString( ReadIdentifier() ); + sal_uInt32 n; + if( !rBase.FindId( rSlotId.getString(), &n ) ) + throw SvParseException( rInStm, "no value for identifier <" + rSlotId.getString() + "> " ); + rSlotId.SetValue(n); +} + +SvMetaClass * SvIdlParser::ReadKnownClass() +{ + OString aName(ReadIdentifier()); + SvMetaClass* pClass = rBase.FindKnownClass( aName ); + if( !pClass ) + throw SvParseException( rInStm, "unknown class" ); + return pClass; +} + +SvMetaType * SvIdlParser::ReadKnownType() +{ + OString aName = ReadIdentifier(); + for( const auto& aType : rBase.GetTypeList() ) + { + if( aType->GetName() == aName ) + return aType; + } + throw SvParseException( rInStm, "wrong typedef: "); +} + +bool SvIdlParser::ReadIfBoolAttribute( SvBOOL& rBool, SvStringHashEntry const * pName ) +{ + sal_uInt32 nTokPos = rInStm.Tell(); + SvToken& rTok = rInStm.GetToken_Next(); + + if( rTok.Is( pName ) ) + { + if( rInStm.ReadIf( '=' ) ) + { + rTok = rInStm.GetToken(); + if( !rTok.IsBool() ) + throw SvParseException(rInStm, "xxx"); + rBool = rTok.GetBool(); + rInStm.GetToken_Next(); + } + else + rBool = true; //default action set to TRUE + return true; + } + rInStm.Seek( nTokPos ); + return false; +} + +void SvIdlParser::ReadIfIdAttribute( SvIdentifier& rIdentifier, SvStringHashEntry const * pName ) +{ + sal_uInt32 nTokPos = rInStm.Tell(); + SvToken& rTok = rInStm.GetToken_Next(); + + if( rTok.Is( pName ) ) + { + if( rInStm.ReadIf( '=' ) ) + { + rTok = rInStm.GetToken(); + if( !rTok.IsIdentifier() ) + throw SvParseException(rInStm, "expected identifier"); + rIdentifier.setString(rTok.GetString()); + rInStm.GetToken_Next(); + } + } + else + rInStm.Seek( nTokPos ); +} + +void SvIdlParser::ReadDelimiter() +{ + if( !ReadIfDelimiter() ) + throw SvParseException(rInStm, "expected delimiter"); +} + +bool SvIdlParser::ReadIfDelimiter() +{ + if( rInStm.GetToken().IsChar() + && (';' == rInStm.GetToken().GetChar() + || ',' == rInStm.GetToken().GetChar()) ) + { + rInStm.GetToken_Next(); + return true; + } + return false; +} + +OString SvIdlParser::ReadIdentifier() +{ + SvToken& rTok = rInStm.GetToken(); + if( !rTok.IsIdentifier() ) + throw SvParseException("expected identifier", rTok); + rInStm.GetToken_Next(); + return rTok.GetString(); +} + +OString SvIdlParser::ReadString() +{ + SvToken& rTok = rInStm.GetToken(); + if( !rTok.IsString() ) + throw SvParseException("expected string", rTok); + rInStm.GetToken_Next(); + return rTok.GetString(); +} + +void SvIdlParser::Read(char cChar) +{ + if( !ReadIf(cChar) ) + throw SvParseException(rInStm, "expected char '" + OStringChar(cChar) + "'"); +} + +bool SvIdlParser::ReadIf(char cChar) +{ + if( rInStm.GetToken().IsChar() && rInStm.GetToken().GetChar() == cChar ) + { + rInStm.GetToken_Next(); + return true; + } + return false; +} + +void SvIdlParser::Read(SvStringHashEntry const * entry) +{ + if( !rInStm.GetToken().Is(entry) ) + throw SvParseException("expected " + entry->GetName(), rInStm.GetToken()); + rInStm.GetToken_Next(); +} + +bool SvIdlParser::ReadIf(SvStringHashEntry const * entry) +{ + if( rInStm.GetToken().Is(entry) ) + { + rInStm.GetToken_Next(); + return true; + } + return false; +} +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idl/source/prj/svidl.cxx b/idl/source/prj/svidl.cxx new file mode 100644 index 000000000..2c9fbf63d --- /dev/null +++ b/idl/source/prj/svidl.cxx @@ -0,0 +1,213 @@ +/* -*- 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 <stdio.h> +#include <database.hxx> +#include <command.hxx> +#include <rtl/ustring.hxx> +#include <osl/file.hxx> +#include <memory> + +#define BR 0x8000 +static bool FileMove_Impl( const OUString & rFile1, const OUString & rFile2, bool bMoveAlways ) +{ + //printf( "Move from %s to %s\n", rFile2.GetStr(), rFile1.GetStr() ); + sal_uLong nC1 = 0; + sal_uLong nC2 = 1; + if( !bMoveAlways ) + { + SvFileStream aOutStm1( rFile1, StreamMode::STD_READ ); + SvFileStream aOutStm2( rFile2, StreamMode::STD_READ ); + if( aOutStm1.GetError() == ERRCODE_NONE ) + { + std::unique_ptr<sal_uInt8[]> pBuf1(new sal_uInt8[ BR ]); + std::unique_ptr<sal_uInt8[]> pBuf2(new sal_uInt8[ BR ]); + nC1 = aOutStm1.ReadBytes(pBuf1.get(), BR); + nC2 = aOutStm2.ReadBytes(pBuf2.get(), BR); + while( nC1 == nC2 ) + { + if( memcmp( pBuf1.get(), pBuf2.get(), nC1 ) ) + { + nC1++; + break; + } + else + { + if( 0x8000 != nC1 ) + break; + nC1 = aOutStm1.ReadBytes(pBuf1.get(), BR); + nC2 = aOutStm2.ReadBytes(pBuf2.get(), BR); + } + } + } + } + OUString fileURL2; + osl::FileBase::getFileURLFromSystemPath( rFile2, fileURL2 ); + if( nC1 != nC2 ) + {// something has changed + OUString fileURL1; + osl::FileBase::getFileURLFromSystemPath( rFile1, fileURL1 ); + // move file + if( osl::FileBase::E_None != osl::File::move( fileURL2, fileURL1 ) ) + { + // delete both files + osl::File::remove( fileURL1 ); + osl::File::remove( fileURL2 ); + return false; + } + return true; + } + return osl::FileBase::E_None == osl::File::remove( fileURL2 ); +} + +//This function gets a system path to a file [fname], creates a temp file in +//the same folder as [fname] and returns the system path of the temp file. +static OUString tempFileHelper(std::u16string_view fname) +{ + OUString aTmpFile; + + size_t delimIndex = fname.rfind( '/' ); + if( delimIndex > 0 && delimIndex != std::u16string_view::npos) + { + OUString aTmpDir( fname.substr( 0, delimIndex ) ); + osl::FileBase::getFileURLFromSystemPath( aTmpDir, aTmpDir ); + osl::FileBase::createTempFile( &aTmpDir, nullptr, &aTmpFile ); + osl::FileBase::getSystemPathFromFileURL( aTmpFile, aTmpFile ); + } + else + { + OString aStr = "invalid filename: " + + OUStringToOString(fname, RTL_TEXTENCODING_UTF8); + fprintf(stderr, "%s\n", aStr.getStr()); + } + return aTmpFile; +} + +int main ( int argc, char ** argv) +{ + OUString aTmpSlotMapFile; + OUString aTmpDepFile; + + SvCommand aCommand( argc, argv ); + + if( aCommand.nVerbosity != 0 ) + printf( "StarView Interface Definition Language (IDL) Compiler 3.0\n" ); + + Init(); + std::unique_ptr<SvIdlWorkingBase> pDataBase( new SvIdlWorkingBase(aCommand)); + + int nExit = 0; + if( !aCommand.aExportFile.isEmpty() ) + { + osl::DirectoryItem aDI; + osl::FileStatus fileStatus( osl_FileStatus_Mask_FileName ); + (void)osl::DirectoryItem::get( aCommand.aExportFile, aDI ); + (void)aDI.getFileStatus(fileStatus); + pDataBase->SetExportFile( fileStatus.getFileName() ); + } + + if( ReadIdl( pDataBase.get(), aCommand ) ) + { + if( nExit == 0 && !aCommand.aSlotMapFile.isEmpty() ) + { + aTmpSlotMapFile = tempFileHelper(aCommand.aSlotMapFile); + SvFileStream aOutStm( aTmpSlotMapFile, StreamMode::READWRITE | StreamMode::TRUNC ); + if( !pDataBase->WriteSfx( aOutStm ) ) + { + nExit = -1; + OString aStr = "cannot write slotmap file: " + + OUStringToOString(aCommand.aSlotMapFile, RTL_TEXTENCODING_UTF8); + fprintf(stderr, "%s\n", aStr.getStr()); + } + } + if (nExit == 0 && !aCommand.m_DepFile.isEmpty()) + { + aTmpDepFile = tempFileHelper(aCommand.m_DepFile); + SvFileStream aOutStm( aTmpDepFile, StreamMode::READWRITE | StreamMode::TRUNC ); + pDataBase->WriteDepFile(aOutStm, aCommand.aTargetFile); + if( aOutStm.GetError() != ERRCODE_NONE ) + { + nExit = -1; + fprintf( stderr, "cannot write dependency file: %s\n", + OUStringToOString( aCommand.m_DepFile, + RTL_TEXTENCODING_UTF8 ).getStr() ); + } + } + } + else + nExit = -1; + + if( nExit == 0 ) + { + bool bErr = false; + bool bDoMove = aCommand.aTargetFile.isEmpty(); + OUString aErrFile, aErrFile2; + if (!aCommand.aSlotMapFile.isEmpty()) + { + bErr = !FileMove_Impl( aCommand.aSlotMapFile, aTmpSlotMapFile, bDoMove ); + if( bErr ) { + aErrFile = aCommand.aSlotMapFile; + aErrFile2 = aTmpSlotMapFile; + } + } + if (!bErr && !aCommand.m_DepFile.isEmpty()) + { + bErr |= !FileMove_Impl( aCommand.m_DepFile, aTmpDepFile, bDoMove ); + if (bErr) { + aErrFile = aCommand.m_DepFile; + aErrFile2 = aTmpDepFile; + } + } + + if( bErr ) + { + nExit = -1; + OString aStr = "cannot move file from: " + + OUStringToOString(aErrFile2, RTL_TEXTENCODING_UTF8) + + "\n to file: " + + OUStringToOString(aErrFile, RTL_TEXTENCODING_UTF8); + fprintf( stderr, "%s\n", aStr.getStr() ); + } + else + { + if( !aCommand.aTargetFile.isEmpty() ) + { + // stamp file, because idl passed through correctly + SvFileStream aOutStm( aCommand.aTargetFile, + StreamMode::READWRITE | StreamMode::TRUNC ); + } + } + } + + if( nExit != 0 ) + { + if( !aCommand.aSlotMapFile.isEmpty() ) + { + osl::FileBase::getSystemPathFromFileURL( aTmpSlotMapFile, aTmpSlotMapFile ); + osl::File::remove( aTmpSlotMapFile ); + } + } + + if( nExit != 0 ) + fprintf( stderr, "svidl terminated with errors\n" ); + return nExit; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |