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 | |
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 '')
108 files changed, 19337 insertions, 0 deletions
diff --git a/idl/Executable_svidl.mk b/idl/Executable_svidl.mk new file mode 100644 index 000000000..54676af66 --- /dev/null +++ b/idl/Executable_svidl.mk @@ -0,0 +1,60 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +# +# 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 . +# + +$(eval $(call gb_Executable_Executable,svidl)) + +$(eval $(call gb_Executable_use_external,svidl,boost_headers)) + +ifeq ($(DISABLE_DYNLOADING),TRUE) +$(eval $(call gb_Executable_use_externals,svidl,\ + dtoa \ + zlib \ +)) +endif + +$(eval $(call gb_Executable_set_include,svidl,\ + $$(INCLUDE) \ + -I$(SRCDIR)/idl/inc \ +)) + +$(eval $(call gb_Executable_use_sdk_api,svidl)) + +$(eval $(call gb_Executable_use_libraries,svidl,\ + comphelper \ + tl \ + sal \ +)) + +$(eval $(call gb_Executable_add_exception_objects,svidl,\ + idl/source/cmptools/hash \ + idl/source/cmptools/lex \ + idl/source/objects/basobj \ + idl/source/objects/bastype \ + idl/source/objects/module \ + idl/source/objects/object \ + idl/source/objects/slot \ + idl/source/objects/types \ + idl/source/prj/command \ + idl/source/prj/database \ + idl/source/prj/globals \ + idl/source/prj/svidl \ + idl/source/prj/parser \ +)) + +# vim: set noet sw=4 ts=4: diff --git a/idl/IwyuFilter_idl.yaml b/idl/IwyuFilter_idl.yaml new file mode 100644 index 000000000..ea0464ad3 --- /dev/null +++ b/idl/IwyuFilter_idl.yaml @@ -0,0 +1,2 @@ +--- +assumeFilename: idl/source/objects/object.cxx diff --git a/idl/Makefile b/idl/Makefile new file mode 100644 index 000000000..0997e6284 --- /dev/null +++ b/idl/Makefile @@ -0,0 +1,14 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +# +# 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/. +# + +module_directory:=$(dir $(realpath $(firstword $(MAKEFILE_LIST)))) + +include $(module_directory)/../solenv/gbuild/partial_build.mk + +# vim: set noet sw=4 ts=4: diff --git a/idl/Module_idl.mk b/idl/Module_idl.mk new file mode 100644 index 000000000..ea476b41c --- /dev/null +++ b/idl/Module_idl.mk @@ -0,0 +1,26 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +# +# 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 . +# + +$(eval $(call gb_Module_Module,idl)) + +$(eval $(call gb_Module_add_targets_for_build,idl,\ + Executable_svidl \ +)) + +# vim: set noet sw=4 ts=4: diff --git a/idl/README.md b/idl/README.md new file mode 100644 index 000000000..019126c70 --- /dev/null +++ b/idl/README.md @@ -0,0 +1,9 @@ +# SvIDL Compiler + +SvIDL Compiler that generates C++ slot headers from SDI files in modules' `sdi/` +subdirectory. + +There is an overview of basic architecture of the markup of SDI files in the +OpenOffice wiki: + +<https://wiki.openoffice.org/wiki/Framework/Article/Implementation_of_the_Dispatch_API_In_SFX2> diff --git a/idl/inc/basobj.hxx b/idl/inc/basobj.hxx new file mode 100644 index 000000000..2bdd8e622 --- /dev/null +++ b/idl/inc/basobj.hxx @@ -0,0 +1,128 @@ +/* -*- 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 . + */ + +#ifndef INCLUDED_IDL_INC_BASOBJ_HXX +#define INCLUDED_IDL_INC_BASOBJ_HXX + +#include <tools/ref.hxx> +#include "bastype.hxx" +#include <vector> + +class SvTokenStream; +class SvIdlDataBase; + +template<typename T> +class SvRefMemberList : private std::vector<T> +{ +private: + typedef typename std::vector<T> base_t; + +public: + using base_t::size; + using base_t::front; + using base_t::back; + using base_t::operator[]; + using base_t::begin; + using base_t::end; + using typename base_t::iterator; + using typename base_t::const_iterator; + using base_t::rbegin; + using base_t::rend; + using typename base_t::reverse_iterator; + using base_t::empty; + + ~SvRefMemberList() { clear(); } + void clear() + { + for( typename base_t::const_iterator it = base_t::begin(); it != base_t::end(); ++it ) + { + T p = *it; + if( p ) + p->ReleaseRef(); + } + base_t::clear(); + } + + void push_back( T p ) + { + base_t::push_back( p ); + p->AddFirstRef(); + } + + void insert( typename base_t::iterator it, T p ) + { + base_t::insert( it, p ); + p->AddFirstRef(); + } + + void pop_back() + { + T p = base_t::back(); + base_t::pop_back(); + if( p ) + p->ReleaseRef(); + } +}; + +class SvMetaObject : public SvRefBase +{ + OString aName; + +protected: + bool ReadNameSvIdl( SvTokenStream & rInStm ); + void DoReadContextSvIdl( SvIdlDataBase &, SvTokenStream & rInStm ); + virtual void ReadContextSvIdl( SvIdlDataBase &, SvTokenStream & rInStm ); + virtual void ReadAttributesSvIdl( SvIdlDataBase & rBase, + SvTokenStream & rInStm ); +public: + SvMetaObject(); + + static void WriteTab( SvStream & rOutStm, sal_uInt16 nTab ); + static void Back2Delimiter( SvStream & ); + static void WriteStars( SvStream & ); + + void SetName( const OString& rName ); + virtual const OString & GetName() const { return aName; } + + virtual bool ReadSvIdl( SvIdlDataBase &, SvTokenStream & rInStm ); +}; + +class SvMetaReference : public SvMetaObject +{ + tools::SvRef<SvMetaReference> aRef; +public: + SvMetaReference(); + + const OString & GetName() const override + { + return ( !aRef.is() + || !SvMetaObject::GetName().isEmpty() ) + ? SvMetaObject::GetName() + : aRef->GetName(); + } + + SvMetaReference * GetRef() const { return aRef.get(); } + void SetRef( SvMetaReference * pRef ) + { aRef = pRef; } +}; + +#endif // INCLUDED_IDL_INC_BASOBJ_HXX + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idl/inc/bastype.hxx b/idl/inc/bastype.hxx new file mode 100644 index 000000000..7494b35a8 --- /dev/null +++ b/idl/inc/bastype.hxx @@ -0,0 +1,76 @@ +/* -*- 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 . + */ + +#ifndef INCLUDED_IDL_INC_BASTYPE_HXX +#define INCLUDED_IDL_INC_BASTYPE_HXX + + +#include <sal/types.h> +#include <rtl/string.hxx> + +class SvStringHashEntry; +class SvIdlDataBase; +class SvStream; +class SvTokenStream; + +class SvBOOL +{ + bool bVal:1, + bSet:1; +public: + SvBOOL() { bSet = bVal = false; } + SvBOOL( bool b ) : bVal( b ), bSet( false) {} + SvBOOL & operator = ( bool n ) { bVal = n; bSet = true; return *this; } + + operator bool() const { return bVal; } + bool IsSet() const { return bSet; } + + bool ReadSvIdl( SvStringHashEntry const * pName, SvTokenStream & rInStm ); +}; + + +class SvIdentifier +{ + OString m_aStr; + sal_uInt32 nValue; +public: + SvIdentifier() : nValue( 0 ) {}; + SvIdentifier(sal_uInt32 n) : nValue( n ) {}; + + void setString(const OString& rStr) { m_aStr = rStr; } + const OString& getString() const { return m_aStr; } + + void ReadSvIdl( SvStringHashEntry const * pName, SvTokenStream & rInStm ); + bool IsSet() const + { + return !m_aStr.isEmpty() || nValue != 0; + } + sal_uInt32 GetValue() const { return nValue; } + void SetValue( sal_uInt32 bVal ) { nValue = bVal; } + + void ReadSvIdl( SvIdlDataBase &, SvTokenStream & rInStm ); +}; + + +bool ReadStringSvIdl( SvStringHashEntry const * pName, SvTokenStream & rInStm, OString& aString ); + + +#endif // INCLUDED_IDL_INC_BASTYPE_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idl/inc/command.hxx b/idl/inc/command.hxx new file mode 100644 index 000000000..ea5e0f446 --- /dev/null +++ b/idl/inc/command.hxx @@ -0,0 +1,47 @@ +/* -*- 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 . + */ + +#ifndef INCLUDED_IDL_INC_COMMAND_HXX +#define INCLUDED_IDL_INC_COMMAND_HXX + +#include <rtl/ustring.hxx> +#include <vector> + +class SvCommand +{ +public: + std::vector<OUString> aInFileList; + OUString aSlotMapFile; + OUString aPath; + OUString aTargetFile; + OUString aExportFile; + OUString m_DepFile; + sal_uInt32 nVerbosity; + + SvCommand( int argc, char ** argv ); + ~SvCommand(); +}; + +void Init(); +class SvIdlWorkingBase; +bool ReadIdl( SvIdlWorkingBase * pDataBase, const SvCommand & rCommand ); + +#endif // INCLUDED_IDL_INC_COMMAND_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idl/inc/database.hxx b/idl/inc/database.hxx new file mode 100644 index 000000000..dcdf93593 --- /dev/null +++ b/idl/inc/database.hxx @@ -0,0 +1,141 @@ +/* -*- 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 . + */ + +#ifndef INCLUDED_IDL_INC_DATABASE_HXX +#define INCLUDED_IDL_INC_DATABASE_HXX + +#include "module.hxx" +#include "hash.hxx" +#include "lex.hxx" +#include <rtl/string.hxx> + +#include <rtl/ustring.hxx> +#include <set> +#include <string_view> +#include <exception> + +class SvCommand; + +class SvIdlError +{ + OString aText; +public: + sal_uInt32 nLine, nColumn; + + SvIdlError() : nLine(0), nColumn(0) {} + SvIdlError( sal_uInt32 nL, sal_uInt32 nC ) + : nLine(nL), nColumn(nC) {} + + const OString& GetText() const { return aText; } + void SetText( const OString& rT ) { aText = rT; } + bool IsError() const { return nLine != 0; } +}; + +class SvParseException final : public std::exception +{ +public: + SvIdlError aError; + SvParseException( SvTokenStream const & rInStm, const OString& rError ); + SvParseException( const OString& rError, SvToken const & rTok ); +}; + + + +class SvIdlDataBase +{ + bool bExport; + OUString aExportFile; + sal_uInt32 nUniqueId; + sal_uInt32 nVerbosity; + std::vector<OUString> aIdFileList; + std::unique_ptr<SvStringHashTable> pIdTable; + + SvRefMemberList<SvMetaType *> aTypeList; + SvRefMemberList<SvMetaClass *> aClassList; + SvRefMemberList<SvMetaModule *> aModuleList; + SvRefMemberList<SvMetaSlot *> aSlotList; + SvRefMemberList<SvMetaObject *> aContextStack; + +protected: + ::std::set< OUString > m_DepFiles; + OUString aPath; + SvIdlError aError; + void WriteReset() + { + aUsedTypes.clear(); + } +public: + OUString sSlotMapFile; + + explicit SvIdlDataBase( const SvCommand& rCmd ); + ~SvIdlDataBase(); + + SvRefMemberList<SvMetaType *>& GetTypeList(); + SvRefMemberList<SvMetaClass *>& GetClassList() { return aClassList; } + SvRefMemberList<SvMetaModule *>& GetModuleList() { return aModuleList; } + + // list of used types while writing + SvRefMemberList<SvMetaType *> aUsedTypes; + + void StartNewFile( std::u16string_view rName ); + void SetExportFile( const OUString& rName ) + { aExportFile = rName; } + void AppendSlot( SvMetaSlot *pSlot ); + const SvIdlError & GetError() const { return aError; } + void SetError( const SvIdlError & r ) + { aError = r; } + + const OUString & GetPath() const { return aPath; } + void SetPath(const OUString &s) { aPath = s; } + SvRefMemberList<SvMetaObject *>& GetStack() { return aContextStack; } + + void Write(const OString& rText) const; + void WriteError( SvTokenStream & rInStm ); + void SetError( const OString& rError, SvToken const & rTok ); + void SetAndWriteError( SvTokenStream & rInStm, const OString& rError ); + void Push( SvMetaObject * pObj ); + sal_uInt32 GetUniqueId() { return ++nUniqueId; } + bool FindId( const OString& rIdName, sal_uInt32 * pVal ); + void InsertId( const OString& rIdName, sal_uInt32 nVal ); + bool ReadIdFile( std::string_view rFileName ); + + SvMetaType * FindType( std::string_view rName ); + static SvMetaType * FindType( const SvMetaType *, SvRefMemberList<SvMetaType *>& ); + + SvMetaType * ReadKnownType( SvTokenStream & rInStm ); + SvMetaAttribute * ReadKnownAttr( SvTokenStream & rInStm, + SvMetaType * pType ); + SvMetaAttribute * FindKnownAttr( const SvIdentifier& ); + SvMetaClass * ReadKnownClass( SvTokenStream & rInStm ); + SvMetaClass * FindKnownClass( std::string_view aName ); + void AddDepFile(OUString const& rFileName); + void WriteDepFile(SvFileStream & rStream, std::u16string_view rTarget); +}; + +class SvIdlWorkingBase : public SvIdlDataBase +{ +public: + explicit SvIdlWorkingBase( const SvCommand& rCmd ); + + bool WriteSfx( SvStream & ); +}; + +#endif // INCLUDED_IDL_INC_DATABASE_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idl/inc/globals.hxx b/idl/inc/globals.hxx new file mode 100644 index 000000000..0739d8757 --- /dev/null +++ b/idl/inc/globals.hxx @@ -0,0 +1,128 @@ +/* -*- 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 . + */ + +#ifndef INCLUDED_IDL_INC_GLOBALS_HXX +#define INCLUDED_IDL_INC_GLOBALS_HXX + +#include "hash.hxx" +#include <memory> + +struct SvGlobalHashNames +{ + SvStringHashEntry* MM_module; + SvStringHashEntry* MM_interface; + SvStringHashEntry* MM_shell; + SvStringHashEntry* MM_Toggle; + SvStringHashEntry* MM_AutoUpdate; + SvStringHashEntry* MM_Asynchron; + SvStringHashEntry* MM_RecordPerSet; + SvStringHashEntry* MM_RecordPerItem; + SvStringHashEntry* MM_NoRecord; + SvStringHashEntry* MM_RecordAbsolute; + SvStringHashEntry* MM_enum; + SvStringHashEntry* MM_UINT16; + SvStringHashEntry* MM_INT16; + SvStringHashEntry* MM_UINT32; + SvStringHashEntry* MM_INT32; + SvStringHashEntry* MM_BOOL; + SvStringHashEntry* MM_BYTE; + SvStringHashEntry* MM_float; + SvStringHashEntry* MM_double; + SvStringHashEntry* MM_item; + SvStringHashEntry* MM_import; + SvStringHashEntry* MM_SlotIdFile; + SvStringHashEntry* MM_include; + SvStringHashEntry* MM_ExecMethod; + SvStringHashEntry* MM_StateMethod; + SvStringHashEntry* MM_GroupId; + SvStringHashEntry* MM_define; + SvStringHashEntry* MM_MenuConfig; + SvStringHashEntry* MM_ToolBoxConfig; + SvStringHashEntry* MM_AccelConfig; + SvStringHashEntry* MM_FastCall; + SvStringHashEntry* MM_SbxObject; + SvStringHashEntry* MM_Container; + SvStringHashEntry* MM_ReadOnlyDoc; + SvStringHashEntry* MM_struct; + SvStringHashEntry* MM_DisableFlags; + + SvGlobalHashNames(); +}; + +class IdlDll +{ +public: + std::unique_ptr<SvStringHashTable> pHashTable; + std::unique_ptr<SvGlobalHashNames> pGlobalNames; + + IdlDll(); + ~IdlDll(); +}; + +IdlDll & GetIdlApp(); + +#define HASH_INLINE( Name ) \ +inline SvStringHashEntry * SvHash_##Name() \ +{ \ + if( !GetIdlApp().pGlobalNames ) \ + GetIdlApp().pGlobalNames.reset( new SvGlobalHashNames() ); \ + return GetIdlApp().pGlobalNames->MM_##Name; \ +} + +HASH_INLINE(module) +HASH_INLINE(interface) +HASH_INLINE(shell) +HASH_INLINE(Toggle) +HASH_INLINE(AutoUpdate) +HASH_INLINE(Asynchron) +HASH_INLINE(RecordPerItem) +HASH_INLINE(RecordPerSet) +HASH_INLINE(NoRecord) +HASH_INLINE(RecordAbsolute) +HASH_INLINE(enum) +HASH_INLINE(UINT16) +HASH_INLINE(INT16) +HASH_INLINE(UINT32) +HASH_INLINE(INT32) +HASH_INLINE(BOOL) +HASH_INLINE(BYTE) +HASH_INLINE(item) +HASH_INLINE(import) +HASH_INLINE(SlotIdFile) +HASH_INLINE(include) +HASH_INLINE(ExecMethod) +HASH_INLINE(StateMethod) +HASH_INLINE(GroupId) +HASH_INLINE(float) +HASH_INLINE(double) +HASH_INLINE(define) +HASH_INLINE(MenuConfig) +HASH_INLINE(ToolBoxConfig) +HASH_INLINE(AccelConfig) +HASH_INLINE(FastCall) +HASH_INLINE(SbxObject) +HASH_INLINE(Container) +HASH_INLINE(ReadOnlyDoc) +HASH_INLINE(struct) +HASH_INLINE(DisableFlags) + + +#endif // INCLUDED_IDL_INC_GLOBALS_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idl/inc/hash.hxx b/idl/inc/hash.hxx new file mode 100644 index 000000000..6bc904133 --- /dev/null +++ b/idl/inc/hash.hxx @@ -0,0 +1,61 @@ +/* -*- 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 . + */ + +#ifndef INCLUDED_IDL_INC_HASH_HXX +#define INCLUDED_IDL_INC_HASH_HXX + +#include <rtl/string.hxx> +#include <tools/solar.h> +#include <unordered_map> +#include <memory> +#include <utility> + +class SvStringHashEntry +{ + OString aName; + sal_uLong nValue; +public: + SvStringHashEntry( OString aName_ ) + : aName(std::move(aName_)) + , nValue(0) + { + } + + const OString& GetName() const { return aName; } + + void SetValue( sal_uLong n ) { nValue = n; } + sal_uLong GetValue() const { return nValue; } +}; + +class SvStringHashTable +{ + std::unordered_map<sal_uInt32, std::unique_ptr<SvStringHashEntry>> maInt2EntryMap; + std::unordered_map<OString, sal_uInt32> maString2IntMap; + sal_uInt32 mnNextId = 0; + +public: + SvStringHashEntry * Insert( OString const & rElement, sal_uInt32 * pInsertPos ); + bool Test( OString const & rElement, sal_uInt32 * pInsertPos ); + SvStringHashEntry * Get( sal_uInt32 nInsertPos ) const; + OString GetNearString( std::string_view rName ) const; +}; + +#endif // INCLUDED_IDL_INC_HASH_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idl/inc/lex.hxx b/idl/inc/lex.hxx new file mode 100644 index 000000000..b7aa9336d --- /dev/null +++ b/idl/inc/lex.hxx @@ -0,0 +1,217 @@ +/* -*- 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 . + */ + +#ifndef INCLUDED_IDL_INC_LEX_HXX +#define INCLUDED_IDL_INC_LEX_HXX + +#include <sal/types.h> +#include "hash.hxx" +#include <tools/stream.hxx> +#include <vector> +#include <memory> + +enum class SVTOKENTYPE { Empty, Comment, + Integer, String, + Bool, Identifier, + Char, + EndOfFile, HashId }; + +class SvToken +{ +friend class SvTokenStream; + sal_uInt64 nLine, nColumn; + SVTOKENTYPE nType; + OString aString; + union + { + sal_uInt64 nLong; + bool bBool; + char cChar; + SvStringHashEntry * pHash; + }; +public: + SvToken(); + SvToken( const SvToken & rObj ) = delete; + + SvToken & operator = ( const SvToken & rObj ); + + OString GetTokenAsString() const; + + void SetLine( sal_uInt64 nLineP ) { nLine = nLineP; } + sal_uInt64 GetLine() const { return nLine; } + + void SetColumn( sal_uInt64 nColumnP ) { nColumn = nColumnP; } + sal_uInt64 GetColumn() const { return nColumn; } + + bool IsComment() const { return nType == SVTOKENTYPE::Comment; } + bool IsInteger() const { return nType == SVTOKENTYPE::Integer; } + bool IsString() const { return nType == SVTOKENTYPE::String; } + bool IsBool() const { return nType == SVTOKENTYPE::Bool; } + bool IsIdentifierHash() const + { return nType == SVTOKENTYPE::HashId; } + bool IsIdentifier() const + { + return nType == SVTOKENTYPE::Identifier + || nType == SVTOKENTYPE::HashId; + } + bool IsChar() const { return nType == SVTOKENTYPE::Char; } + bool IsEof() const { return nType == SVTOKENTYPE::EndOfFile; } + + const OString& GetString() const + { + return IsIdentifierHash() + ? pHash->GetName() + : aString; + } + sal_uInt64 GetNumber() const { return nLong; } + bool GetBool() const { return bBool; } + char GetChar() const { return cChar; } + + void SetHash( SvStringHashEntry * pHashP ) + { pHash = pHashP; nType = SVTOKENTYPE::HashId; } + bool Is( SvStringHashEntry const * pEntry ) const + { return IsIdentifierHash() && pHash == pEntry; } +}; + +inline SvToken::SvToken() + : nLine(0) + , nColumn(0) + , nType( SVTOKENTYPE::Empty ) +{ +} + +class SvTokenStream +{ + sal_uInt64 nLine, nColumn; + sal_Int32 nBufPos; + char c; // next character + static const sal_uInt16 nTabSize = 4; // length of tabulator + OString aStrTrue; + OString aStrFalse; + sal_uInt32 nMaxPos; + + std::unique_ptr<SvFileStream> pInStream; + OUString aFileName; + std::vector<std::unique_ptr<SvToken> > aTokList; + std::vector<std::unique_ptr<SvToken> >::iterator pCurToken; + + OString aBufStr; + + void InitCtor(); + + char GetNextChar(); + char GetFastNextChar() + { + return (nBufPos < aBufStr.getLength()) + ? aBufStr[nBufPos++] + : '\0'; + } + + void FillTokenList(); + sal_uInt64 GetNumber(); + bool MakeToken( SvToken & ); + bool IsEof() const { return pInStream->eof(); } + void SetMax() + { + sal_uInt32 n = Tell(); + if( n > nMaxPos ) + nMaxPos = n; + } + void CalcColumn() + { + // if end of line spare calculation + if( 0 != c ) + { + sal_Int32 n = 0; + nColumn = 0; + while( n < nBufPos ) + nColumn += aBufStr[n++] == '\t' ? nTabSize : 1; + } + } +public: + SvTokenStream( const OUString & rFileName ); + ~SvTokenStream(); + + const OUString & GetFileName() const { return aFileName; } + SvStream & GetStream() { return *pInStream; } + + SvToken& GetToken_PrevAll() + { + std::vector<std::unique_ptr<SvToken> >::iterator pRetToken = pCurToken; + + // current iterator always valid + if(pCurToken != aTokList.begin()) + --pCurToken; + + return *(*pRetToken); + } + + SvToken& GetToken_Next() + { + std::vector<std::unique_ptr<SvToken> >::iterator pRetToken = pCurToken++; + + if (pCurToken == aTokList.end()) + pCurToken = pRetToken; + + SetMax(); + + return *(*pRetToken); + } + + SvToken& GetToken() const { return *(*pCurToken); } + + bool ReadIf( char cChar ) + { + if( GetToken().IsChar() && cChar == GetToken().GetChar() ) + { + GetToken_Next(); + return true; + } + else + return false; + } + + void ReadIfDelimiter() + { + if( GetToken().IsChar() + && (';' == GetToken().GetChar() + || ',' == GetToken().GetChar()) ) + { + GetToken_Next(); + } + } + + sal_uInt32 Tell() const { return pCurToken-aTokList.begin(); } + + void Seek( sal_uInt32 nPos ) + { + pCurToken = aTokList.begin() + nPos; + SetMax(); + } + + void SeekToMax() + { + pCurToken = aTokList.begin()+nMaxPos; + } +}; + + +#endif // INCLUDED_IDL_INC_LEX_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idl/inc/module.hxx b/idl/inc/module.hxx new file mode 100644 index 000000000..08c14cc9c --- /dev/null +++ b/idl/inc/module.hxx @@ -0,0 +1,37 @@ +/* -*- 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 . + */ + +#ifndef INCLUDED_IDL_INC_MODULE_HXX +#define INCLUDED_IDL_INC_MODULE_HXX + +#include "object.hxx" + +class SvMetaModule final : public SvMetaObject +{ +public: + SvRefMemberList<SvMetaClass *> aClassList; + + SvMetaModule(); + + void WriteSfx( SvIdlDataBase & rBase, SvStream & rOutStm ); +}; + +#endif // INCLUDED_IDL_INC_MODULE_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idl/inc/object.hxx b/idl/inc/object.hxx new file mode 100644 index 000000000..8d16ca563 --- /dev/null +++ b/idl/inc/object.hxx @@ -0,0 +1,90 @@ +/* -*- 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 . + */ + +#ifndef INCLUDED_IDL_INC_OBJECT_HXX +#define INCLUDED_IDL_INC_OBJECT_HXX + +#include "types.hxx" + +#include <tools/solar.h> + +#include <vector> + +class SvMetaClass; +typedef ::std::vector< SvMetaClass* > SvMetaClassList; + +class SvClassElement +{ + OString aPrefix; + tools::SvRef<SvMetaClass> xClass; +public: + SvClassElement(); + SvClassElement(SvMetaClass* pClass) { xClass = pClass; } + + void SetPrefix( const OString& rPrefix ) + { aPrefix = rPrefix; } + const OString& GetPrefix() const + { return aPrefix; } + + void SetClass( SvMetaClass * pClass ) + { xClass = pClass; } + SvMetaClass * GetClass() const + { return xClass.get(); } +}; + + +class SvMetaClass : public SvMetaType +{ +public: + tools::SvRef<SvMetaClass> aSuperClass; + std::vector<SvClassElement> aClassElementList; + SvRefMemberList<SvMetaAttribute *> aAttrList; + bool TestAttribute( SvIdlDataBase & rBase, SvTokenStream & rInStm, + SvMetaAttribute & rAttr ) const; +private: + + static void WriteSlotStubs( std::string_view rShellName, + SvSlotElementList & rSlotList, + std::vector<OString> & rList, + SvStream & rOutStm ); + static sal_uInt16 WriteSlotParamArray( SvIdlDataBase & rBase, + SvSlotElementList & rSlotList, + SvStream & rOutStm ); + static sal_uInt16 WriteSlots( std::string_view rShellName, + SvSlotElementList & rSlotList, + SvIdlDataBase & rBase, + SvStream & rOutStm ); + + void InsertSlots( SvSlotElementList& rList, std::vector<sal_uLong>& rSuperList, + SvMetaClassList & rClassList, + const OString& rPrefix, SvIdlDataBase& rBase ); + +public: + SvMetaClass(); + virtual void ReadContextSvIdl( SvIdlDataBase &, + SvTokenStream & rInStm ) override; + + void FillClasses( SvMetaClassList & rList ); + + virtual void WriteSfx( SvIdlDataBase & rBase, SvStream & rOutStm ) override; +}; + +#endif // INCLUDED_IDL_INC_OBJECT_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idl/inc/parser.hxx b/idl/inc/parser.hxx new file mode 100644 index 000000000..ae9db7105 --- /dev/null +++ b/idl/inc/parser.hxx @@ -0,0 +1,72 @@ +/* -*- 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 . + */ + +#ifndef INCLUDED_IDL_INC_PARSER_HXX +#define INCLUDED_IDL_INC_PARSER_HXX + +#include <rtl/ustring.hxx> +#include "types.hxx" + +class SvTokenStream; +class SvIdlDataBase; +class SvMetaModule; +class SvMetaTypeEnum; +class SvStringHashEntry; +class SvMetaType; +class SvMetaClass; +class SvBOOL; + +class SvIdlParser +{ + SvIdlDataBase& rBase; + SvTokenStream & rInStm; +public: + SvIdlParser( SvIdlDataBase& rBase_, SvTokenStream & rInStrm_) : rBase(rBase_), rInStm(rInStrm_) {} + void ReadSvIdl( const OUString & rPath ); + void ReadModuleHeader(SvMetaModule& rModule); + void ReadModuleBody(SvMetaModule& rModule); + void ReadModuleElement( SvMetaModule& rModule ); + void ReadInclude( SvMetaModule& rModule ); + void ReadInterfaceOrShell( SvMetaModule& rModule, MetaTypeType aMetaTypeType ); + void ReadInterfaceOrShellEntry( SvMetaClass& rClass ); + bool ReadSlot( SvMetaSlot& rSlot ); + void ReadInterfaceOrShellMethod( SvMetaAttribute& rAttr ); + void ReadItem(); + void ReadStruct(); + void ReadEnum(); + void ReadEnumValue( SvMetaTypeEnum& rEnum ); + void ReadSlotId(SvIdentifier& rSlotId); + void ReadSlotAttribute( SvMetaSlot& rSlot ); + SvMetaClass* ReadKnownClass(); + SvMetaType* ReadKnownType(); + void Read(char cChar); + bool ReadIfBoolAttribute( SvBOOL&, SvStringHashEntry const * pName); + void ReadIfIdAttribute( SvIdentifier& rIdentifier, SvStringHashEntry const * pName ); + bool ReadIf(char cChar); + void ReadDelimiter(); + bool ReadIfDelimiter(); + OString ReadIdentifier(); + OString ReadString(); + void Read(SvStringHashEntry const *); + bool ReadIf(SvStringHashEntry const *); +}; + +#endif // INCLUDED_IDL_INC_PARSER_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idl/inc/slot.hxx b/idl/inc/slot.hxx new file mode 100644 index 000000000..f8ba61d98 --- /dev/null +++ b/idl/inc/slot.hxx @@ -0,0 +1,134 @@ +/* -*- 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 . + */ + +#ifndef INCLUDED_IDL_INC_SLOT_HXX +#define INCLUDED_IDL_INC_SLOT_HXX + +#include "types.hxx" + +#include <tools/solar.h> + +class SvMetaSlot : public SvMetaAttribute +{ +public: + SvIdentifier aGroupId; + SvIdentifier aExecMethod; + SvIdentifier aStateMethod; + + SvBOOL aToggle; + SvBOOL aAutoUpdate; + + SvBOOL aAsynchron; + + SvBOOL aRecordPerItem;// exclusive + SvBOOL aRecordPerSet; + SvBOOL aNoRecord; + SvBOOL aRecordAbsolute; + + SvBOOL aMenuConfig; + SvBOOL aToolBoxConfig; + SvBOOL aAccelConfig; + SvBOOL aFastCall; + SvBOOL aContainer; + OString aDisableFlags; + SvMetaSlot* pNextSlot; + sal_uLong nListPos; + SvBOOL aReadOnlyDoc; + + void WriteSlot( std::string_view rShellName, + sal_uInt16 nCount, std::string_view rSlotId, + SvSlotElementList &rList, + size_t nStart, + SvIdlDataBase & rBase, SvStream & rOutStm ); + + bool IsVariable() const; + bool IsMethod() const; + + void SetRecordPerItem( bool bSet ) + { + aRecordPerItem = bSet; + if( bSet ) + aRecordPerSet = aNoRecord = false; + } + void SetRecordPerSet( bool bSet ) + { + aRecordPerSet = bSet; + if( bSet ) + aRecordPerItem = aNoRecord = false; + } + void SetNoRecord( bool bSet ) + { + aNoRecord = bSet; + if( bSet ) + aRecordPerItem = aRecordPerSet = false; + } + +public: + SvMetaSlot(); + SvMetaSlot( SvMetaType * pType ); + + const OString& GetGroupId() const; + const OString& GetExecMethod() const; + const OString& GetStateMethod() const; + const OString& GetDisableFlags() const; + bool GetToggle() const; + bool GetAutoUpdate() const; + + bool GetAsynchron() const; + + bool GetRecordPerItem() const; + bool GetRecordPerSet() const; + bool GetNoRecord() const; + bool GetRecordAbsolute() const; + + bool GetMenuConfig() const; + bool GetToolBoxConfig() const; + bool GetAccelConfig() const; + bool GetFastCall() const; + bool GetContainer() const; + bool GetReadOnlyDoc() const; + + sal_uLong GetListPos() const + { return nListPos; } + void SetListPos(sal_uLong n) + { nListPos = n; } + void ResetSlotPointer() + { pNextSlot = nullptr; } + + virtual bool Test( SvTokenStream & rInStm ) override; + virtual void ReadAttributesSvIdl( SvIdlDataBase & rBase, + SvTokenStream & rInStm ) override; + virtual bool ReadSvIdl( SvIdlDataBase &, SvTokenStream & rInStm ) override; + virtual void Insert( SvSlotElementList& ) override; + void WriteSlotStubs( std::string_view rShellName, + std::vector<OString> & rList, + SvStream & rOutStm ) const; + sal_uInt16 WriteSlotMap( std::string_view rShellName, + sal_uInt16 nCount, + SvSlotElementList&, + size_t nStart, + SvIdlDataBase & rBase, + SvStream & rOutStm ); + sal_uInt16 WriteSlotParamArray( SvIdlDataBase & rBase, + SvStream & rOutStm ) const; +}; + +#endif // INCLUDED_IDL_INC_SLOT_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idl/inc/types.hxx b/idl/inc/types.hxx new file mode 100644 index 000000000..badab618e --- /dev/null +++ b/idl/inc/types.hxx @@ -0,0 +1,118 @@ +/* -*- 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 . + */ + +#ifndef INCLUDED_IDL_INC_TYPES_HXX +#define INCLUDED_IDL_INC_TYPES_HXX + +#include <rtl/strbuf.hxx> +#include <tools/ref.hxx> +#include "basobj.hxx" + +class SvMetaType; +class SvMetaSlot; +typedef SvRefMemberList< SvMetaSlot* > SvSlotElementList; + +class SvMetaAttribute : public SvMetaReference +{ +public: + tools::SvRef<SvMetaType> aType; + SvIdentifier aSlotId; + SvMetaAttribute(); + SvMetaAttribute( SvMetaType * ); + + void SetSlotId( const SvIdentifier & rId ) + { aSlotId = rId; } + const SvIdentifier& GetSlotId() const; + SvMetaType * GetType() const; + + virtual bool Test( SvTokenStream & rInStm ); + virtual bool ReadSvIdl( SvIdlDataBase &, SvTokenStream & rInStm ) override; + size_t MakeSfx( OStringBuffer& rAtrrArray ) const; + virtual void Insert( SvSlotElementList& ); +}; + +enum MetaTypeType { Method, Struct, Base, Enum, Interface, Shell }; + +class SvMetaType : public SvMetaReference +{ + SvRefMemberList<SvMetaAttribute *> aAttrList; + MetaTypeType nType; + bool bIsItem; + + void WriteSfxItem( std::string_view rItemName, SvIdlDataBase const & rBase, + SvStream & rOutStm ); +protected: + bool ReadHeaderSvIdl( SvTokenStream & rInStm ); +public: + SvMetaType(); + SvMetaType( const OString& rTypeName ); + + virtual ~SvMetaType() override; + + virtual void ReadContextSvIdl( SvIdlDataBase &, SvTokenStream & rInStm ) override; + + SvRefMemberList<SvMetaAttribute *>& + GetAttrList() { return aAttrList; } + size_t GetAttrCount() const { return aAttrList.size(); } + + void SetType( MetaTypeType nT ); + MetaTypeType GetMetaTypeType() const { return nType; } + SvMetaType * GetBaseType() const; + SvMetaType * GetReturnType() const; + void SetItem(bool b) { bIsItem = b; } + bool IsItem() const { return bIsItem; } + + virtual bool ReadSvIdl( SvIdlDataBase &, SvTokenStream & rInStm ) override; + + size_t MakeSfx( OStringBuffer& rAtrrArray ); + virtual void WriteSfx( SvIdlDataBase & rBase, SvStream & rOutStm ); + bool ReadMethodArgs( SvIdlDataBase & rBase, + SvTokenStream & rInStm ); +}; + +class SvMetaTypeString final : public SvMetaType +{ +public: + SvMetaTypeString(); +}; + +class SvMetaEnumValue final : public SvMetaObject +{ +public: + SvMetaEnumValue(); +}; + +class SvMetaTypeEnum final : public SvMetaType +{ +public: + SvRefMemberList<SvMetaEnumValue *> aEnumValueList; + OString aPrefix; + SvMetaTypeEnum(); +}; + +class SvMetaTypevoid final : public SvMetaType +{ +public: + SvMetaTypevoid(); +}; + + +#endif // INCLUDED_IDL_INC_TYPES_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idl/source/cmptools/hash.cxx b/idl/source/cmptools/hash.cxx new file mode 100644 index 000000000..d3993881a --- /dev/null +++ b/idl/source/cmptools/hash.cxx @@ -0,0 +1,65 @@ +/* -*- 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 . + */ + + +// program-sensitive includes +#include <hash.hxx> + +SvStringHashEntry * SvStringHashTable::Insert( const OString& rElement, sal_uInt32 * pInsertPos ) +{ + auto it = maString2IntMap.find(rElement); + if (it != maString2IntMap.end()) { + *pInsertPos = it->second; + return maInt2EntryMap[*pInsertPos].get(); + } + maString2IntMap[rElement] = mnNextId; + maInt2EntryMap[mnNextId] = std::make_unique<SvStringHashEntry>(rElement); + *pInsertPos = mnNextId; + mnNextId++; + return maInt2EntryMap[*pInsertPos].get(); +} + +bool SvStringHashTable::Test( const OString& rElement, sal_uInt32 * pInsertPos ) +{ + auto it = maString2IntMap.find(rElement); + if (it != maString2IntMap.end()) { + *pInsertPos = it->second; + return true; + } + return false; +} + +SvStringHashEntry * SvStringHashTable::Get( sal_uInt32 nInsertPos ) const +{ + auto it = maInt2EntryMap.find(nInsertPos); + return it->second.get(); +} + +OString SvStringHashTable::GetNearString( std::string_view rName ) const +{ + for( auto const & rPair : maInt2EntryMap ) + { + SvStringHashEntry * pE = rPair.second.get(); + if( pE->GetName().equalsIgnoreAsciiCase( rName ) && pE->GetName() != rName ) + return pE->GetName(); + } + return OString(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idl/source/cmptools/lex.cxx b/idl/source/cmptools/lex.cxx new file mode 100644 index 000000000..eb9ad1170 --- /dev/null +++ b/idl/source/cmptools/lex.cxx @@ -0,0 +1,336 @@ +/* -*- 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 <memory> +#include <hash.hxx> +#include <lex.hxx> +#include <globals.hxx> +#include <rtl/strbuf.hxx> +#include<rtl/character.hxx> + +OString SvToken::GetTokenAsString() const +{ + OString aStr; + switch( nType ) + { + case SVTOKENTYPE::Empty: + break; + case SVTOKENTYPE::Comment: + aStr = aString; + break; + case SVTOKENTYPE::Integer: + aStr = OString::number(nLong); + break; + case SVTOKENTYPE::String: + aStr = aString; + break; + case SVTOKENTYPE::Bool: + aStr = bBool ? "TRUE" : "FALSE"; + break; + case SVTOKENTYPE::Identifier: + aStr = aString; + break; + case SVTOKENTYPE::Char: + aStr = OString(cChar); + break; + case SVTOKENTYPE::EndOfFile: + case SVTOKENTYPE::HashId: + break; + } + + return aStr; +} + +SvToken & SvToken::operator = ( const SvToken & rObj ) +{ + if( this != &rObj ) + { + nLine = rObj.nLine; + nColumn = rObj.nColumn; + nType = rObj.nType; + aString = rObj.aString; + nLong = rObj.nLong; + } + return *this; +} + +void SvTokenStream::InitCtor() +{ + aStrTrue = OString("TRUE"); + aStrFalse = OString("FALSE"); + nLine = nColumn = 0; + nBufPos = 0; + nMaxPos = 0; + c = GetNextChar(); + FillTokenList(); +} + +SvTokenStream::SvTokenStream( const OUString & rFileName ) + : pInStream( new SvFileStream( rFileName, StreamMode::STD_READ ) ) + , aFileName( rFileName ) +{ + InitCtor(); +} + +SvTokenStream::~SvTokenStream() +{ +} + +void SvTokenStream::FillTokenList() +{ + SvToken * pToken = new SvToken(); + aTokList.push_back(std::unique_ptr<SvToken>(pToken)); + do + { + if( !MakeToken( *pToken ) ) + { + if (!aTokList.empty()) + { + *pToken = SvToken(); + std::vector<std::unique_ptr<SvToken> >::const_iterator it = aTokList.begin(); + + pToken->SetLine((*it)->GetLine()); + pToken->SetColumn((*it)->GetColumn()); + } + break; + } + else if( pToken->IsComment() ) + *pToken = SvToken(); + else if( pToken->IsEof() ) + break; + else + { + pToken = new SvToken(); + aTokList.push_back(std::unique_ptr<SvToken>(pToken)); + } + } + while( !pToken->IsEof() ); + pCurToken = aTokList.begin(); +} + +char SvTokenStream::GetNextChar() +{ + char nChar; + while (aBufStr.getLength() <= nBufPos) + { + if (pInStream->ReadLine(aBufStr)) + { + nLine++; + nColumn = 0; + nBufPos = 0; + } + else + { + aBufStr.clear(); + nColumn = 0; + nBufPos = 0; + return '\0'; + } + } + nChar = aBufStr[nBufPos++]; + nColumn += nChar == '\t' ? nTabSize : 1; + return nChar; +} + +sal_uInt64 SvTokenStream::GetNumber() +{ + sal_uInt64 l = 0; + short nLog = 10; + + if( '0' == c ) + { + c = GetFastNextChar(); + if( 'x' == c ) + { + nLog = 16; + c = GetFastNextChar(); + } + } + + if( nLog == 16 ) + { + while( rtl::isAsciiHexDigit( static_cast<unsigned char>(c) ) ) + { + if( rtl::isAsciiDigit( static_cast<unsigned char>(c) ) ) + l = l * nLog + (c - '0'); + else + l = l * nLog + + (rtl::toAsciiUpperCase( static_cast<unsigned char>(c) ) + - 'A' + 10 ); + c = GetFastNextChar(); + } + } + else + { + while( rtl::isAsciiDigit( static_cast<unsigned char>(c) ) || 'x' == c ) + { + l = l * nLog + (c - '0'); + c = GetFastNextChar(); + } + } + + return l; +} + +bool SvTokenStream::MakeToken( SvToken & rToken ) +{ + do + { + if( 0 == c ) + c = GetNextChar(); + // skip whitespace + while( rtl::isAsciiWhiteSpace( static_cast<unsigned char>(c) ) + || 26 == c ) + { + c = GetFastNextChar(); + nColumn += c == '\t' ? nTabSize : 1; + } + } + while( 0 == c && !IsEof() && ( ERRCODE_NONE == pInStream->GetError() ) ); + + sal_uInt64 nLastLine = nLine; + sal_uInt64 nLastColumn = nColumn; + // comment + if( '/' == c ) + { + // time optimization, no comments + char c1 = c; + c = GetFastNextChar(); + if( '/' == c ) + { + while( '\0' != c ) + { + c = GetFastNextChar(); + } + c = GetNextChar(); + rToken.nType = SVTOKENTYPE::Comment; + } + else if( '*' == c ) + { + c = GetFastNextChar(); + do + { + while( '*' != c ) + { + if( '\0' == c ) + { + c = GetNextChar(); + if( IsEof() ) + return false; + } + else + c = GetFastNextChar(); + } + c = GetFastNextChar(); + } + while( '/' != c && !IsEof() && ( ERRCODE_NONE == pInStream->GetError() ) ); + if( IsEof() || ( ERRCODE_NONE != pInStream->GetError() ) ) + return false; + c = GetNextChar(); + rToken.nType = SVTOKENTYPE::Comment; + CalcColumn(); + } + else + { + rToken.nType = SVTOKENTYPE::Char; + rToken.cChar = c1; + } + } + else if( c == '"' ) + { + OStringBuffer aStr(128); + bool bDone = false; + while( !bDone && !IsEof() && c ) + { + c = GetFastNextChar(); + if( '\0' == c ) + { + // read strings beyond end of line + aStr.append('\n'); + c = GetNextChar(); + if( IsEof() ) + return false; + } + if( c == '"' ) + { + c = GetFastNextChar(); + bDone = true; + } + else + aStr.append(c); + } + if( IsEof() || ( ERRCODE_NONE != pInStream->GetError() ) ) + return false; + rToken.nType = SVTOKENTYPE::String; + rToken.aString = aStr.makeStringAndClear(); + } + else if( rtl::isAsciiDigit( static_cast<unsigned char>(c) ) ) + { + rToken.nType = SVTOKENTYPE::Integer; + rToken.nLong = GetNumber(); + + } + else if( rtl::isAsciiAlpha (static_cast<unsigned char>(c)) || (c == '_') ) + { + OStringBuffer aBuf(64); + while( rtl::isAsciiAlphanumeric( static_cast<unsigned char>(c) ) + || c == '_' || c == ':') + { + aBuf.append(c); + c = GetFastNextChar(); + } + OString aStr = aBuf.makeStringAndClear(); + if( aStr.equalsIgnoreAsciiCase( aStrTrue ) ) + { + rToken.nType = SVTOKENTYPE::Bool; + rToken.bBool = true; + } + else if( aStr.equalsIgnoreAsciiCase( aStrFalse ) ) + { + rToken.nType = SVTOKENTYPE::Bool; + rToken.bBool = false; + } + else + { + sal_uInt32 nHashId; + if( GetIdlApp().pHashTable->Test( aStr, &nHashId ) ) + rToken.SetHash( GetIdlApp().pHashTable->Get( nHashId ) ); + else + { + rToken.nType = SVTOKENTYPE::Identifier; + rToken.aString = aStr; + } + } + } + else if( IsEof() ) + { + rToken.nType = SVTOKENTYPE::EndOfFile; + } + else + { + rToken.nType = SVTOKENTYPE::Char; + rToken.cChar = c; + c = GetFastNextChar(); + } + rToken.SetLine( nLastLine ); + rToken.SetColumn( nLastColumn ); + return pInStream->GetError() == ERRCODE_NONE; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idl/source/objects/basobj.cxx b/idl/source/objects/basobj.cxx new file mode 100644 index 000000000..872b42b39 --- /dev/null +++ b/idl/source/objects/basobj.cxx @@ -0,0 +1,141 @@ +/* -*- 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 <rtl/character.hxx> + +#include <basobj.hxx> +#include <database.hxx> + +void SvMetaObject::WriteTab( SvStream & rOutStm, sal_uInt16 nTab ) +{ + while( nTab-- ) + rOutStm.WriteCharPtr( " " ); +} + +void SvMetaObject::WriteStars( SvStream & rOutStm ) +{ + rOutStm.WriteChar( '/' ); + for( int i = 6; i > 0; i-- ) + rOutStm.WriteCharPtr( "**********" ); + rOutStm.WriteChar( '/' ) << endl; +} + +void SvMetaObject::Back2Delimiter( SvStream & rOutStm ) +{ + // write no empty brackets + sal_uInt64 nPos = rOutStm.Tell(); + rOutStm.SeekRel( -1 ); + char c = 0; + rOutStm.ReadChar( c ); + + while( rtl::isAsciiWhiteSpace( static_cast<unsigned char>(c) ) + && rOutStm.Tell() != 1 ) + { + rOutStm.SeekRel( -2 ); + rOutStm.ReadChar( c ); + } + + if( c == ';' || c == ',' ) + rOutStm.SeekRel( -1 ); + else + rOutStm.Seek( nPos ); +} + +SvMetaObject::SvMetaObject() +{ +} + +void SvMetaObject::SetName( const OString& rName ) +{ + aName = rName; +} + +bool SvMetaObject::ReadNameSvIdl( SvTokenStream & rInStm ) +{ + sal_uInt32 nTokPos = rInStm.Tell(); + SvToken& rTok = rInStm.GetToken_Next(); + + // read module name + if( rTok.IsIdentifier() ) + { + SetName( rTok.GetString() ); + return true; + } + + rInStm.Seek( nTokPos ); + return false; +} + +void SvMetaObject::ReadAttributesSvIdl( SvIdlDataBase & , + SvTokenStream & ) +{ +} + +void SvMetaObject::DoReadContextSvIdl( SvIdlDataBase & rBase, + SvTokenStream & rInStm ) +{ + sal_uInt32 nBeginPos = 0; // can not happen with Tell + while( nBeginPos != rInStm.Tell() ) + { + nBeginPos = rInStm.Tell(); + ReadContextSvIdl( rBase, rInStm ); + rInStm.ReadIfDelimiter(); + } +} + +void SvMetaObject::ReadContextSvIdl( SvIdlDataBase &, SvTokenStream & ) +{ +} + +bool SvMetaObject::ReadSvIdl( SvIdlDataBase & rBase, SvTokenStream & rInStm ) +{ + sal_uInt32 nTokPos = rInStm.Tell(); + bool bOk = true; + if( rInStm.ReadIf( '[' ) ) + { + sal_uInt32 nBeginPos = 0; // can not happen with Tell + while( nBeginPos != rInStm.Tell() ) + { + nBeginPos = rInStm.Tell(); + ReadAttributesSvIdl( rBase, rInStm ); + rInStm.ReadIfDelimiter(); + } + bOk = rInStm.ReadIf( ']' ); + } + + if( bOk && rInStm.ReadIf( '{' ) ) + { + DoReadContextSvIdl( rBase, rInStm ); + bOk = rInStm.ReadIf( '}' ); + } + + if( !bOk ) + rInStm.Seek( nTokPos ); + return bOk; +} + + +SvMetaReference::SvMetaReference() +{ +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idl/source/objects/bastype.cxx b/idl/source/objects/bastype.cxx new file mode 100644 index 000000000..6a36db617 --- /dev/null +++ b/idl/source/objects/bastype.cxx @@ -0,0 +1,120 @@ +/* -*- 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 <bastype.hxx> +#include <lex.hxx> +#include <hash.hxx> +#include <database.hxx> + +bool SvBOOL::ReadSvIdl( SvStringHashEntry const * pName, SvTokenStream & rInStm ) +{ + 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"); + *this = rTok.GetBool(); + rInStm.GetToken_Next(); + } + else + *this = true; //default action set to TRUE + return true; + } + rInStm.Seek( nTokPos ); + return false; +} + +void SvIdentifier::ReadSvIdl( SvStringHashEntry const * pName, SvTokenStream & rInStm ) +{ + sal_uInt32 nTokPos = rInStm.Tell(); + SvToken& rTok = rInStm.GetToken_Next(); + + if( rTok.Is( pName ) ) + { + bool bOk = true; + bool bBracket = rInStm.ReadIf( '(' ); + if( bBracket || rInStm.ReadIf( '=' ) ) + { + rTok = rInStm.GetToken(); + if( rTok.IsIdentifier() ) + { + setString(rTok.GetString()); + rInStm.GetToken_Next(); + } + if( bOk && bBracket ) + bOk = rInStm.ReadIf( ')' ); + } + if( bOk ) + return; + } + rInStm.Seek( nTokPos ); +} + +void SvIdentifier::ReadSvIdl( SvIdlDataBase & rBase, + SvTokenStream & rInStm ) +{ + sal_uInt32 nTokPos = rInStm.Tell(); + SvToken& rTok = rInStm.GetToken_Next(); + + if( rTok.IsIdentifier() ) + { + sal_uInt32 n; + if( !rBase.FindId( rTok.GetString(), &n ) ) + rBase.SetAndWriteError( rInStm, "no value for identifier <" + getString() + "> " ); + setString(rTok.GetString()); + nValue = n; + return; + } + rInStm.Seek( nTokPos ); +} + +bool ReadStringSvIdl( SvStringHashEntry const * pName, SvTokenStream & rInStm, OString& aRetString ) +{ + sal_uInt32 nTokPos = rInStm.Tell(); + SvToken& rTok = rInStm.GetToken_Next(); + + if( rTok.Is( pName ) ) + { + bool bOk = true; + bool bBracket = rInStm.ReadIf( '(' ); + if( bBracket || rInStm.ReadIf( '=' ) ) + { + rTok = rInStm.GetToken(); + if( rTok.IsString() ) + { + aRetString = rTok.GetString(); + rInStm.GetToken_Next(); + } + if( bOk && bBracket ) + bOk = rInStm.ReadIf( ')' ); + } + if( bOk ) + return true; + } + rInStm.Seek( nTokPos ); + return false; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idl/source/objects/module.cxx b/idl/source/objects/module.cxx new file mode 100644 index 000000000..dc692f608 --- /dev/null +++ b/idl/source/objects/module.cxx @@ -0,0 +1,34 @@ +/* -*- 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 <module.hxx> +#include <database.hxx> + +SvMetaModule::SvMetaModule() {} + +void SvMetaModule::WriteSfx(SvIdlDataBase& rBase, SvStream& rOutStm) +{ + for (size_t n = 0; n < aClassList.size(); n++) + { + SvMetaClass* pClass = aClassList[n]; + pClass->WriteSfx(rBase, rOutStm); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idl/source/objects/object.cxx b/idl/source/objects/object.cxx new file mode 100644 index 000000000..510d3a8a7 --- /dev/null +++ b/idl/source/objects/object.cxx @@ -0,0 +1,347 @@ +/* -*- 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 <rtl/strbuf.hxx> +#include <sal/log.hxx> + +#include <object.hxx> +#include <globals.hxx> +#include <database.hxx> +#include <slot.hxx> + + +SvClassElement::SvClassElement() +{ +}; + +SvMetaClass::SvMetaClass() +{ +} + +void SvMetaClass::ReadContextSvIdl( SvIdlDataBase & rBase, + SvTokenStream & rInStm ) +{ + sal_uInt32 nTokPos = rInStm.Tell(); + SvToken& rTok = rInStm.GetToken_Next(); + + if( rTok.Is( SvHash_import() ) ) + { + SvMetaClass * pClass = rBase.ReadKnownClass( rInStm ); + if( !pClass ) + throw SvParseException( rInStm, "unknown imported interface" ); + SvClassElement aEle; + aEle.SetClass( pClass ); + aClassElementList.push_back( aEle ); + + rTok = rInStm.GetToken(); + if( rTok.IsString() ) + { + aEle.SetPrefix( rTok.GetString() ); + rInStm.GetToken_Next(); + } + return; + } + else + { + rInStm.Seek( nTokPos ); + SvMetaType * pType = rBase.ReadKnownType( rInStm ); + + bool bOk = false; + tools::SvRef<SvMetaAttribute> xAttr; + if( !pType || pType->IsItem() ) + { + xAttr = new SvMetaSlot( pType ); + if( xAttr->ReadSvIdl( rBase, rInStm ) ) + bOk = xAttr->Test( rInStm ); + } + else + { + xAttr = new SvMetaAttribute( pType ); + if( xAttr->ReadSvIdl( rBase, rInStm ) ) + bOk = xAttr->Test( rInStm ); + } + + if( bOk ) + bOk = TestAttribute( rBase, rInStm, *xAttr ); + if( bOk ) + { + if( !xAttr->GetSlotId().IsSet() ) + { + SvIdentifier aI; + aI.SetValue( rBase.GetUniqueId() ); + xAttr->SetSlotId( aI ); + } + aAttrList.push_back( xAttr.get() ); + return; + } + } + rInStm.Seek( nTokPos ); +} + +bool SvMetaClass::TestAttribute( SvIdlDataBase & rBase, SvTokenStream & rInStm, + SvMetaAttribute & rAttr ) const +{ + if ( !rAttr.GetRef() && dynamic_cast<const SvMetaSlot *>(&rAttr) ) + { + SAL_WARN( "idl", "new slot : " << rAttr.GetSlotId().getString() ); + } + + for( size_t n = 0; n < aAttrList.size(); n++ ) + { + SvMetaAttribute * pS = aAttrList[n]; + if( pS->GetName() == rAttr.GetName() ) + { + // values have to match + if( pS->GetSlotId().GetValue() != rAttr.GetSlotId().GetValue() ) + { + throw SvParseException( rInStm, "Attribute's " + pS->GetName() + " with different id's"); + } + } + else + { + sal_uInt32 nId1 = pS->GetSlotId().GetValue(); + sal_uInt32 nId2 = rAttr.GetSlotId().GetValue(); + if( nId1 == nId2 && nId1 != 0 ) + { + OString aStr = "Attribute " + pS->GetName() + " and Attribute " + rAttr.GetName() + " with equal id's"; + throw SvParseException(rInStm, aStr); + } + } + } + SvMetaClass * pSC = aSuperClass.get(); + if( pSC ) + return pSC->TestAttribute( rBase, rInStm, rAttr ); + return true; +} + +sal_uInt16 SvMetaClass::WriteSlotParamArray( SvIdlDataBase & rBase, + SvSlotElementList & rSlotList, + SvStream & rOutStm ) +{ + sal_uInt16 nCount = 0; + for ( size_t i = 0, n = rSlotList.size(); i < n; ++i ) + { + SvMetaSlot *pAttr = rSlotList[ i ]; + nCount = nCount + pAttr->WriteSlotParamArray( rBase, rOutStm ); + } + + return nCount; +} + +sal_uInt16 SvMetaClass::WriteSlots( std::string_view rShellName, + SvSlotElementList & rSlotList, + SvIdlDataBase & rBase, + SvStream & rOutStm ) +{ + sal_uInt16 nSCount = 0; + for ( size_t i = 0, n = rSlotList.size(); i < n; ++i ) + { + SvMetaSlot * pAttr = rSlotList[ i ]; + nSCount = nSCount + pAttr->WriteSlotMap( rShellName, nSCount, + rSlotList, i, rBase, + rOutStm ); + } + + return nSCount; +} + +void SvMetaClass::InsertSlots( SvSlotElementList& rList, std::vector<sal_uLong>& rSuperList, + SvMetaClassList &rClassList, + const OString& rPrefix, SvIdlDataBase& rBase) +{ + // was this class already written? + for ( size_t i = 0, n = rClassList.size(); i < n ; ++i ) + if ( rClassList[ i ] == this ) + return; + + rClassList.push_back( this ); + + // write all direct attributes + sal_uLong n; + for( n = 0; n < aAttrList.size(); n++ ) + { + SvMetaAttribute * pAttr = aAttrList[n]; + + sal_uLong nId = pAttr->GetSlotId().GetValue(); + + std::vector<sal_uLong>::iterator iter = std::find(rSuperList.begin(), + rSuperList.end(),nId); + + if( iter == rSuperList.end() ) + { + // Write only if not already written by subclass or + // imported interface. + rSuperList.push_back(nId); + pAttr->Insert(rList); + } + } + + // All Interfaces already imported by SuperShell should not be + // written any more. + // It is prohibited that Shell and SuperShell directly import the same + // class. + if( GetMetaTypeType() == MetaTypeType::Shell && aSuperClass.is() ) + aSuperClass->FillClasses( rClassList ); + + // Write all attributes of the imported classes, as long as they have + // not already been imported by the superclass. + for( n = 0; n < aClassElementList.size(); n++ ) + { + SvClassElement& rElement = aClassElementList[n]; + SvMetaClass * pCl = rElement.GetClass(); + OStringBuffer rPre(rPrefix.getLength() + 1 + rElement.GetPrefix().getLength()); + rPre.append(rPrefix); + if( !rPre.isEmpty() && !rElement.GetPrefix().isEmpty() ) + rPre.append('.'); + rPre.append(rElement.GetPrefix()); + + // first of all write direct imported interfaces + pCl->InsertSlots( rList, rSuperList, rClassList, + rPre.makeStringAndClear(), rBase ); + } + + // only write superclass if no shell and not in the list + if( GetMetaTypeType() != MetaTypeType::Shell && aSuperClass.is() ) + { + aSuperClass->InsertSlots( rList, rSuperList, rClassList, rPrefix, rBase ); + } +} + +void SvMetaClass::FillClasses( SvMetaClassList & rList ) +{ + // Am I not yet in? + for ( size_t i = 0, n = rList.size(); i < n; ++i ) + if ( rList[ i ] == this ) + return; + + rList.push_back( this ); + + // my imports + for( size_t n = 0; n < aClassElementList.size(); n++ ) + { + SvClassElement& rElement = aClassElementList[n]; + SvMetaClass * pCl = rElement.GetClass(); + pCl->FillClasses( rList ); + } + + // my superclass + if( aSuperClass.is() ) + aSuperClass->FillClasses( rList ); +} + + +void SvMetaClass::WriteSlotStubs( std::string_view rShellName, + SvSlotElementList & rSlotList, + std::vector<OString> & rList, + SvStream & rOutStm ) +{ + // write all attributes + for ( size_t i = 0, n = rSlotList.size(); i < n; ++i ) + { + SvMetaSlot *pAttr = rSlotList[ i ]; + pAttr->WriteSlotStubs( rShellName, rList, rOutStm ); + } +} + +void SvMetaClass::WriteSfx( SvIdlDataBase & rBase, SvStream & rOutStm ) +{ + WriteStars( rOutStm ); + // define class + rOutStm.WriteCharPtr( "#ifdef ShellClass_" ).WriteOString( GetName() ) << endl; + rOutStm.WriteCharPtr( "#undef ShellClass" ) << endl; + rOutStm.WriteCharPtr( "#undef ShellClass_" ).WriteOString( GetName() ) << endl; + rOutStm.WriteCharPtr( "#define ShellClass " ).WriteOString( GetName() ) << endl; + + // no slotmaps get written for interfaces + if( GetMetaTypeType() != MetaTypeType::Shell ) + { + rOutStm.WriteCharPtr( "#endif" ) << endl << endl; + return; + } + // write parameter array + rOutStm.WriteCharPtr("static SfxFormalArgument a").WriteOString(GetName()).WriteCharPtr("Args_Impl[] =") << endl; + rOutStm.WriteChar('{') << endl; + + std::vector<sal_uLong> aSuperList; + SvMetaClassList classList; + SvSlotElementList aSlotList; + InsertSlots(aSlotList, aSuperList, classList, OString(), rBase); + for ( size_t i = 0, n = aSlotList.size(); i < n; ++i ) + { + SvMetaSlot *pSlot = aSlotList[ i ]; + pSlot->SetListPos( i ); + } + + size_t nSlotCount = aSlotList.size(); + + // write all attributes + sal_uInt16 nArgCount = WriteSlotParamArray( rBase, aSlotList, rOutStm ); + if( nArgCount ) + Back2Delimiter( rOutStm ); + else + { + // at least one dummy + WriteTab( rOutStm, 1 ); + rOutStm.WriteCharPtr("{ (const SfxType*) &aSfxVoidItem_Impl, 0, 0 }" ) << endl; + } + rOutStm << endl; + rOutStm.WriteCharPtr( "};" ) << endl << endl; + + std::vector<OString> aStringList; + WriteSlotStubs( GetName(), aSlotList, aStringList, rOutStm ); + aStringList.clear(); + + rOutStm << endl; + + // write slotmap + rOutStm.WriteCharPtr("static SfxSlot a").WriteOString(GetName()).WriteCharPtr("Slots_Impl[] =") << endl; + rOutStm.WriteChar( '{' ) << endl; + + // write all attributes + WriteSlots( GetName(), aSlotList, rBase, rOutStm ); + if( nSlotCount ) + Back2Delimiter( rOutStm ); + else + { + // at least one dummy + WriteTab( rOutStm, 1 ); + rOutStm.WriteCharPtr( "SFX_SLOT_ARG(" ).WriteOString( GetName() ) + .WriteCharPtr( ", 0, SfxGroupId::NONE, " ) + .WriteCharPtr( "SFX_STUB_PTR_EXEC_NONE," ) + .WriteCharPtr( "SFX_STUB_PTR_STATE_NONE," ) + .WriteCharPtr( "SfxSlotMode::NONE, SfxVoidItem, 0, 0, \"\", SfxSlotMode::NONE )" ) << endl; + } + rOutStm << endl; + rOutStm.WriteCharPtr( "};" ) << endl; + rOutStm.WriteCharPtr( "#endif" ) << endl << endl; + + for( size_t i = 0, n = aSlotList.size(); i < n; ++i ) + { + SvMetaSlot* pAttr = aSlotList[ i ]; + pAttr->ResetSlotPointer(); + } + + aSlotList.clear(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idl/source/objects/slot.cxx b/idl/source/objects/slot.cxx new file mode 100644 index 000000000..17b8970ed --- /dev/null +++ b/idl/source/objects/slot.cxx @@ -0,0 +1,620 @@ +/* -*- 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 <osl/diagnose.h> +#include <tools/debug.hxx> +#include <slot.hxx> +#include <globals.hxx> +#include <database.hxx> + + +SvMetaSlot::SvMetaSlot() + : aRecordPerSet( true ) + , aRecordAbsolute( false ) + , pNextSlot(nullptr) + , nListPos(0) + , aReadOnlyDoc ( true ) +{ +} + +SvMetaSlot::SvMetaSlot( SvMetaType * pType ) + : SvMetaAttribute( pType ) + , aRecordPerSet( true ) + , aRecordAbsolute( false ) + , pNextSlot(nullptr) + , nListPos(0) + , aReadOnlyDoc ( true ) +{ +} + +bool SvMetaSlot::GetReadOnlyDoc() const +{ + if( aReadOnlyDoc.IsSet() || !GetRef() ) return aReadOnlyDoc; + return static_cast<SvMetaSlot *>(GetRef())->GetReadOnlyDoc(); +} + +bool SvMetaSlot::IsVariable() const +{ + SvMetaType * pType = GetType(); + return pType->GetMetaTypeType() != MetaTypeType::Method; +} + +bool SvMetaSlot::IsMethod() const +{ + SvMetaType * pType = GetType(); + return pType->GetMetaTypeType() == MetaTypeType::Method; +} + +/************************************************************************* +|* reference +|* +|* description Second FALSE in the SvBOOL-Objects means +|* IsSet() provides FALSE (default initialization). +*************************************************************************/ +/** reference disbandment **/ +const OString& SvMetaSlot::GetGroupId() const +{ + if( !aGroupId.getString().isEmpty() || !GetRef() ) return aGroupId.getString(); + return static_cast<SvMetaSlot *>(GetRef())->GetGroupId(); +} +const OString& SvMetaSlot::GetDisableFlags() const +{ + if( !aDisableFlags.isEmpty() || !GetRef() ) return aDisableFlags; + return static_cast<SvMetaSlot *>(GetRef())->GetDisableFlags(); +} +const OString& SvMetaSlot::GetExecMethod() const +{ + if( !aExecMethod.getString().isEmpty() || !GetRef() ) return aExecMethod.getString(); + return static_cast<SvMetaSlot *>(GetRef())->GetExecMethod(); +} +const OString& SvMetaSlot::GetStateMethod() const +{ + if( !aStateMethod.getString().isEmpty() || !GetRef() ) return aStateMethod.getString(); + return static_cast<SvMetaSlot *>(GetRef())->GetStateMethod(); +} +bool SvMetaSlot::GetToggle() const +{ + if( aToggle.IsSet() || !GetRef() ) return aToggle; + return static_cast<SvMetaSlot *>(GetRef())->GetToggle(); +} +bool SvMetaSlot::GetAutoUpdate() const +{ + if( aAutoUpdate.IsSet() || !GetRef() ) return aAutoUpdate; + return static_cast<SvMetaSlot *>(GetRef())->GetAutoUpdate(); +} +bool SvMetaSlot::GetAsynchron() const +{ + // Synchron and Asynchron are exclusive + if( !GetRef() || aAsynchron.IsSet() ) + return aAsynchron; + return static_cast<SvMetaSlot *>(GetRef())->GetAsynchron(); +} +bool SvMetaSlot::GetRecordPerItem() const +{ + // Record- PerItem, No, PerSet and Manual are exclusive + if( !GetRef() || aRecordPerItem.IsSet() || aNoRecord.IsSet() + || aRecordPerSet.IsSet() ) + return aRecordPerItem; + return static_cast<SvMetaSlot *>(GetRef())->GetRecordPerItem(); +} +bool SvMetaSlot::GetRecordPerSet() const +{ + // Record- PerItem, No, PerSet and Manual are exclusive + if( !GetRef() || aRecordPerItem.IsSet() || aNoRecord.IsSet() + || aRecordPerSet.IsSet() ) + return aRecordPerSet; + return static_cast<SvMetaSlot *>(GetRef())->GetRecordPerSet(); +} +bool SvMetaSlot::GetNoRecord() const +{ + // Record- PerItem, No, PerSet and Manual are exclusive + if( !GetRef() || aRecordPerItem.IsSet() || aNoRecord.IsSet() + || aRecordPerSet.IsSet() ) + return aNoRecord; + return static_cast<SvMetaSlot *>(GetRef())->GetNoRecord(); +} +bool SvMetaSlot::GetRecordAbsolute() const +{ + if( !GetRef() || aRecordAbsolute.IsSet() ) + return aRecordAbsolute; + return static_cast<SvMetaSlot *>(GetRef())->GetRecordAbsolute(); +} +bool SvMetaSlot::GetMenuConfig() const +{ + if( aMenuConfig.IsSet() || !GetRef() ) return aMenuConfig; + return static_cast<SvMetaSlot *>(GetRef())->GetMenuConfig(); +} +bool SvMetaSlot::GetToolBoxConfig() const +{ + if( aToolBoxConfig.IsSet() || !GetRef() ) return aToolBoxConfig; + return static_cast<SvMetaSlot *>(GetRef())->GetToolBoxConfig(); +} +bool SvMetaSlot::GetAccelConfig() const +{ + if( aAccelConfig.IsSet() || !GetRef() ) return aAccelConfig; + return static_cast<SvMetaSlot *>(GetRef())->GetAccelConfig(); +} +bool SvMetaSlot::GetFastCall() const +{ + if( aFastCall.IsSet() || !GetRef() ) return aFastCall; + return static_cast<SvMetaSlot *>(GetRef())->GetFastCall(); +} +bool SvMetaSlot::GetContainer() const +{ + if( aContainer.IsSet() || !GetRef() ) return aContainer; + return static_cast<SvMetaSlot *>(GetRef())->GetContainer(); +} + +void SvMetaSlot::ReadAttributesSvIdl( SvIdlDataBase & rBase, + SvTokenStream & rInStm ) +{ + SvMetaAttribute::ReadAttributesSvIdl( rBase, rInStm ); + + aGroupId.ReadSvIdl( SvHash_GroupId(), rInStm ); + aExecMethod.ReadSvIdl( SvHash_ExecMethod(), rInStm ); + aStateMethod.ReadSvIdl( SvHash_StateMethod(), rInStm ); + ReadStringSvIdl( SvHash_DisableFlags(), rInStm, aDisableFlags ); + aReadOnlyDoc.ReadSvIdl( SvHash_ReadOnlyDoc(), rInStm ); + aToggle.ReadSvIdl( SvHash_Toggle(), rInStm ); + aAutoUpdate.ReadSvIdl( SvHash_AutoUpdate(), rInStm ); + aAsynchron.ReadSvIdl( SvHash_Asynchron(), rInStm ); + aRecordAbsolute.ReadSvIdl( SvHash_RecordAbsolute(), rInStm ); + + if( aRecordPerItem.ReadSvIdl( SvHash_RecordPerItem(), rInStm ) ) + { + SetRecordPerItem( aRecordPerItem ); + } + if( aRecordPerSet.ReadSvIdl( SvHash_RecordPerSet(), rInStm ) ) + { + SetRecordPerSet( aRecordPerSet ); + } + if( aNoRecord.ReadSvIdl( SvHash_NoRecord(), rInStm ) ) + { + SetNoRecord( aNoRecord ); + } + + aMenuConfig.ReadSvIdl( SvHash_MenuConfig(), rInStm ); + aToolBoxConfig.ReadSvIdl( SvHash_ToolBoxConfig(), rInStm ); + aAccelConfig.ReadSvIdl( SvHash_AccelConfig(), rInStm ); + + aFastCall.ReadSvIdl( SvHash_FastCall(), rInStm ); + aContainer.ReadSvIdl( SvHash_Container(), rInStm ); +} + +bool SvMetaSlot::Test( SvTokenStream & rInStm ) +{ + bool bOk = SvMetaAttribute::Test( rInStm ); + if( bOk ) + { + SvMetaType * pType = GetType(); + if( pType->GetMetaTypeType() == MetaTypeType::Method ) + pType = pType->GetReturnType(); + if( !pType->IsItem() ) + { + throw SvParseException( rInStm, "this attribute is not a slot" ); + } + } + + return bOk; +} + +bool SvMetaSlot::ReadSvIdl( SvIdlDataBase & rBase, SvTokenStream & rInStm ) +{ + sal_uInt32 nTokPos = rInStm.Tell(); + bool bOk = true; + + SvMetaAttribute * pAttr = rBase.ReadKnownAttr( rInStm, GetType() ); + if( pAttr ) + { + // c + SvMetaSlot * pKnownSlot = dynamic_cast<SvMetaSlot*>( pAttr ); + if( !pKnownSlot ) + throw SvParseException( rInStm, "attribute " + pAttr->GetName() + " is method or variable but not a slot" ); + SetRef( pKnownSlot ); + SetName( pKnownSlot->GetName() ); + bOk = SvMetaObject::ReadSvIdl( rBase, rInStm ); + } + else + { + bOk = SvMetaAttribute::ReadSvIdl( rBase, rInStm ); + + SvMetaAttribute *pAttr2 = rBase.FindKnownAttr( GetSlotId() ); + if( pAttr2 ) + { + // for testing purposes: reference in case of complete definition + SvMetaSlot * pKnownSlot = dynamic_cast<SvMetaSlot*>( pAttr2 ); + if( !pKnownSlot ) + throw SvParseException( rInStm, "attribute " + pAttr2->GetName() + " is method or variable but not a slot" ); + SetRef( pKnownSlot ); + + // names may differ, because explicitly given + if ( pKnownSlot->GetName() != GetName() ) + { + OSL_FAIL("Illegal definition!"); + rInStm.Seek( nTokPos ); + return false; + } + + SetName( pKnownSlot->GetName() ); + } + } + + if( !bOk ) + rInStm.Seek( nTokPos ); + + return bOk; +} + +void SvMetaSlot::Insert( SvSlotElementList& rList) +{ + // get insert position through binary search in slotlist + sal_uInt16 nId = static_cast<sal_uInt16>(GetSlotId().GetValue()); + sal_uInt16 nListCount = static_cast<sal_uInt16>(rList.size()); + sal_uInt16 nPos; + + if ( !nListCount ) + nPos = 0; + else if ( nListCount == 1 ) + nPos = rList[ 0 ]->GetSlotId().GetValue() >= nId ? 0 : 1; + else + { + sal_uInt16 nMid = 0, nLow = 0; + sal_uInt16 nHigh = nListCount - 1; + bool bFound = false; + while ( !bFound && nLow <= nHigh ) + { + nMid = (nLow + nHigh) >> 1; + DBG_ASSERT( nMid < nListCount, "bsearch is buggy" ); + int nDiff = static_cast<int>(nId) - static_cast<int>(rList[ nMid ]->GetSlotId().GetValue()); + if ( nDiff < 0) + { + if ( nMid == 0 ) + break; + nHigh = nMid - 1; + } + else if ( nDiff > 0 ) + { + nLow = nMid + 1; + if ( nLow == 0 ) + break; + } + else + bFound = true; + } + + DBG_ASSERT(!bFound, "Duplicate SlotId!"); + nPos = bFound ? nMid : nLow; + } + + DBG_ASSERT( nPos <= nListCount, + "nPos too large" ); + DBG_ASSERT( nPos == nListCount || nId <= + static_cast<sal_uInt16>(rList[ nPos ]->GetSlotId().GetValue()), + "Successor has lower SlotId" ); + DBG_ASSERT( nPos == 0 || nId > + static_cast<sal_uInt16>(rList[ nPos-1 ]->GetSlotId().GetValue()), + "Predecessor has higher SlotId" ); + DBG_ASSERT( nPos+1 >= nListCount || nId < + static_cast<sal_uInt16>(rList[ nPos+1 ]->GetSlotId().GetValue()), + "Successor has lower SlotId" ); + + if ( nPos < rList.size() ) + { + SvSlotElementList::iterator it = rList.begin(); + std::advance( it, nPos ); + rList.insert( it, this ); + } + else + { + rList.push_back( this ); + } +} + + +static OString MakeSlotName( SvStringHashEntry const * pEntry ) +{ + return "SfxSlotMode::" + pEntry->GetName().toAsciiUpperCase(); +}; + +void SvMetaSlot::WriteSlotStubs( std::string_view rShellName, + std::vector<OString> & rList, + SvStream & rOutStm ) const +{ + OString aMethodName( GetExecMethod() ); + if ( !aMethodName.isEmpty() && + aMethodName != "NoExec" ) + { + bool bIn = false; + for( size_t n = 0; n < rList.size(); n++ ) + { + if (rList[n] == aMethodName) + { + bIn = true; + break; + } + } + + if ( !bIn ) + { + rList.push_back( aMethodName ); + rOutStm.WriteCharPtr( "SFX_EXEC_STUB(" ) + .WriteOString( rShellName ) + .WriteChar( ',' ) + .WriteOString( aMethodName ) + .WriteChar( ')' ) << endl; + } + } + + aMethodName = GetStateMethod(); + if (aMethodName.isEmpty() || aMethodName == "NoState") + return; + + bool bIn = false; + for ( size_t n=0; n < rList.size(); n++ ) + { + if (rList[n] == aMethodName) + { + bIn = true; + break; + } + } + + if ( !bIn ) + { + rList.push_back( aMethodName ); + rOutStm.WriteCharPtr( "SFX_STATE_STUB(" ) + .WriteOString( rShellName ) + .WriteChar( ',' ) + .WriteOString( aMethodName ) + .WriteChar( ')' ) << endl; + } +} + +void SvMetaSlot::WriteSlot( std::string_view rShellName, sal_uInt16 nCount, + std::string_view rSlotId, + SvSlotElementList& rSlotList, + size_t nStart, + SvIdlDataBase & rBase, SvStream & rOutStm ) +{ + rOutStm.WriteCharPtr( "// Slot Nr. " ) + .WriteOString( OString::number(nListPos) ) + .WriteCharPtr( " : " ); + OString aSlotIdValue(OString::number(GetSlotId().GetValue())); + rOutStm.WriteOString( aSlotIdValue ) << endl; + WriteTab( rOutStm, 1 ); + rOutStm.WriteCharPtr( "SFX_NEW_SLOT_ARG( " ).WriteOString( rShellName ).WriteChar( ',' ) ; + + rOutStm.WriteOString( rSlotId ).WriteChar( ',' ); + + // GroupId + if( !GetGroupId().isEmpty() ) + rOutStm.WriteOString( GetGroupId() ); + else + rOutStm.WriteCharPtr( "SfxGroupId::NONE" ); + rOutStm.WriteChar( ',' ) << endl; + WriteTab( rOutStm, 4 ); + + // look for the next slot with the same StateMethod like me + // the slotlist is set to the current slot + size_t i = nStart; + SvMetaSlot* pEle = ( ++i < rSlotList.size() ) ? rSlotList[ i ] : nullptr; + pNextSlot = pEle; + while ( pNextSlot ) + { + if ( !pNextSlot->pNextSlot && + pNextSlot->GetStateMethod() == GetStateMethod() + ) { + break; + } + pEle = ( ++i < rSlotList.size() ) ? rSlotList[ i ] : nullptr; + pNextSlot = pEle; + } + + if ( !pNextSlot ) + { + // There is no slot behind me that has the same ExecMethod. + // So I search for the first slot with it (could be myself). + i = 0; + pEle = rSlotList.empty() ? nullptr : rSlotList[ i ]; + pNextSlot = pEle; + while (pNextSlot && pNextSlot != this) + { + if ( pNextSlot->GetStateMethod() == GetStateMethod() ) + break; + pEle = ( ++i < rSlotList.size() ) ? rSlotList[ i ] : nullptr; + pNextSlot = pEle; + } + } + + assert(pNextSlot); + + rOutStm.WriteCharPtr( "&a" ).WriteOString( rShellName ).WriteCharPtr( "Slots_Impl[" ) + .WriteOString( OString::number(pNextSlot->GetListPos()) ) + .WriteCharPtr( "] /*Offset Next*/, " ) << endl; + + WriteTab( rOutStm, 4 ); + + // write ExecMethod, with standard name if not specified + if( !GetExecMethod().isEmpty() && + GetExecMethod() != "NoExec") + { + rOutStm.WriteCharPtr( "SFX_STUB_PTR(" ).WriteOString( rShellName ).WriteChar( ',' ) + .WriteOString( GetExecMethod() ).WriteChar( ')' ); + } + else + rOutStm.WriteCharPtr( "SFX_STUB_PTR_EXEC_NONE" ); + rOutStm.WriteChar( ',' ); + + // write StateMethod, with standard name if not specified + if( !GetStateMethod().isEmpty() && + GetStateMethod() != "NoState") + { + rOutStm.WriteCharPtr( "SFX_STUB_PTR(" ).WriteOString( rShellName ).WriteChar( ',' ) + .WriteOString( GetStateMethod() ).WriteChar( ')' ); + } + else + rOutStm.WriteCharPtr( "SFX_STUB_PTR_STATE_NONE" ); + + rOutStm.WriteChar( ',' ) << endl; + WriteTab( rOutStm, 4 ); + + // write flags + if( GetToggle() ) + rOutStm.WriteOString( MakeSlotName( SvHash_Toggle() ) ).WriteChar( '|' ); + if( GetAutoUpdate() ) + rOutStm.WriteOString( MakeSlotName( SvHash_AutoUpdate() ) ).WriteChar( '|' ); + if( GetAsynchron() ) + rOutStm.WriteOString( MakeSlotName( SvHash_Asynchron() ) ).WriteChar( '|' ); + if( GetRecordPerItem() ) + rOutStm.WriteOString( MakeSlotName( SvHash_RecordPerItem() ) ).WriteChar( '|' ); + if( GetRecordPerSet() ) + rOutStm.WriteOString( MakeSlotName( SvHash_RecordPerSet() ) ).WriteChar( '|' ); + if( GetNoRecord() ) + rOutStm.WriteOString( MakeSlotName( SvHash_NoRecord() ) ).WriteChar( '|' ); + if( GetRecordAbsolute() ) + rOutStm.WriteOString( MakeSlotName( SvHash_RecordAbsolute() ) ).WriteChar( '|' ); + if( GetMenuConfig() ) + rOutStm.WriteOString( MakeSlotName( SvHash_MenuConfig() ) ).WriteChar( '|' ); + if( GetToolBoxConfig() ) + rOutStm.WriteOString( MakeSlotName( SvHash_ToolBoxConfig() ) ).WriteChar( '|' ); + if( GetAccelConfig() ) + rOutStm.WriteOString( MakeSlotName( SvHash_AccelConfig() ) ).WriteChar( '|' ); + if( GetFastCall() ) + rOutStm.WriteOString( MakeSlotName( SvHash_FastCall() ) ).WriteChar( '|' ); + if( GetContainer() ) + rOutStm.WriteOString( MakeSlotName( SvHash_Container() ) ).WriteChar( '|' ); + if ( GetReadOnlyDoc() ) + rOutStm.WriteOString( MakeSlotName( SvHash_ReadOnlyDoc() ) ).WriteChar( '|' ); + rOutStm.WriteCharPtr( "SfxSlotMode::NONE" ); + + rOutStm.WriteChar( ',' ) << endl; + WriteTab( rOutStm, 4 ); + if ( GetDisableFlags().isEmpty() ) + rOutStm.WriteCharPtr( "SfxDisableFlags::NONE" ); + else + rOutStm.WriteOString( GetDisableFlags() ); + + // write attribute type + rOutStm.WriteChar( ',' ) << endl; + WriteTab( rOutStm, 4 ); + + SvMetaType * pT = GetType(); + if( !IsVariable() ) + { + SvMetaType * pRT = GetType()->GetReturnType(); + pT = pRT ? pRT : rBase.FindType( "SfxVoidItem" ); + } + + if( pT ) + { + assert(pT->IsItem()); + rOutStm.WriteOString( pT->GetName() ); + if( !SvIdlDataBase::FindType( pT, rBase.aUsedTypes ) ) + rBase.aUsedTypes.push_back( pT ); + } + else + rOutStm.WriteCharPtr( "SfxVoidItem not defined" ); + + { + rOutStm.WriteChar( ',' ) << endl; + WriteTab( rOutStm, 4 ); + rOutStm + .WriteOString( OString::number(nCount) ) + .WriteCharPtr( "/*Offset*/, " ); + + if( IsMethod() ) + { + SvMetaType * pType = GetType(); + sal_uLong nSCount = pType->GetAttrCount(); + rOutStm + .WriteOString( OString::number(nSCount) ) + .WriteCharPtr( "/*Count*/," ); + } + else + rOutStm.WriteCharPtr( "0," ); + + rOutStm.WriteCharPtr( " " ); + + // Method/Property flags + if( IsMethod() ) + rOutStm.WriteCharPtr( "SfxSlotMode::METHOD|" ); + + rOutStm.WriteCharPtr( "SfxSlotMode::NONE" ); + } + + { + rOutStm.WriteCharPtr( ",\"" ); + rOutStm.WriteOString( GetName() ); + rOutStm.WriteCharPtr( "\"" ); + } + + rOutStm.WriteCharPtr( " )," ) << endl; +} + +sal_uInt16 SvMetaSlot::WriteSlotParamArray( SvIdlDataBase & rBase, SvStream & rOutStm ) const +{ + if( !IsMethod() ) + return 0; + + SvMetaType * pType = GetType(); + + if( !SvIdlDataBase::FindType( pType, rBase.aUsedTypes ) ) + rBase.aUsedTypes.push_back( pType ); + + const SvRefMemberList<SvMetaAttribute *>& rList = + pType->GetAttrList(); + for( size_t n = 0; n < rList.size(); n++ ) + { + SvMetaAttribute * pPar = rList[n]; + SvMetaType * pPType = pPar->GetType(); + WriteTab( rOutStm, 1 ); + rOutStm.WriteCharPtr("{ (const SfxType*) &a") + // item type + .WriteOString(pPType->GetName()).WriteCharPtr("_Impl, ") + // parameter name + .WriteCharPtr("\"").WriteOString(pPar->GetName()).WriteCharPtr("\", ") + // slot id + .WriteOString(pPar->GetSlotId().getString()).WriteCharPtr(" },") << endl; + if( !SvIdlDataBase::FindType( pPType, rBase.aUsedTypes ) ) + rBase.aUsedTypes.push_back( pPType ); + } + return static_cast<sal_uInt16>(rList.size()); +} + +sal_uInt16 SvMetaSlot::WriteSlotMap( std::string_view rShellName, sal_uInt16 nCount, + SvSlotElementList& rSlotList, + size_t nStart, + SvIdlDataBase & rBase, + SvStream & rOutStm ) +{ + // SlotId, if not specified generate from name + OString slotId = GetSlotId().getString(); + + sal_uInt16 nSCount = 0; + if( IsMethod() ) + { + SvMetaType * pType = GetType(); + nSCount = static_cast<sal_uInt16>(pType->GetAttrCount()); + } + + WriteSlot( rShellName, nCount, slotId, rSlotList, nStart, rBase, rOutStm ); + return nSCount; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idl/source/objects/types.cxx b/idl/source/objects/types.cxx new file mode 100644 index 000000000..08492b4b6 --- /dev/null +++ b/idl/source/objects/types.cxx @@ -0,0 +1,320 @@ +/* -*- 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 <tools/debug.hxx> + +#include <types.hxx> +#include <globals.hxx> +#include <database.hxx> + +SvMetaAttribute::SvMetaAttribute() +{ +} + +SvMetaAttribute::SvMetaAttribute( SvMetaType * pType ) + : aType( pType ) +{ +} + +SvMetaType * SvMetaAttribute::GetType() const +{ + if( aType.is() || !GetRef() ) return aType.get(); + return static_cast<SvMetaAttribute *>(GetRef())->GetType(); +} + +const SvIdentifier & SvMetaAttribute::GetSlotId() const +{ + if( aSlotId.IsSet() || !GetRef() ) return aSlotId; + return static_cast<SvMetaAttribute *>(GetRef())->GetSlotId(); +} + +bool SvMetaAttribute::Test( SvTokenStream & rInStm ) +{ + if( GetType()->IsItem() && !GetSlotId().IsSet() ) + { + throw SvParseException( rInStm, "slot without id declared" ); + } + return true; +} + +bool SvMetaAttribute::ReadSvIdl( SvIdlDataBase & rBase, + SvTokenStream & rInStm ) +{ + sal_uInt32 nTokPos = rInStm.Tell(); + if( !GetType() ) + // no type in ctor passed on + aType = rBase.ReadKnownType( rInStm ); + bool bOk = false; + if( GetType() ) + { + ReadNameSvIdl( rInStm ); + aSlotId.ReadSvIdl( rBase, rInStm ); + + bOk = true; + SvToken& rTok = rInStm.GetToken(); + if( rTok.IsChar() && rTok.GetChar() == '(' ) + { + tools::SvRef<SvMetaType> xT(new SvMetaType() ); + xT->SetRef( GetType() ); + aType = xT; + bOk = aType->ReadMethodArgs( rBase, rInStm ); + } + if( bOk ) + bOk = SvMetaObject::ReadSvIdl( rBase, rInStm ); + } + else + { + SvToken& rTok = rInStm.GetToken(); + rBase.SetError( "unknown type of token. Each new SID needs an " + "item statement in an SDI file, eg. " + "SfxVoidItem FooItem " + rTok.GetTokenAsString() + + " ... which describes the slot more fully", rTok ); + } + + if( !bOk ) + rInStm.Seek( nTokPos ); + return bOk; +} + +size_t SvMetaAttribute::MakeSfx( OStringBuffer& rAttrArray ) const +{ + SvMetaType * pType = GetType(); + DBG_ASSERT( pType, "no type for attribute" ); + SvMetaType * pBaseType = pType->GetBaseType(); + DBG_ASSERT( pBaseType, "no base type for attribute" ); + if( pBaseType->GetMetaTypeType() == MetaTypeType::Struct ) + return pBaseType->MakeSfx( rAttrArray ); + else + { + rAttrArray.append('{'); + rAttrArray.append(GetSlotId().getString()); + rAttrArray.append(",\""); + rAttrArray.append(GetName()); + rAttrArray.append("\"}"); + return 1; + } +} + +void SvMetaAttribute::Insert(SvSlotElementList&) +{ +} + +SvMetaType::SvMetaType() + : nType( MetaTypeType::Base ) + , bIsItem( false ) +{ +} + +SvMetaType::SvMetaType( const OString& rName ) + : SvMetaType() +{ + SetName( rName ); +} + +SvMetaType::~SvMetaType() +{} + +void SvMetaType::SetType( MetaTypeType nT ) +{ + nType = nT; +} + +SvMetaType * SvMetaType::GetBaseType() const +{ + if( GetRef() && GetMetaTypeType() == MetaTypeType::Base ) + return static_cast<SvMetaType *>(GetRef())->GetBaseType(); + return const_cast<SvMetaType *>(this); +} + +SvMetaType * SvMetaType::GetReturnType() const +{ + DBG_ASSERT( GetMetaTypeType() == MetaTypeType::Method, "no method" ); + DBG_ASSERT( GetRef(), "no return type" ); + return static_cast<SvMetaType *>(GetRef()); +} + +bool SvMetaType::ReadHeaderSvIdl( SvTokenStream & rInStm ) +{ + bool bOk = false; + sal_uInt32 nTokPos = rInStm.Tell(); + SvToken& rTok = rInStm.GetToken_Next(); + + if( rTok.Is( SvHash_interface() ) ) + { + SetType( MetaTypeType::Interface ); + bOk = ReadNameSvIdl( rInStm ); + } + else if( rTok.Is( SvHash_shell() ) ) + { + SetType( MetaTypeType::Shell ); + bOk = ReadNameSvIdl( rInStm ); + } + if( !bOk ) + rInStm.Seek( nTokPos ); + return bOk; +} + +bool SvMetaType::ReadSvIdl( SvIdlDataBase & rBase, + SvTokenStream & rInStm ) +{ + if( ReadHeaderSvIdl( rInStm ) ) + { + rBase.Write(OString('.')); + return SvMetaReference::ReadSvIdl( rBase, rInStm ); + } + return false; +} + +void SvMetaType::ReadContextSvIdl( SvIdlDataBase & rBase, + SvTokenStream & rInStm ) +{ + tools::SvRef<SvMetaAttribute> xAttr( new SvMetaAttribute() ); + if( xAttr->ReadSvIdl( rBase, rInStm ) ) + { + if( xAttr->Test( rInStm ) ) + GetAttrList().push_back( xAttr.get() ); + } +} + +size_t SvMetaType::MakeSfx( OStringBuffer& rAttrArray ) +{ + size_t nC = 0; + + if( GetBaseType()->GetMetaTypeType() == MetaTypeType::Struct ) + { + size_t nAttrCount = GetAttrCount(); + // write the single attributes + for( size_t n = 0; n < nAttrCount; n++ ) + { + nC += aAttrList[n]->MakeSfx( rAttrArray ); + if( n +1 < nAttrCount ) + rAttrArray.append(", "); + } + } + return nC; +} + +void SvMetaType::WriteSfxItem( + std::string_view rItemName, SvIdlDataBase const & rBase, SvStream& rOutStm ) +{ + WriteStars( rOutStm ); + OString aVarName = OString::Concat(" a") + rItemName + "_Impl"; + + OStringBuffer aAttrArray(1024); + size_t nAttrCount = MakeSfx( aAttrArray ); + OString aAttrCount( OString::number(nAttrCount)); + OString aTypeName = "SfxType" + aAttrCount; + + bool bExport = false, bReturn = false; + // these are exported from sfx library + if (rItemName == "SfxBoolItem" || + rItemName == "SfxInt16Item" || + rItemName == "SfxStringItem" || + rItemName == "SfxUInt16Item" || + rItemName == "SfxUInt32Item" || + rItemName == "SfxVoidItem") + { + bExport = true; + if (!rBase.sSlotMapFile.endsWith("sfxslots.hxx")) + bReturn = true; + } + + rOutStm.WriteCharPtr( "extern " ); + if (bExport) + rOutStm.WriteCharPtr( "SFX2_DLLPUBLIC " ); + rOutStm.WriteOString( aTypeName ) + .WriteOString( aVarName ).WriteChar( ';' ) << endl; + if (bReturn) + return; + + // write the implementation part + rOutStm.WriteCharPtr( "#ifdef SFX_TYPEMAP" ) << endl; + rOutStm.WriteCharPtr( "#if !defined(_WIN32) && (defined(DISABLE_DYNLOADING) && (defined(ANDROID) || defined(IOS) || defined(EMSCRIPTEN) || defined(LINUX)))" ) << endl; + rOutStm.WriteCharPtr( "__attribute__((__weak__))" ) << endl; + rOutStm.WriteCharPtr( "#endif" ) << endl; + rOutStm.WriteOString( aTypeName ).WriteOString( aVarName ) + .WriteCharPtr( " = " ) << endl; + rOutStm.WriteChar( '{' ) << endl; + + rOutStm.WriteCharPtr( "\tcreateSfxPoolItem<" ).WriteOString( rItemName ) + .WriteCharPtr(">, &typeid(").WriteOString( rItemName ).WriteCharPtr( "), " ); + rOutStm.WriteOString( aAttrCount ); + if( nAttrCount ) + { + rOutStm.WriteCharPtr( ", { " ); + // write the single attributes + rOutStm.WriteCharPtr( aAttrArray.getStr() ); + rOutStm.WriteCharPtr( " }" ); + } + rOutStm << endl; + rOutStm.WriteCharPtr( "};" ) << endl; + rOutStm.WriteCharPtr( "#endif" ) << endl << endl; +} + +void SvMetaType::WriteSfx( SvIdlDataBase & rBase, SvStream & rOutStm ) +{ + if( IsItem() ) + { + if( GetBaseType()->GetMetaTypeType() == MetaTypeType::Struct ) + GetBaseType()->WriteSfxItem( GetName(), rBase, rOutStm ); + else + WriteSfxItem( GetName(), rBase, rOutStm ); + } +} + +bool SvMetaType::ReadMethodArgs( SvIdlDataBase & rBase, + SvTokenStream & rInStm ) +{ + sal_uInt32 nTokPos = rInStm.Tell(); + if( rInStm.ReadIf( '(' ) ) + { + DoReadContextSvIdl( rBase, rInStm ); + if( rInStm.ReadIf( ')' ) ) + { + SetType( MetaTypeType::Method ); + return true; + } + } + rInStm.Seek( nTokPos ); + return false; +} + +SvMetaTypeString::SvMetaTypeString() + : SvMetaType( "String" ) +{ +} + +SvMetaEnumValue::SvMetaEnumValue() +{ +} + +SvMetaTypeEnum::SvMetaTypeEnum() +{ +} + +SvMetaTypevoid::SvMetaTypevoid() + : SvMetaType( "void" ) +{ +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 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: */ diff --git a/idlc/CustomTarget_parser_test.mk b/idlc/CustomTarget_parser_test.mk new file mode 100644 index 000000000..f8c7632bd --- /dev/null +++ b/idlc/CustomTarget_parser_test.mk @@ -0,0 +1,91 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +# +# 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/. +# + +$(eval $(call gb_CustomTarget_CustomTarget,idlc/parser_test)) + +# this target is phony to run it every time +.PHONY : $(call gb_CustomTarget_get_target,idlc/parser_test) + +$(call gb_CustomTarget_get_target,idlc/parser_test) : \ + $(call gb_Executable_get_runtime_dependencies,idlc) \ + $(SRCDIR)/solenv/bin/exectest.pl \ + $(SRCDIR)/idlc/test/parser/attribute.tests \ + $(SRCDIR)/idlc/test/parser/constant.tests \ + $(SRCDIR)/idlc/test/parser/constructor.tests \ + $(SRCDIR)/idlc/test/parser/conversion.tests \ + $(SRCDIR)/idlc/test/parser/interfaceinheritance.tests \ + $(SRCDIR)/idlc/test/parser/methodoverload.tests \ + $(SRCDIR)/idlc/test/parser/polystruct.tests \ + $(SRCDIR)/idlc/test/parser/published.tests \ + $(SRCDIR)/idlc/test/parser/struct.tests \ + $(SRCDIR)/idlc/test/parser/typedef.tests \ + | $(call gb_CustomTarget_get_workdir,idlc/parser_test)/.dir +ifneq ($(gb_SUPPRESS_TESTS),) + @true +else + $(call gb_Helper_abbreviate_dirs,( \ + $(PERL) $(SRCDIR)/solenv/bin/exectest.pl \ + $(SRCDIR)/idlc/test/parser/attribute.tests \ + $(call gb_CustomTarget_get_workdir,idlc/parser_test)/in.idl 0 \ + $(call gb_Executable_get_command,idlc) \ + -O $(call gb_CustomTarget_get_workdir,idlc/parser_test) {} && \ + $(PERL) $(SRCDIR)/solenv/bin/exectest.pl \ + $(SRCDIR)/idlc/test/parser/constant.tests \ + $(call gb_CustomTarget_get_workdir,idlc/parser_test)/in.idl 0 \ + $(call gb_Executable_get_command,idlc) \ + -O $(call gb_CustomTarget_get_workdir,idlc/parser_test) {} && \ + $(PERL) $(SRCDIR)/solenv/bin/exectest.pl \ + $(SRCDIR)/idlc/test/parser/constructor.tests \ + $(call gb_CustomTarget_get_workdir,idlc/parser_test)/in.idl 0 \ + $(call gb_Executable_get_command,idlc) \ + -O $(call gb_CustomTarget_get_workdir,idlc/parser_test) {} && \ + $(PERL) $(SRCDIR)/solenv/bin/exectest.pl \ + $(SRCDIR)/idlc/test/parser/conversion.tests \ + $(call gb_CustomTarget_get_workdir,idlc/parser_test)/in.idl 0 \ + $(call gb_Executable_get_command,idlc) \ + -O $(call gb_CustomTarget_get_workdir,idlc/parser_test) {} && \ + $(PERL) $(SRCDIR)/solenv/bin/exectest.pl \ + $(SRCDIR)/idlc/test/parser/interfaceinheritance.tests \ + $(call gb_CustomTarget_get_workdir,idlc/parser_test)/in.idl 0 \ + $(call gb_Executable_get_command,idlc) \ + -O $(call gb_CustomTarget_get_workdir,idlc/parser_test) {} && \ + $(PERL) $(SRCDIR)/solenv/bin/exectest.pl \ + $(SRCDIR)/idlc/test/parser/methodoverload.tests \ + $(call gb_CustomTarget_get_workdir,idlc/parser_test)/in.idl 0 \ + $(call gb_Executable_get_command,idlc) \ + -O $(call gb_CustomTarget_get_workdir,idlc/parser_test) {} && \ + $(PERL) $(SRCDIR)/solenv/bin/exectest.pl \ + $(SRCDIR)/idlc/test/parser/oldstyle.tests \ + $(call gb_CustomTarget_get_workdir,idlc/parser_test)/in.idl 0 \ + $(call gb_Executable_get_command,idlc) \ + -O $(call gb_CustomTarget_get_workdir,idlc/parser_test) {} && \ + $(PERL) $(SRCDIR)/solenv/bin/exectest.pl \ + $(SRCDIR)/idlc/test/parser/polystruct.tests \ + $(call gb_CustomTarget_get_workdir,idlc/parser_test)/in.idl 0 \ + $(call gb_Executable_get_command,idlc) \ + -O $(call gb_CustomTarget_get_workdir,idlc/parser_test) {} && \ + $(PERL) $(SRCDIR)/solenv/bin/exectest.pl \ + $(SRCDIR)/idlc/test/parser/published.tests \ + $(call gb_CustomTarget_get_workdir,idlc/parser_test)/in.idl 0 \ + $(call gb_Executable_get_command,idlc) \ + -O $(call gb_CustomTarget_get_workdir,idlc/parser_test) {} && \ + $(PERL) $(SRCDIR)/solenv/bin/exectest.pl \ + $(SRCDIR)/idlc/test/parser/struct.tests \ + $(call gb_CustomTarget_get_workdir,idlc/parser_test)/in.idl 0 \ + $(call gb_Executable_get_command,idlc) \ + -O $(call gb_CustomTarget_get_workdir,idlc/parser_test) {} && \ + $(PERL) $(SRCDIR)/solenv/bin/exectest.pl \ + $(SRCDIR)/idlc/test/parser/typedef.tests \ + $(call gb_CustomTarget_get_workdir,idlc/parser_test)/in.idl 0 \ + $(call gb_Executable_get_command,idlc) \ + -O $(call gb_CustomTarget_get_workdir,idlc/parser_test) {}) \ + > $@.log 2>&1 || (cat $@.log && false)) +endif + +# vim: set noet sw=4 ts=4: diff --git a/idlc/Executable_idlc.mk b/idlc/Executable_idlc.mk new file mode 100644 index 000000000..8af0c40f1 --- /dev/null +++ b/idlc/Executable_idlc.mk @@ -0,0 +1,81 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +# +# 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/. +# + +$(eval $(call gb_Executable_Executable,idlc)) + +$(eval $(call gb_Executable_set_include,idlc,\ + -I$(SRCDIR)/idlc/inc \ + -I$(SRCDIR)/idlc/source \ + $$(INCLUDE) \ +)) + +$(eval $(call gb_Executable_use_externals,idlc,\ + boost_headers \ +)) + +$(eval $(call gb_Executable_use_libraries,idlc,\ + reg \ + $(if $(filter TRUE,$(DISABLE_DYNLOADING)),store) \ + sal \ + salhelper \ +)) + +$(eval $(call gb_Executable_add_grammars,idlc,\ + idlc/source/parser \ +)) + +$(eval $(call gb_Executable_add_scanners,idlc,\ + idlc/source/scanner \ +)) + +ifneq (,$(SYSTEM_UCPP)) + +$(eval $(call gb_Executable_add_defs,idlc,\ + -DSYSTEM_UCPP \ + -DUCPP=\"file://$(SYSTEM_UCPP)\" \ +)) + +ifneq ($(SYSTEM_UCPP_IS_GCC),) +$(eval $(call gb_Executable_add_defs,idlc,\ + -DSYSTEM_UCPP_IS_GCC \ +)) +endif + +endif + +$(eval $(call gb_Executable_add_exception_objects,idlc,\ + idlc/source/idlcmain \ + idlc/source/idlc \ + idlc/source/idlccompile \ + idlc/source/idlcproduce \ + idlc/source/errorhandler \ + idlc/source/options \ + idlc/source/fehelper \ + idlc/source/astdeclaration \ + idlc/source/astscope \ + idlc/source/aststack \ + idlc/source/astdump \ + idlc/source/astinterface \ + idlc/source/aststruct \ + idlc/source/aststructinstance \ + idlc/source/astoperation \ + idlc/source/astconstant \ + idlc/source/astenum \ + idlc/source/astexpression \ + idlc/source/astservice \ +)) + +# Without this, e.g. 'make clean; make CustomTarget_idlc/parser_test' may fail on Windows localized +# to something other than listed in Impl_getTextEncodingData, because osl_getThreadTextEncoding() +# returns Windows ACP, calling FullTextEncodingData ctor which loads the not-yet-built library +$(call gb_Executable_add_runtime_dependencies,idlc, \ + $(call gb_CondLibSalTextenc,$(call gb_Library_get_target,sal_textenc)) \ +) + +# vim:set noet sw=4 ts=4: diff --git a/idlc/Makefile b/idlc/Makefile new file mode 100644 index 000000000..0997e6284 --- /dev/null +++ b/idlc/Makefile @@ -0,0 +1,14 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +# +# 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/. +# + +module_directory:=$(dir $(realpath $(firstword $(MAKEFILE_LIST)))) + +include $(module_directory)/../solenv/gbuild/partial_build.mk + +# vim: set noet sw=4 ts=4: diff --git a/idlc/Module_idlc.mk b/idlc/Module_idlc.mk new file mode 100644 index 000000000..a20d105cd --- /dev/null +++ b/idlc/Module_idlc.mk @@ -0,0 +1,25 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +# +# 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/. +# + +$(eval $(call gb_Module_Module,idlc)) + +# if not cross-compiling or we need this for ODK +ifneq (,$(if $(CROSS_COMPILING),,T)$(filter ODK,$(BUILD_TYPE))) + +$(eval $(call gb_Module_add_targets,idlc,\ + Executable_idlc \ +)) + +$(eval $(call gb_Module_add_check_targets,idlc,\ + CustomTarget_parser_test \ +)) + +endif + +# vim:set noet sw=4 ts=4: diff --git a/idlc/README.md b/idlc/README.md new file mode 100644 index 000000000..621a767b3 --- /dev/null +++ b/idlc/README.md @@ -0,0 +1,7 @@ +# UNO IDL Compiler (idlc) + +Contains the UNO IDL compiler: `idlc`, depends on preprocessor: `ucpp` + +This compiler generates binary RDB fragments that can be assembled +into a RDB (UNO type library) with the `regmerge` tool, as is done +primarily in the `offapi` and `udkapi` directories. diff --git a/idlc/inc/astattribute.hxx b/idlc/inc/astattribute.hxx new file mode 100644 index 000000000..b9a799f92 --- /dev/null +++ b/idlc/inc/astattribute.hxx @@ -0,0 +1,107 @@ +/* -*- 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 . + */ +#ifndef INCLUDED_IDLC_INC_ASTATTRIBUTE_HXX +#define INCLUDED_IDLC_INC_ASTATTRIBUTE_HXX + +#include "astdeclaration.hxx" +#include "astscope.hxx" + +#include <registry/types.hxx> +#include <rtl/ustring.hxx> + +namespace typereg { class Writer; } + +class AstAttribute final : public AstDeclaration, public AstScope { +public: + AstAttribute( + sal_uInt32 flags, AstType const * type, OString const & name, + AstScope * scope): + AstDeclaration(NT_attribute, name, scope), + AstScope(NT_attribute), m_flags(flags), m_pType(type) + {} + + AstAttribute(NodeType nodeType, sal_uInt32 flags, AstType const * pType, const OString& name, AstScope* pScope) + : AstDeclaration(nodeType, name, pScope), AstScope(nodeType) + , m_flags(flags) + , m_pType(pType) + {} + + void setExceptions( + OUString const * getDoc, DeclList const * getExc, + OUString const * setDoc, DeclList const * setExc) + { + if (getDoc != nullptr) { + m_getDocumentation = *getDoc; + } + if (getExc != nullptr) { + m_getExceptions = *getExc; + } + if (setDoc != nullptr) { + m_setDocumentation = *setDoc; + } + if (setExc != nullptr) { + m_setExceptions = *setExc; + } + } + + DeclList::size_type getGetExceptionCount() const + { return m_getExceptions.size(); } + + DeclList::size_type getSetExceptionCount() const + { return m_setExceptions.size(); } + + bool isReadonly() const + { return ((m_flags & AF_READONLY) == AF_READONLY); } + bool isOptional() const + { return ((m_flags & AF_OPTIONAL) == AF_OPTIONAL); } + bool isBound() const + { return ((m_flags & AF_BOUND) == AF_BOUND); } + bool isMayBeVoid() const + { return ((m_flags & AF_MAYBEVOID) == AF_MAYBEVOID); } + bool isConstrained() const + { return ((m_flags & AF_CONSTRAINED) == AF_CONSTRAINED); } + bool isTransient() const + { return ((m_flags & AF_TRANSIENT) == AF_TRANSIENT); } + bool isMayBeAmbiguous() const + { return ((m_flags & AF_MAYBEAMBIGUOUS) == AF_MAYBEAMBIGUOUS); } + bool isMayBeDefault() const + { return ((m_flags & AF_MAYBEDEFAULT) == AF_MAYBEDEFAULT); } + bool isRemoveable() const + { return ((m_flags & AF_REMOVABLE) == AF_REMOVABLE); } + + void dumpBlob( + typereg::Writer & rBlob, sal_uInt16 index, sal_uInt16 * methodIndex) const; + +private: + void dumpExceptions( + typereg::Writer & writer, OUString const & documentation, + DeclList const & exceptions, RTMethodMode flags, + sal_uInt16 * methodIndex) const; + + const sal_uInt32 m_flags; + AstType const * m_pType; + OUString m_getDocumentation; + DeclList m_getExceptions; + OUString m_setDocumentation; + DeclList m_setExceptions; +}; + +#endif // INCLUDED_IDLC_INC_ASTATTRIBUTE_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/inc/astbasetype.hxx b/idlc/inc/astbasetype.hxx new file mode 100644 index 000000000..0b488c800 --- /dev/null +++ b/idlc/inc/astbasetype.hxx @@ -0,0 +1,50 @@ +/* -*- 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 . + */ +#pragma once + +#include "asttype.hxx" +#include "astexpression.hxx" + + +class AstBaseType final : public AstType +{ +public: + AstBaseType(const ExprType type, const OString& name, AstScope* pScope) + : AstType(NT_predefined, name, pScope) + , m_exprType(type) + {} + + virtual bool isUnsigned() const override { + switch (m_exprType) { + case ET_ushort: + case ET_ulong: + case ET_uhyper: + return true; + default: + return false; + } + } + + ExprType getExprType() const + { return m_exprType; } +private: + const ExprType m_exprType; +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/inc/astconstant.hxx b/idlc/inc/astconstant.hxx new file mode 100644 index 000000000..fb8b417f4 --- /dev/null +++ b/idlc/inc/astconstant.hxx @@ -0,0 +1,50 @@ +/* -*- 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 . + */ +#ifndef INCLUDED_IDLC_INC_ASTCONSTANT_HXX +#define INCLUDED_IDLC_INC_ASTCONSTANT_HXX + +#include "astdeclaration.hxx" +#include "astexpression.hxx" + +namespace typereg { class Writer; } + +class AstConstant final : public AstDeclaration +{ +public: + AstConstant(const ExprType type, const NodeType nodeType, + AstExpression* pExpr, const OString& name, AstScope* pScope); + AstConstant(const ExprType type, AstExpression* pExpr, + const OString& name, AstScope* pScope); + virtual ~AstConstant() override; + + AstExpression* getConstValue() + { return m_pConstValue; } + ExprType getConstValueType() const + { return m_constValueType; } + + bool dumpBlob( + typereg::Writer & rBlob, sal_uInt16 index, bool published); +private: + AstExpression* m_pConstValue; + const ExprType m_constValueType; +}; + +#endif // INCLUDED_IDLC_INC_ASTCONSTANT_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/inc/astconstants.hxx b/idlc/inc/astconstants.hxx new file mode 100644 index 000000000..6add23a45 --- /dev/null +++ b/idlc/inc/astconstants.hxx @@ -0,0 +1,35 @@ +/* -*- 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 . + */ +#ifndef INCLUDED_IDLC_INC_ASTCONSTANTS_HXX +#define INCLUDED_IDLC_INC_ASTCONSTANTS_HXX + +#include "astmodule.hxx" + +class AstConstants final : public AstModule +{ +public: + AstConstants(const OString& name, AstScope* pScope) + : AstModule(NT_constants, name, pScope) + { + } +}; + +#endif // INCLUDED_IDLC_INC_ASTCONSTANTS_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/inc/astdeclaration.hxx b/idlc/inc/astdeclaration.hxx new file mode 100644 index 000000000..0707dbc57 --- /dev/null +++ b/idlc/inc/astdeclaration.hxx @@ -0,0 +1,136 @@ +/* -*- 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 . + */ +#ifndef INCLUDED_IDLC_INC_ASTDECLARATION_HXX +#define INCLUDED_IDLC_INC_ASTDECLARATION_HXX + +#include "idlc.hxx" +#include <registry/registry.hxx> + +class AstScope; + +// Enum defining the different kinds of Ast nodes +enum NodeType +{ + NT_service, // Denotes a service + NT_interface_member, // Denotes an interface which is exported from object + NT_service_member, // Denotes a service which is exported from object + NT_observes, // Denotes an observed interface + NT_needs, // Denotes a needed service + NT_module, // Denotes a module + NT_root, // Denotes the root of AST + NT_interface, // Denotes an interface + NT_constants, // Denotes a constant group + NT_const, // Denotes a constant + NT_exception, // Denotes an exception + NT_attribute, // Denotes an attribute + NT_property, // Denotes a property + NT_operation, // Denotes an operation + NT_parameter, // Denotes an op. parameter + NT_struct, // Denotes either a plain struct type, or a + // polymorphic struct type template + NT_type_parameter, // Denotes a type parameter of a polymorphic struct + // type template + NT_instantiated_struct, // Denotes an instantiated polymorphic struct type + NT_member, // Denotes a member in structure, exception + NT_enum, // Denotes an enumeration + NT_enum_val, // Denotes an enum. value + NT_sequence, // Denotes an IDL sequence + NT_typedef, // Denotes a typedef + NT_predefined, // Denotes a predefined type + NT_singleton // Denotes a singleton +}; + +class AstDeclaration +{ +public: + // Constructors + AstDeclaration(NodeType type, const OString& name, AstScope* pScope); + virtual ~AstDeclaration(); + + AstDeclaration(AstDeclaration const &) = default; + AstDeclaration(AstDeclaration &&) = default; + AstDeclaration & operator =(AstDeclaration const &) = default; + AstDeclaration & operator =(AstDeclaration &&) = default; + + // Data access + const OString& getLocalName() const + { return m_localName; } + const OString& getScopedName() const + { return m_scopedName; } + const OString& getFullName() const + { return m_fullName; } + virtual const char* getRelativName() const + { return m_fullName.getStr()+1; } + AstScope* getScope() + { return m_pScope; } + const AstScope* getScope() const + { return m_pScope; } + NodeType getNodeType() const + { return m_nodeType; } + bool isInMainfile() const + { return m_bInMainFile; } + void setInMainfile(bool bInMainfile) + { m_bInMainFile = bInMainfile; } + bool isImported() const + { return m_bImported; } + void setImported(bool bImported) + { m_bImported = bImported; } + sal_Int32 getLineNumber() const + { return m_lineNumber; } + void setLineNumber(sal_Int32 lineNumber) + { m_lineNumber = lineNumber; } + const OString& getFileName() const + { return m_fileName; } + void setFileName(const OString& rFileName) + { m_fileName = rFileName; } + const OUString& getDocumentation() const + { return m_documentation; } + void setDocumentation(const OUString& rDocumentation) + { m_documentation = rDocumentation; } + + virtual bool isType() const; + + bool hasAncestor(AstDeclaration* pDecl); + + void setPublished() { m_bPublished = true; } + bool isPublished() const { return m_bPublished; } + + virtual bool dump(RegistryKey& rKey); + + bool isPredefined() const { return m_bPredefined; } + void setPredefined(bool bPredefined); + +protected: + OString m_localName; + OString m_scopedName; // full qualified name + OString m_fullName; // full qualified name with '/' as separator + AstScope* m_pScope; + NodeType m_nodeType; + bool m_bImported; // imported ? + bool m_bInMainFile; // defined in main file + bool m_bPublished; + bool m_bPredefined; + sal_Int32 m_lineNumber; // line number defined in + OString m_fileName; // fileName defined in + OUString m_documentation; // fileName defined in +}; + +#endif // INCLUDED_IDLC_INC_ASTDECLARATION_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/inc/astenum.hxx b/idlc/inc/astenum.hxx new file mode 100644 index 000000000..dc89d430a --- /dev/null +++ b/idlc/inc/astenum.hxx @@ -0,0 +1,45 @@ +/* -*- 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 . + */ +#ifndef INCLUDED_IDLC_INC_ASTENUM_HXX +#define INCLUDED_IDLC_INC_ASTENUM_HXX + +#include "asttype.hxx" +#include "astscope.hxx" +#include "astconstant.hxx" + +class AstEnum final : public AstType, public AstScope +{ +public: + AstEnum(const OString& name, AstScope* pScope); + + virtual ~AstEnum() override; + + sal_Int32 getEnumValueCount() { return m_enumValueCount++; } + + AstConstant* checkValue(AstExpression* pExpr); + + virtual bool dump(RegistryKey& rKey) override; + +private: + sal_Int32 m_enumValueCount; +}; + +#endif // INCLUDED_IDLC_INC_ASTENUM_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/inc/astexception.hxx b/idlc/inc/astexception.hxx new file mode 100644 index 000000000..6c2d549bc --- /dev/null +++ b/idlc/inc/astexception.hxx @@ -0,0 +1,35 @@ +/* -*- 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 . + */ +#ifndef INCLUDED_IDLC_INC_ASTEXCEPTION_HXX +#define INCLUDED_IDLC_INC_ASTEXCEPTION_HXX + +#include "aststruct.hxx" + +class AstException final : public AstStruct +{ +public: + AstException(const OString& name, AstException const* pBaseType, AstScope* pScope) + : AstStruct(NT_exception, name, pBaseType, pScope) + { + } +}; + +#endif // INCLUDED_IDLC_INC_ASTEXCEPTION_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/inc/astexpression.hxx b/idlc/inc/astexpression.hxx new file mode 100644 index 000000000..05d20baa5 --- /dev/null +++ b/idlc/inc/astexpression.hxx @@ -0,0 +1,139 @@ +/* -*- 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 . + */ +#ifndef INCLUDED_IDLC_INC_ASTEXPRESSION_HXX +#define INCLUDED_IDLC_INC_ASTEXPRESSION_HXX + +#include <sal/config.h> + +#include <memory> + +#include "idlc.hxx" +#include <optional> + +// Enum to define all the different operators to combine expressions +enum class ExprComb +{ + Add, // '+' + Minus, // '-' + Mul, // '*' + Div, // '/' + Mod, // '%' + Or, // '|' + Xor, // '^' + And, // '&' + Left, // '<<' + Right, // '>>' + UPlus, // unary '+' + UMinus, // unary '-' + NONE, // No operator (missing) + Symbol // a symbol (function or constant name) +}; + +// Enum to define expression type +enum ExprType +{ + ET_short, // Expression value is short + ET_ushort, // Expression value is unsigned short + ET_long, // Expression value is long + ET_ulong, // Expression value is unsigned long + ET_hyper, // Expression value is hyper (64 bit) + ET_uhyper, // Expression value is unsigned hyper + ET_float, // Expression value is 32-bit float + ET_double, // Expression value is 64-bit float + ET_char, // Expression value is char + ET_byte, // Expression value is byte + ET_boolean, // Expression value is boolean + ET_string, // Expression value is char * + ET_any, // Expression value is any of above + ET_void, // Expression value is void (absent) + ET_type, // Expression value is type + ET_none // Expression value is missing +}; + +// Structure to describe value of constant expression and its type +struct AstExprValue +{ + union + { + sal_uInt8 byval; // Contains byte expression value + sal_Int16 sval; // Contains short expression value + sal_uInt16 usval; // Contains unsigned short expr value + sal_Int32 lval; // Contains long expression value + sal_uInt32 ulval; // Contains unsigned long expr value + sal_Int64 hval; // Contains hyper expression value + sal_uInt64 uhval; // Contains unsigned hyper expr value + bool bval; // Contains boolean expression value + float fval; // Contains 32-bit float expr value + double dval; // Contains 64-bit float expr value + } u; + ExprType et; +}; + +const char* exprTypeToString(ExprType t); + +class AstExpression final +{ +public: + // Constructor(s) + AstExpression(ExprComb c, AstExpression *pExpr1, AstExpression *pExpr2); + + AstExpression(sal_Int32 l); + AstExpression(sal_Int32 l, ExprType et); + AstExpression(sal_Int64 h); + AstExpression(sal_uInt64 uh); + AstExpression(double d); + AstExpression(OString* scopedName); + + ~AstExpression(); + + // Data Accessors + AstExprValue* getExprValue() + { return m_exprValue.get(); } + + // Evaluation and value coercion + bool coerce(ExprType type); + + // Evaluate then store value inside this AstExpression + void evaluate(); + + // Compare LONG AstExpression values + bool compareLong(AstExpression *pExpr); + + OString toString(); +private: + // Evaluate different sets of operators + std::unique_ptr<AstExprValue> eval_bin_op(); + std::unique_ptr<AstExprValue> eval_bit_op(); + std::unique_ptr<AstExprValue> eval_un_op(); + std::unique_ptr<AstExprValue> eval_symbol(); + + ExprComb m_combOperator; + std::unique_ptr<AstExpression> + m_subExpr1; + std::unique_ptr<AstExpression> + m_subExpr2; + std::unique_ptr<AstExprValue> + m_exprValue; + std::optional<OString> + m_xSymbolicName; +}; + +#endif // INCLUDED_IDLC_INC_ASTEXPRESSION_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/inc/astinterface.hxx b/idlc/inc/astinterface.hxx new file mode 100644 index 000000000..03c5f22f5 --- /dev/null +++ b/idlc/inc/astinterface.hxx @@ -0,0 +1,129 @@ +/* -*- 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 . + */ +#ifndef INCLUDED_IDLC_INC_ASTINTERFACE_HXX +#define INCLUDED_IDLC_INC_ASTINTERFACE_HXX + +#include "asttype.hxx" +#include "astscope.hxx" +#include "inheritedinterface.hxx" + +#include <map> +#include <vector> + +class AstInterface : public AstType + , public AstScope +{ +public: + typedef std::vector< InheritedInterface > InheritedInterfaces; + + struct DoubleMemberDeclaration { + AstDeclaration const * first; + AstDeclaration const * second; + }; + + typedef std::vector< DoubleMemberDeclaration > DoubleMemberDeclarations; + + struct DoubleDeclarations { + std::vector< AstInterface const * > interfaces; + DoubleMemberDeclarations members; + }; + + AstInterface( + const OString& name, AstInterface const * pInherits, + AstScope* pScope); + virtual ~AstInterface() override; + + AstInterface(AstInterface const &) = default; + AstInterface(AstInterface &&) = default; + AstInterface & operator =(AstInterface const &) = default; + AstInterface & operator =(AstInterface &&) = default; + + InheritedInterfaces const & getAllInheritedInterfaces() const + { return m_inheritedInterfaces; } + + bool hasMandatoryInheritedInterfaces() const + { return m_mandatoryInterfaces > 0; } + + void setDefined() { m_bIsDefined = true; } + bool isDefined() const + { return m_bIsDefined; } + + bool usesSingleInheritance() const { return m_bSingleInheritance; } + + DoubleDeclarations checkInheritedInterfaceClashes( + AstInterface const * ifc, bool optional) const; + + void addInheritedInterface( + AstType const * ifc, bool optional, + OUString const & documentation); + + DoubleMemberDeclarations checkMemberClashes( + AstDeclaration const * member) const; + + void addMember(AstDeclaration /*TODO: const*/ * member); + + void forwardDefined(AstInterface const & def); + + virtual bool dump(RegistryKey& rKey) override; + +private: + enum InterfaceKind { + INTERFACE_INDIRECT_OPTIONAL, INTERFACE_DIRECT_OPTIONAL, + INTERFACE_INDIRECT_MANDATORY, INTERFACE_DIRECT_MANDATORY }; + + struct VisibleMember { + explicit VisibleMember(AstDeclaration const * theMandatory = nullptr): + mandatory(theMandatory) {} + + typedef std::map< OString, AstDeclaration const * > Optionals; + + AstDeclaration const * mandatory; + Optionals optionals; + }; + + typedef std::map< OString, InterfaceKind > VisibleInterfaces; + typedef std::map< OString, VisibleMember > VisibleMembers; + + void checkInheritedInterfaceClashes( + DoubleDeclarations & doubleDeclarations, + std::set< OString > & seenInterfaces, AstInterface const * ifc, + bool direct, bool optional, bool mainOptional) const; + + void checkMemberClashes( + DoubleMemberDeclarations & doubleMembers, AstDeclaration const * member, + bool checkOptional) const; + + void addVisibleInterface( + AstInterface const * ifc, bool direct, bool optional); + + void addOptionalVisibleMembers(AstInterface const * ifc); + + bool increment(sal_uInt16 * counter, char const * sort) const; + + InheritedInterfaces m_inheritedInterfaces; + InheritedInterfaces::size_type m_mandatoryInterfaces; + bool m_bIsDefined; + bool m_bSingleInheritance; + VisibleInterfaces m_visibleInterfaces; + VisibleMembers m_visibleMembers; +}; + +#endif // INCLUDED_IDLC_INC_ASTINTERFACE_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/inc/astinterfacemember.hxx b/idlc/inc/astinterfacemember.hxx new file mode 100644 index 000000000..0e290e187 --- /dev/null +++ b/idlc/inc/astinterfacemember.hxx @@ -0,0 +1,45 @@ +/* -*- 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 . + */ +#ifndef INCLUDED_IDLC_INC_ASTINTERFACEMEMBER_HXX +#define INCLUDED_IDLC_INC_ASTINTERFACEMEMBER_HXX + +#include "astinterface.hxx" + +class AstInterfaceMember final : public AstDeclaration +{ +public: + AstInterfaceMember(const sal_uInt32 flags, AstInterface* pRealInterface, + const OString& name, AstScope* pScope) + : AstDeclaration(NT_interface_member, name, pScope) + , m_flags(flags) + , m_pRealInterface(pRealInterface) + {} + + AstInterface* getRealInterface() + { return m_pRealInterface; } + bool isOptional() const + { return ((m_flags & AF_OPTIONAL) == AF_OPTIONAL); } +private: + const sal_uInt32 m_flags; + AstInterface* m_pRealInterface; +}; + +#endif // INCLUDED_IDLC_INC_ASTINTERFACEMEMBER_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/inc/astmember.hxx b/idlc/inc/astmember.hxx new file mode 100644 index 000000000..43597d125 --- /dev/null +++ b/idlc/inc/astmember.hxx @@ -0,0 +1,48 @@ +/* -*- 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 . + */ + +#ifndef INCLUDED_IDLC_INC_ASTMEMBER_HXX +#define INCLUDED_IDLC_INC_ASTMEMBER_HXX + +#include "astdeclaration.hxx" + +class AstScope; +class AstType; + +class AstMember: public AstDeclaration { +public: + AstMember( + AstType const * pType, OString const & name, AstScope * pScope): + AstDeclaration(NT_member, name, pScope), m_pType(pType) {} + + AstType const * getType() const { return m_pType; } + +protected: + AstMember( + NodeType type, AstType const * pType, OString const & name, + AstScope * pScope): + AstDeclaration(type, name, pScope), m_pType(pType) {} + +private: + AstType const * m_pType; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/inc/astmodule.hxx b/idlc/inc/astmodule.hxx new file mode 100644 index 000000000..6178cfbb6 --- /dev/null +++ b/idlc/inc/astmodule.hxx @@ -0,0 +1,44 @@ +/* -*- 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 . + */ +#ifndef INCLUDED_IDLC_INC_ASTMODULE_HXX +#define INCLUDED_IDLC_INC_ASTMODULE_HXX + +#include "astdeclaration.hxx" +#include "astscope.hxx" + +class AstModule : public AstDeclaration, public AstScope +{ +public: + AstModule(const OString& name, AstScope* pScope) + : AstDeclaration(NT_module, name, pScope) + , AstScope(NT_module) + { + } + AstModule(NodeType type, const OString& name, AstScope* pScope) + : AstDeclaration(type, name, pScope) + , AstScope(type) + { + } + + virtual bool dump(RegistryKey& rKey) override; +}; + +#endif // INCLUDED_IDLC_INC_ASTMODULE_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/inc/astneeds.hxx b/idlc/inc/astneeds.hxx new file mode 100644 index 000000000..13d2dbbef --- /dev/null +++ b/idlc/inc/astneeds.hxx @@ -0,0 +1,41 @@ +/* -*- 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 . + */ +#ifndef INCLUDED_IDLC_INC_ASTNEEDS_HXX +#define INCLUDED_IDLC_INC_ASTNEEDS_HXX + +#include "astservice.hxx" + +class AstNeeds final : public AstDeclaration +{ +public: + AstNeeds(AstService* pRealService, const OString& name, AstScope* pScope) + : AstDeclaration(NT_needs, name, pScope) + , m_pRealService(pRealService) + { + } + + AstService* getRealService() { return m_pRealService; } + +private: + AstService* m_pRealService; +}; + +#endif // INCLUDED_IDLC_INC_ASTNEEDS_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/inc/astobserves.hxx b/idlc/inc/astobserves.hxx new file mode 100644 index 000000000..11bb5a677 --- /dev/null +++ b/idlc/inc/astobserves.hxx @@ -0,0 +1,41 @@ +/* -*- 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 . + */ +#ifndef INCLUDED_IDLC_INC_ASTOBSERVES_HXX +#define INCLUDED_IDLC_INC_ASTOBSERVES_HXX + +#include "astinterface.hxx" + +class AstObserves final : public AstDeclaration +{ +public: + AstObserves(AstInterface* pRealInterface, const OString& name, AstScope* pScope) + : AstDeclaration(NT_observes, name, pScope) + , m_pRealInterface(pRealInterface) + { + } + + AstInterface* getRealInterface() { return m_pRealInterface; } + +private: + AstInterface* m_pRealInterface; +}; + +#endif // INCLUDED_IDLC_INC_ASTOBSERVES_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/inc/astoperation.hxx b/idlc/inc/astoperation.hxx new file mode 100644 index 000000000..e3e0335c9 --- /dev/null +++ b/idlc/inc/astoperation.hxx @@ -0,0 +1,54 @@ +/* -*- 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 . + */ +#ifndef INCLUDED_IDLC_INC_ASTOPERATION_HXX +#define INCLUDED_IDLC_INC_ASTOPERATION_HXX + +#include "astdeclaration.hxx" +#include "astscope.hxx" + +namespace typereg { class Writer; } + +class AstType; + +class AstOperation final : public AstDeclaration + , public AstScope +{ +public: + AstOperation(AstType const * pReturnType, const OString& name, AstScope* pScope) + : AstDeclaration(NT_operation, name, pScope) + , AstScope(NT_operation) + , m_pReturnType(pReturnType) + {} + + bool isVariadic() const; + + bool isConstructor() const { return m_pReturnType == nullptr; } + + void setExceptions(DeclList const * pExceptions); + + void dumpBlob(typereg::Writer & rBlob, sal_uInt16 index); + +private: + AstType const * m_pReturnType; + DeclList m_exceptions; +}; + +#endif // INCLUDED_IDLC_INC_ASTOPERATION_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/inc/astparameter.hxx b/idlc/inc/astparameter.hxx new file mode 100644 index 000000000..cfee34260 --- /dev/null +++ b/idlc/inc/astparameter.hxx @@ -0,0 +1,46 @@ +/* -*- 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 . + */ + +#ifndef INCLUDED_IDLC_INC_ASTPARAMETER_HXX +#define INCLUDED_IDLC_INC_ASTPARAMETER_HXX + +#include "astmember.hxx" + +enum Direction { DIR_IN, DIR_OUT, DIR_INOUT }; + +class AstParameter final : public AstMember { +public: + AstParameter( + Direction direction, bool rest, AstType const * type, + OString const & name, AstScope * scope): + AstMember(NT_parameter, type, name, scope), m_direction(direction), + m_rest(rest) {} + + Direction getDirection() const { return m_direction; } + + bool isRest() const { return m_rest; } + +private: + Direction m_direction; + bool m_rest; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/inc/astscope.hxx b/idlc/inc/astscope.hxx new file mode 100644 index 000000000..be7b03828 --- /dev/null +++ b/idlc/inc/astscope.hxx @@ -0,0 +1,73 @@ +/* -*- 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 . + */ +#ifndef INCLUDED_IDLC_INC_ASTSCOPE_HXX +#define INCLUDED_IDLC_INC_ASTSCOPE_HXX + +#include <sal/config.h> + +#include <string_view> +#include "idlc.hxx" +#include "astdeclaration.hxx" +#include "astexpression.hxx" + +class AstExpression; + +class AstScope +{ +public: + AstScope(NodeType nodeType); + virtual ~AstScope(); + + AstScope(AstScope const&) = default; + AstScope(AstScope&&) = default; + AstScope& operator=(AstScope const&) = default; + AstScope& operator=(AstScope&&) = default; + + NodeType getScopeNodeType() const { return m_nodeType; } + + AstDeclaration* addDeclaration(AstDeclaration* pDecl); + + sal_uInt32 nMembers() const { return static_cast<sal_uInt32>(m_declarations.size()); } + DeclList::const_iterator getIteratorBegin() const { return m_declarations.begin(); } + DeclList::const_iterator getIteratorEnd() const { return m_declarations.end(); } + sal_uInt16 getNodeCount(NodeType nType) const; + + // Name look up mechanism + AstDeclaration* lookupByName(const OString& scopedName); + // Look up the identifier 'name' specified only in the local scope + AstDeclaration* lookupByNameLocal(std::string_view name) const; + + AstDeclaration* lookupInInherited(const OString& scopedName) const; + + // Look up a predefined type by its ExprType + AstDeclaration* lookupPrimitiveType(ExprType type); + + AstDeclaration* lookupForAdd(AstDeclaration const* pDecl) const; + +protected: + AstDeclaration const* getLast() const { return m_declarations.back(); } + +private: + DeclList m_declarations; + NodeType m_nodeType; +}; + +#endif // INCLUDED_IDLC_INC_ASTSCOPE_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/inc/astsequence.hxx b/idlc/inc/astsequence.hxx new file mode 100644 index 000000000..e8a2850e2 --- /dev/null +++ b/idlc/inc/astsequence.hxx @@ -0,0 +1,49 @@ +/* -*- 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 . + */ +#ifndef INCLUDED_IDLC_INC_ASTSEQUENCE_HXX +#define INCLUDED_IDLC_INC_ASTSEQUENCE_HXX + +#include "asttype.hxx" + +class AstSequence final : public AstType +{ +public: + AstSequence(AstType const* pMemberType, AstScope* pScope) + : AstType(NT_sequence, OString::Concat("[]") + pMemberType->getScopedName(), pScope) + , m_pMemberType(pMemberType) + { + } + + AstType const* getMemberType() const { return m_pMemberType; } + + virtual bool isUnsigned() const override + { + return m_pMemberType != nullptr && m_pMemberType->isUnsigned(); + } + + virtual const char* getRelativName() const override; + +private: + AstType const* m_pMemberType; + mutable std::optional<OString> m_xRelativName; +}; + +#endif // INCLUDED_IDLC_INC_ASTSEQUENCE_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/inc/astservice.hxx b/idlc/inc/astservice.hxx new file mode 100644 index 000000000..4ad769cd5 --- /dev/null +++ b/idlc/inc/astservice.hxx @@ -0,0 +1,61 @@ +/* -*- 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 . + */ +#ifndef INCLUDED_IDLC_INC_ASTSERVICE_HXX +#define INCLUDED_IDLC_INC_ASTSERVICE_HXX + +#include "astdeclaration.hxx" +#include "astscope.hxx" + +class AstService final : public AstDeclaration + , public AstScope +{ +public: + AstService(const OString& name, AstScope* pScope) + : AstDeclaration(NT_service, name, pScope) + , AstScope(NT_service) + , m_singleInterfaceBasedService(false) + , m_defaultConstructor(false) + {} + AstService(const NodeType type, const OString& name, AstScope* pScope) + : AstDeclaration(type, name, pScope) + , AstScope(type) + , m_singleInterfaceBasedService(false) + , m_defaultConstructor(false) + {} + + virtual bool dump(RegistryKey& rKey) override; + + void setSingleInterfaceBasedService() + { m_singleInterfaceBasedService = true; } + + void setDefaultConstructor(bool b) { m_defaultConstructor = b; } + + bool isSingleInterfaceBasedService() const + { return m_singleInterfaceBasedService; } + + bool checkLastConstructor() const; + +private: + bool m_singleInterfaceBasedService; + bool m_defaultConstructor; +}; + +#endif // INCLUDED_IDLC_INC_ASTSERVICE_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/inc/astservicemember.hxx b/idlc/inc/astservicemember.hxx new file mode 100644 index 000000000..380449b25 --- /dev/null +++ b/idlc/inc/astservicemember.hxx @@ -0,0 +1,45 @@ +/* -*- 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 . + */ +#ifndef INCLUDED_IDLC_INC_ASTSERVICEMEMBER_HXX +#define INCLUDED_IDLC_INC_ASTSERVICEMEMBER_HXX + +#include "astservice.hxx" + +class AstServiceMember final : public AstDeclaration +{ +public: + AstServiceMember(const sal_uInt32 flags, AstService* pRealService, + const OString& name, AstScope* pScope) + : AstDeclaration(NT_service_member, name, pScope) + , m_flags(flags) + , m_pRealService(pRealService) + {} + + AstService* getRealService() + { return m_pRealService; } + bool isOptional() const + { return ((m_flags & AF_OPTIONAL) == AF_OPTIONAL); } +private: + const sal_uInt32 m_flags; + AstService* m_pRealService; +}; + +#endif // INCLUDED_IDLC_INC_ASTSERVICEMEMBER_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/inc/aststack.hxx b/idlc/inc/aststack.hxx new file mode 100644 index 000000000..d36bd4e48 --- /dev/null +++ b/idlc/inc/aststack.hxx @@ -0,0 +1,46 @@ +/* -*- 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 . + */ + +#pragma once + +#include <sal/types.h> +#include <vector> + +class AstScope; + +class AstStack final +{ +public: + AstStack(); + ~AstStack(); + + sal_uInt32 depth() const { return m_stack.size(); } + AstScope* top(); + AstScope* bottom(); + AstScope* nextToTop(); + AstScope* topNonNull(); + AstStack* push(AstScope* pScope); + void pop(); + void clear(); + +private: + std::vector<AstScope*> m_stack; +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/inc/aststruct.hxx b/idlc/inc/aststruct.hxx new file mode 100644 index 000000000..5e037d1b5 --- /dev/null +++ b/idlc/inc/aststruct.hxx @@ -0,0 +1,62 @@ +/* -*- 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 . + */ +#ifndef INCLUDED_IDLC_INC_ASTSTRUCT_HXX +#define INCLUDED_IDLC_INC_ASTSTRUCT_HXX + +#include <sal/config.h> + +#include <string_view> + +#include "asttype.hxx" +#include "astscope.hxx" +#include "idlctypes.hxx" + +class AstStruct; + +class AstStruct : public AstType + , public AstScope +{ +public: + AstStruct( + const OString& name, + std::vector< OString > const & typeParameters, + AstStruct const* pBaseType, AstScope* pScope); + + AstStruct(const NodeType type, + const OString& name, + AstStruct const* pBaseType, + AstScope* pScope); + virtual ~AstStruct() override; + + std::size_t getTypeParameterCount() const + { return m_typeParameters.size(); } + + AstDeclaration const * findTypeParameter(std::string_view name) const; + + virtual bool isType() const override; + + virtual bool dump(RegistryKey& rKey) override; +private: + AstStruct const* m_pBaseType; + std::vector<std::unique_ptr<AstDeclaration>> m_typeParameters; +}; + +#endif // INCLUDED_IDLC_INC_ASTSTRUCT_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/inc/aststructinstance.hxx b/idlc/inc/aststructinstance.hxx new file mode 100644 index 000000000..1357aa351 --- /dev/null +++ b/idlc/inc/aststructinstance.hxx @@ -0,0 +1,49 @@ +/* -*- 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 . + */ + +#ifndef INCLUDED_IDLC_INC_ASTSTRUCTINSTANCE_HXX +#define INCLUDED_IDLC_INC_ASTSTRUCTINSTANCE_HXX + +#include "asttype.hxx" +#include "idlctypes.hxx" + +class AstScope; + +class AstStructInstance final : public AstType { +public: + AstStructInstance( + AstType const * typeTemplate, DeclList const * typeArguments, + AstScope * scope); + + AstType const * getTypeTemplate() const { return m_typeTemplate; } + + DeclList::const_iterator getTypeArgumentsBegin() const + { return m_typeArguments.begin(); } + + DeclList::const_iterator getTypeArgumentsEnd() const + { return m_typeArguments.end(); } + +private: + AstType const * m_typeTemplate; + DeclList m_typeArguments; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/inc/asttype.hxx b/idlc/inc/asttype.hxx new file mode 100644 index 000000000..8627429cd --- /dev/null +++ b/idlc/inc/asttype.hxx @@ -0,0 +1,37 @@ +/* -*- 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 . + */ +#ifndef INCLUDED_IDLC_INC_ASTTYPE_HXX +#define INCLUDED_IDLC_INC_ASTTYPE_HXX + +#include "astdeclaration.hxx" + +class AstType : public AstDeclaration +{ +public: + AstType(const NodeType type, const OString& name, AstScope* pScope) + : AstDeclaration(type, name, pScope) + { + } + + virtual bool isUnsigned() const { return false; } +}; + +#endif // INCLUDED_IDLC_INC_ASTTYPE_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/inc/asttypedef.hxx b/idlc/inc/asttypedef.hxx new file mode 100644 index 000000000..427d63307 --- /dev/null +++ b/idlc/inc/asttypedef.hxx @@ -0,0 +1,44 @@ +/* -*- 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 . + */ +#ifndef INCLUDED_IDLC_INC_ASTTYPEDEF_HXX +#define INCLUDED_IDLC_INC_ASTTYPEDEF_HXX + +#include "asttype.hxx" + +class AstTypeDef final : public AstType +{ +public: + AstTypeDef( + AstType const * baseType, OString const & name, AstScope * scope): + AstType(NT_typedef, name, scope), m_pBaseType(baseType) {} + + AstType const * getBaseType() const + { return m_pBaseType; } + + virtual bool isUnsigned() const override + { return m_pBaseType != nullptr && m_pBaseType->isUnsigned(); } + + virtual bool dump(RegistryKey& rKey) override; +private: + AstType const * m_pBaseType; +}; + +#endif // INCLUDED_IDLC_INC_ASTTYPEDEF_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/inc/errorhandler.hxx b/idlc/inc/errorhandler.hxx new file mode 100644 index 000000000..9b49f5df4 --- /dev/null +++ b/idlc/inc/errorhandler.hxx @@ -0,0 +1,118 @@ +/* -*- 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 . + */ +#ifndef INCLUDED_IDLC_INC_ERRORHANDLER_HXX +#define INCLUDED_IDLC_INC_ERRORHANDLER_HXX + +#include "astdeclaration.hxx" +#include "astexpression.hxx" +#include "astenum.hxx" + +enum class ErrorCode +{ + SyntaxError, // Syntax error in IDL input + // More details will be gleaned from examining + // the parse state + RedefScope, // Redefinition inside defining scope + CoercionFailure, // Coercion failure + ScopeConflict, // Between fwd declare and full declare + IllegalAdd, // Illegal add action + IllegalRaises, // Error in "raises" clause + CantInherit, // Cannot inherit from non-interface + IdentNotFound, // Identifier not found + CannotInheritFromForward, // Cannot inherit from fwd decl interface + ExpectedConstant, // We got something else... + Eval, // Error in evaluating expression + ForwardDeclLookup, // Tried to lookup in fwd declared intf + RecursiveType, // Illegal recursive use of type + NotAType, // Not a type + InterfaceMemberLookup, // interface is not defined or a fwd declaration not exists + ServiceMemberLookup, + DefinedAttributeFlag, + WrongAttributeKeyword, + MissingAttributeKeyword, + BadAttributeFlags, + ExpectedOptional, + MixedInheritance, + DoubleInheritance, + DoubleMember, + ConstructorParameterNotIn, + ConstructorRestParameterNotFirst, + RestParameterNotLast, + RestParameterNotAny, + MethodHasRestParameter, + ReadOnlyAttributeSetExceptions, + UnsignedTypeArgument, + WrongNumberOfTypeArguments, + InstantiatedStructTypeTypedef, + IdenticalTypeParameters, + StructTypeTemplateWithBase, + PublishedForward, + PublishedusesUnpublished, + SimilarConstructors +}; + +enum class WarningCode +{ + WrongNamingConvention // type or identifier doesn't fulfill the UNO naming convention +}; + +class ErrorHandler +{ +public: + // Report errors with varying numbers of arguments + static void error0(ErrorCode e); + static void error1(ErrorCode e, AstDeclaration const * d); + static void error2( + ErrorCode e, AstDeclaration const * d1, AstDeclaration const * d2); + static void error3(ErrorCode e, AstDeclaration const * d1, AstDeclaration const * d2, AstDeclaration const * d3); + + // Warning + static void warning0(WarningCode e, const char* warningmsg); + + // Report a syntax error in IDL input + static void syntaxError(ParseState state, sal_Int32 lineNumber, const char* errmsg); + + // Report an unsuccessful coercion attempt + static void coercionError(AstExpression *pExpr, ExprType et); + + // Report a failed name lookup attempt + static void lookupError(const OString& n); + // Report a failed name lookup attempt + static void lookupError(ErrorCode e, const OString& n, AstDeclaration const * pScope); + + + // Report a type error + static void noTypeError(AstDeclaration const * pDecl); + + static void inheritanceError(NodeType nodeType, const OString* name, AstDeclaration const * pDecl); + + static void flagError(ErrorCode e, sal_uInt32 flag); + + static void forwardLookupError(const AstDeclaration* pForward, const OString& name); + + static void constantExpected(AstDeclaration const * pDecl, const OString& name); + + static void evalError(AstExpression* pExpr); + + static bool checkPublished(AstDeclaration const * decl, bool bOptional=false); +}; + +#endif // INCLUDED_IDLC_INC_ERRORHANDLER_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/inc/fehelper.hxx b/idlc/inc/fehelper.hxx new file mode 100644 index 000000000..be401defc --- /dev/null +++ b/idlc/inc/fehelper.hxx @@ -0,0 +1,70 @@ +/* -*- 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 . + */ +#ifndef INCLUDED_IDLC_INC_FEHELPER_HXX +#define INCLUDED_IDLC_INC_FEHELPER_HXX + +#include "asttype.hxx" +#include "astinterface.hxx" + +#include <vector> + +class FeDeclarator final +{ +public: + FeDeclarator(const OString& name); + ~FeDeclarator(); + const OString& getName() const + { return m_name; } + bool checkType(AstDeclaration const * pType) const; + static AstType const * compose(AstDeclaration const * pDecl); +private: + OString m_name; +}; + +typedef ::std::list< FeDeclarator* > FeDeclList; + +class FeInheritanceHeader final +{ +public: + FeInheritanceHeader( + NodeType nodeType, OString* pName, OString const * pInherits, + std::vector< OString > const * typeParameters); + + NodeType getNodeType() const + { return m_nodeType; } + OString* getName() + { return m_pName.get(); } + AstDeclaration* getInherits() + { return m_pInherits; } + + std::vector< OString > const & getTypeParameters() const + { return m_typeParameters; } + +private: + void initializeInherits(OString const * pinherits); + + NodeType m_nodeType; + std::unique_ptr<OString> m_pName; + AstDeclaration* m_pInherits; + std::vector< OString > m_typeParameters; +}; + +#endif // INCLUDED_IDLC_INC_FEHELPER_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/inc/idlc.hxx b/idlc/inc/idlc.hxx new file mode 100644 index 000000000..1be11b145 --- /dev/null +++ b/idlc/inc/idlc.hxx @@ -0,0 +1,164 @@ +/* -*- 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 . + */ +#pragma once + +#include "idlctypes.hxx" +#include "aststack.hxx" +#include "options.hxx" +#include <memory> +#include <string_view> + +#ifdef SAL_UNX +#define SEPARATOR '/' +#define PATH_SEPARATOR "/" +#else +#define SEPARATOR '\\' +#define PATH_SEPARATOR "\\" +#endif + +class AstInterface; +class AstModule; +class AstType; +class Options; +class ErrorHandler; + +class Idlc final +{ +public: + Idlc(Options* pOptions); + ~Idlc(); + + void init(); + + bool dumpDeps(std::string_view rDepFile, + OString const& rTarget); + + Options* getOptions() + { return m_pOptions; } + AstStack* scopes() + { return m_pScopes.get(); } + AstModule* getRoot() + { return m_pRoot.get(); } + const OString& getFileName() const + { return m_fileName; } + void setFileName(const OString& fileName) + { m_fileName = fileName; addInclude(fileName); } + const OString& getMainFileName() const + { return m_mainFileName; } + void setMainFileName(const OString& mainFileName) + { m_mainFileName = mainFileName; } + const OString& getRealFileName() const + { return m_realFileName; } + void setRealFileName(const OString& realFileName) + { m_realFileName = realFileName; } + const OString& getDocumentation() + { + m_bIsDocValid = false; + return m_documentation; + } + void setDocumentation(const OString& documentation) + { + m_documentation = documentation; + m_bIsDocValid = true; + } + OUString processDocumentation(); + bool isInMainFile() const + { return m_bIsInMainfile; } + void setInMainfile(bool bInMainfile) + { m_bIsInMainfile = bInMainfile; } + sal_uInt32 getErrorCount() const + { return m_errorCount; } + void incErrorCount() + { m_errorCount++; } + sal_uInt32 getWarningCount() const + { return m_warningCount; } + void incWarningCount() + { m_warningCount++; } + sal_uInt32 getLineNumber() const + { return m_lineNumber; } + sal_uInt32 getOffsetStart() const + { return m_offsetStart; } + sal_uInt32 getOffsetEnd() const + { return m_offsetEnd; } + void setOffset( sal_uInt32 start, sal_uInt32 end) + { m_offsetStart = start; m_offsetEnd = end; } + void setLineNumber(sal_uInt32 lineNumber) + { m_lineNumber = lineNumber; } + void incLineNumber() + { m_lineNumber++; } + ParseState getParseState() const + { return m_parseState; } + void setParseState(ParseState parseState) + { m_parseState = parseState; } + + void addInclude(const OString& inc) + { m_includes.insert(inc); } + + void setPublished(bool published) { m_published = published; } + bool isPublished() const { return m_published; } + + void reset(); +private: + Options* m_pOptions; + std::unique_ptr<AstStack> m_pScopes; + std::unique_ptr<AstModule> m_pRoot; + OString m_fileName; + OString m_mainFileName; + OString m_realFileName; + OString m_documentation; + bool m_bIsDocValid; + bool m_bGenerateDoc; + bool m_bIsInMainfile; + bool m_published; + sal_uInt32 m_errorCount; + sal_uInt32 m_warningCount; + sal_uInt32 m_lineNumber; + sal_uInt32 m_offsetStart; + sal_uInt32 m_offsetEnd; + ParseState m_parseState; + std::set< OString > m_includes; +}; + + +typedef ::std::pair< OString, OString > sPair_t; +sal_Int32 compileFile(const OString * pathname); + // a null pathname means stdin +sal_Int32 produceFile(const OString& filenameBase, + sPair_t const*const pDepFile); + // filenameBase is filename without ".idl" +void removeIfExists(std::string_view pathname); + +bool copyFile(const OString* source, const OString& target); + // a null source means stdin + +bool isFileUrl(std::string_view fileName); +OString convertToAbsoluteSystemPath(const OString& fileName); +OString convertToFileUrl(const OString& fileName); + +Idlc* idlc(); +Idlc* setIdlc(Options* pOptions); + +AstDeclaration const * resolveTypedefs(AstDeclaration const * type); + +AstDeclaration const * deconstructAndResolveTypedefs( + AstDeclaration const * type, sal_Int32 * rank); + +AstInterface const * resolveInterfaceTypedefs(AstType const * type); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/inc/idlctypes.hxx b/idlc/inc/idlctypes.hxx new file mode 100644 index 000000000..a2dadfee1 --- /dev/null +++ b/idlc/inc/idlctypes.hxx @@ -0,0 +1,189 @@ +/* -*- 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 . + */ +#pragma once + +#include <stdio.h> + +#include <list> +#include <set> +#include <string> +#include <unordered_map> +#include <vector> + +#include <sal/types.h> +#include <rtl/ustring.hxx> + + +class AstDeclaration; + +typedef std::list< AstDeclaration* > DeclList; + +class AstScope; +AstDeclaration* scopeAsDecl(AstScope* pScope); +AstScope* declAsScope(AstDeclaration* pDecl); + +// flags used for attributes, properties and services +#define AF_INVALID 0x0000 +#define AF_READONLY 0x0001 +#define AF_OPTIONAL 0x0002 +#define AF_MAYBEVOID 0x0004 +#define AF_BOUND 0x0008 +#define AF_CONSTRAINED 0x0010 +#define AF_TRANSIENT 0x0020 +#define AF_MAYBEAMBIGUOUS 0x0040 +#define AF_MAYBEDEFAULT 0x0080 +#define AF_REMOVABLE 0x0100 +#define AF_ATTRIBUTE 0x0200 +#define AF_PROPERTY 0x0400 + +enum ParseState +{ + PS_NoState, + PS_TypeDeclSeen, // Seen complete typedef declaration + PS_ConstantDeclSeen, // Seen complete const declaration + PS_ExceptionDeclSeen, // Seen complete exception declaration + PS_InterfaceDeclSeen, // Seen complete interface declaration + PS_ServiceDeclSeen, // Seen complete service declaration + PS_SingletonDeclSeen, // Seen complete singleton declaration + PS_ModuleDeclSeen, // Seen complete module declaration + PS_AttributeDeclSeen, // Seen complete attribute declaration + PS_PropertyDeclSeen, // Seen complete property declaration + PS_OperationDeclSeen, // Seen complete operation declaration + PS_InterfaceInheritanceDeclSeen, // Seen complete interface inheritance decl + PS_ConstantsDeclSeen, // Seen complete constants declaration + + PS_ServiceSeen, // Seen a SERVICE keyword + PS_ServiceIDSeen, // Seen the service ID + PS_ServiceSqSeen, // '{' seen for service + PS_ServiceQsSeen, // '}' seen for service + PS_ServiceBodySeen, // Seen complete service body + PS_ServiceMemberSeen, // Seen a service member + PS_ServiceIFHeadSeen, // Seen an interface member header + PS_ServiceSHeadSeen, // Seen a service member header + + PS_SingletonSeen, // Seen a SINGLETON keyword + PS_SingletonIDSeen, // Seen the singleton ID + PS_SingletonSqSeen, // '{' seen for singleton + PS_SingletonQsSeen, // '}' seen for singleton + PS_SingletonBodySeen, // Seen complete singleton body + + PS_ModuleSeen, // Seen a MODULE keyword + PS_ModuleIDSeen, // Seen the module ID + PS_ModuleSqSeen, // '{' seen for module + PS_ModuleQsSeen, // '}' seen for module + PS_ModuleBodySeen, // Seen complete module body + + PS_ConstantsSeen, // Seen a CONSTANTS keyword + PS_ConstantsIDSeen, // Seen the constants ID + PS_ConstantsSqSeen, // '{' seen for constants + PS_ConstantsQsSeen, // '}' seen for constants + PS_ConstantsBodySeen, // Seen complete constants body + + PS_InterfaceSeen, // Seen an INTERFACE keyword + PS_InterfaceIDSeen, // Seen the interface ID + PS_InterfaceHeadSeen, // Seen the interface head + PS_InheritSpecSeen, // Seen a complete inheritance spec + PS_ForwardDeclSeen, // Forward interface decl seen + PS_InterfaceSqSeen, // '{' seen for interface + PS_InterfaceQsSeen, // '}' seen for interface + PS_InterfaceBodySeen, // Seen an interface body + PS_InheritColonSeen, // Seen ':' in inheritance list + + PS_SNListCommaSeen, // Seen ',' in list of scoped names + PS_ScopedNameSeen, // Seen a complete scoped name + PS_SN_IDSeen, // Seen an identifier as part of a scoped name + PS_ScopeDelimSeen, // Seen a scope delim as party of a scoped name + + PS_ConstSeen, // Seen a CONST keyword + PS_ConstTypeSeen, // Parsed the type of a constant + PS_ConstIDSeen, // Seen the constant ID + PS_ConstAssignSeen, // Seen the '=' + PS_ConstExprSeen, // Seen the constant value expression + + PS_TypedefSeen, // Seen a TYPEDEF keyword + PS_TypeSpecSeen, // Seen a complete type specification + PS_DeclaratorsSeen, // Seen a complete list of declarators + + PS_StructSeen, // Seen a STRUCT keyword + PS_StructHeaderSeen, // Seen struct header + PS_StructIDSeen, // Seen the struct ID + PS_StructSqSeen, // '{' seen for struct + PS_StructQsSeen, // '}' seen for struct + PS_StructBodySeen, // Seen complete body of struct decl + + PS_MemberTypeSeen, // Seen type of struct or except member + PS_MemberDeclsSeen, // Seen decls of struct or except members + PS_MemberDeclsCompleted,// Completed one struct or except member to ';' + + PS_EnumSeen, // Seen an ENUM keyword + PS_EnumIDSeen, // Seen the enum ID + PS_EnumSqSeen, // Seen '{' for enum + PS_EnumQsSeen, // Seen '}' for enum + PS_EnumBodySeen, // Seen complete enum body + PS_EnumCommaSeen, // Seen ',' in list of enumerators + + PS_SequenceSeen, // Seen a SEQUENCE keyword + PS_SequenceSqSeen, // Seen '<' for sequence + PS_SequenceQsSeen, // Seen '>' for sequence + PS_SequenceTypeSeen, // Seen type decl for sequence + + PS_FlagHeaderSeen, // Seen the attribute|property|interface member head + PS_AttrSeen, // Seen ATTRIBUTE keyword + PS_AttrTypeSeen, // Seen type decl for attribute + PS_AttrCompleted, // Seen complete attribute declaration + PS_ReadOnlySeen, // Seen READONLY keyword + PS_OptionalSeen, // Seen OPTIONAL keyword + PS_MayBeVoidSeen, // Seen MAYBEVOID yword + PS_BoundSeen, // Seen BOUND keyword + PS_ConstrainedSeen, // Seen CONSTRAINED keyword + PS_TransientSeen, // Seen TRANSIENT keyword + PS_MayBeAmbiguousSeen, // Seen MAYBEAMBIGUOUS keyword + PS_MayBeDefaultSeen, // Seen MAYBEDEFAULT keyword + PS_RemoveableSeen, // Seen REMOVABLE keyword + + PS_PropertySeen, // Seen PROPERTY keyword + PS_PropertyTypeSeen, // Seen type decl for property + PS_PropertyCompleted, // Seen complete property declaration + + PS_ExceptSeen, // Seen EXCEPTION keyword + PS_ExceptHeaderSeen, // Seen exception header keyword + PS_ExceptIDSeen, // Seen exception identifier + PS_ExceptSqSeen, // Seen '{' for exception + PS_ExceptQsSeen, // Seen '}' for exception + PS_ExceptBodySeen, // Seen complete exception body + + PS_OpTypeSeen, // Seen operation return type + PS_OpIDSeen, // Seen operation ID + PS_OpParsCompleted, // Completed operation param list + PS_OpSqSeen, // Seen '(' for operation + PS_OpQsSeen, // Seen ')' for operation + PS_OpParCommaSeen, // Seen ',' in list of op params + PS_OpParDirSeen, // Seen parameter direction + PS_OpParTypeSeen, // Seen parameter type + PS_OpParDeclSeen, // Seen parameter declaration + + PS_RaiseSeen, // Seen RAISES keyword + PS_RaiseSqSeen, // Seen '(' for RAISES + PS_RaiseQsSeen, // Seen ')' for RAISES + + PS_DeclsCommaSeen, // Seen ',' in declarators list + PS_DeclsDeclSeen // Seen complete decl in decls list +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/inc/inheritedinterface.hxx b/idlc/inc/inheritedinterface.hxx new file mode 100644 index 000000000..16462b4da --- /dev/null +++ b/idlc/inc/inheritedinterface.hxx @@ -0,0 +1,56 @@ +/* -*- 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 . + */ + +#ifndef INCLUDED_IDLC_INC_INHERITEDINTERFACE_HXX +#define INCLUDED_IDLC_INC_INHERITEDINTERFACE_HXX + +#include "idlc.hxx" + +#include <rtl/ustring.hxx> +#include <utility> + +class AstInterface; +class AstType; + +class InheritedInterface { +public: + InheritedInterface( + AstType const * theInterface, bool theOptional, + OUString theDocumentation): + interface(theInterface), optional(theOptional), + documentation(std::move(theDocumentation)) {} + + AstType const * getInterface() const { return interface; } + + AstInterface const * getResolved() const + { return resolveInterfaceTypedefs(interface); } + + bool isOptional() const { return optional; } + + const OUString& getDocumentation() const { return documentation; } + +private: + AstType const * interface; + bool optional; + OUString documentation; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/inc/options.hxx b/idlc/inc/options.hxx new file mode 100644 index 000000000..c3a0949b3 --- /dev/null +++ b/idlc/inc/options.hxx @@ -0,0 +1,76 @@ +/* -*- 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 . + */ + +#ifndef INCLUDED_IDLC_INC_OPTIONS_HXX +#define INCLUDED_IDLC_INC_OPTIONS_HXX + +#include "idlctypes.hxx" +#include <utility> + +typedef std::unordered_map< OString, OString > OptionMap; + +class IllegalArgument +{ +public: + IllegalArgument(OString msg) : m_message(std::move(msg)) {} + + OString m_message; +}; + + +class Options +{ +public: + explicit Options(char const * progname); + ~Options(); + + static bool checkArgument(std::vector< std::string > & rArgs, char const * arg, size_t len); + static bool checkCommandFile(std::vector< std::string > & rArgs, char const * filename); + + /// @throws IllegalArgument + bool initOptions(std::vector< std::string > & rArgs); + /// @throws IllegalArgument + static bool badOption(char const * reason, std::string const & rArg); + bool setOption(char const * option, std::string const & rArg); + + OString prepareHelp() const; + OString prepareVersion() const; + + const OString& getProgramName() const { return m_program;} + bool isValid(const OString& option) const; + /// @throws IllegalArgument + const OString& getOption(const OString& option); + + const std::vector< OString >& getInputFiles() const { return m_inputFiles; } + bool readStdin() const { return m_stdin; } + bool verbose() const { return m_verbose; } + bool quiet() const { return m_quiet; } + +protected: + OString m_program; + std::vector< OString > m_inputFiles; + bool m_stdin; + bool m_verbose; + bool m_quiet; + OptionMap m_options; +}; + +#endif // INCLUDED_IDLC_INC_OPTIONS_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/source/astconstant.cxx b/idlc/source/astconstant.cxx new file mode 100644 index 000000000..54d235fa3 --- /dev/null +++ b/idlc/source/astconstant.cxx @@ -0,0 +1,123 @@ +/* -*- 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 <astconstant.hxx> +#include <astscope.hxx> + +#include <registry/writer.hxx> + +AstConstant::AstConstant(const ExprType type, + const NodeType nodeType, + AstExpression* pExpr, + const OString& name, + AstScope* pScope) + : AstDeclaration(nodeType, name, pScope) + , m_pConstValue(pExpr) + , m_constValueType(type) +{ +} + +AstConstant::AstConstant(const ExprType type, + AstExpression* pExpr, + const OString& name, + AstScope* pScope) + : AstDeclaration(NT_const, name, pScope) + , m_pConstValue(pExpr) + , m_constValueType(type) +{ +} + +AstConstant::~AstConstant() +{ + +} + +bool AstConstant::dumpBlob( + typereg::Writer & rBlob, sal_uInt16 index, bool published) +{ + RTConstValue aConst; + + AstExprValue *exprVal = getConstValue()->getExprValue(); + switch (getConstValueType()) + { + case ET_short: + aConst.m_type = RT_TYPE_INT16; + aConst.m_value.aShort = exprVal->u.sval; + break; + case ET_ushort: + aConst.m_type = RT_TYPE_UINT16; + aConst.m_value.aUShort = exprVal->u.usval; + break; + case ET_long: + aConst.m_type = RT_TYPE_INT32; + aConst.m_value.aLong = exprVal->u.lval; + break; + case ET_ulong: + aConst.m_type = RT_TYPE_UINT32; + aConst.m_value.aULong = exprVal->u.ulval; + break; + case ET_hyper: + aConst.m_type = RT_TYPE_INT64; + aConst.m_value.aHyper = exprVal->u.hval; + break; + case ET_uhyper: + aConst.m_type = RT_TYPE_UINT64; + aConst.m_value.aUHyper = exprVal->u.uhval; + break; + case ET_float: + aConst.m_type = RT_TYPE_FLOAT; + aConst.m_value.aFloat = exprVal->u.fval; + break; + case ET_double: + aConst.m_type = RT_TYPE_DOUBLE; + aConst.m_value.aDouble = exprVal->u.dval; + break; + case ET_byte: + aConst.m_type = RT_TYPE_BYTE; + aConst.m_value.aByte = exprVal->u.byval; + break; + case ET_boolean: + aConst.m_type = RT_TYPE_BOOL; + aConst.m_value.aBool = exprVal->u.bval; + break; + default: + { + fprintf(stderr, "%s: exprtype to const type: cannot convert ExprType\n", + idlc()->getOptions()->getProgramName().getStr()); + return false; + } + } + + OString name = getLocalName(); + + OUString type; + if ( getNodeType() != NT_enum_val ) + { + type = OStringToOUString(exprTypeToString(getConstValueType()), RTL_TEXTENCODING_UTF8); + } + + rBlob.setFieldData( + index, getDocumentation(), OUString(), + RTFieldAccess::CONST | (published ? RTFieldAccess::PUBLISHED : RTFieldAccess::NONE), + OStringToOUString(name, RTL_TEXTENCODING_UTF8), type, aConst); + + return true; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/source/astdeclaration.cxx b/idlc/source/astdeclaration.cxx new file mode 100644 index 000000000..980e7dd2b --- /dev/null +++ b/idlc/source/astdeclaration.cxx @@ -0,0 +1,164 @@ +/* -*- 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 <astdeclaration.hxx> +#include <astscope.hxx> +#include <rtl/strbuf.hxx> +#include <o3tl/string_view.hxx> +#include <osl/diagnose.h> + +constexpr OStringLiteral sGlobal("::"); + +static OString convertName(std::string_view name) +{ + OStringBuffer nameBuffer(name.size()+1); + sal_Int32 nIndex = 0; + do + { + std::string_view token( o3tl::getToken(name, 0, ':', nIndex ) ); + if( !token.empty() ) + { + nameBuffer.append('/'); + nameBuffer.append( token ); + } + } while( nIndex != -1 ); + return nameBuffer.makeStringAndClear(); +} + +AstDeclaration::AstDeclaration(NodeType type, const OString& name, AstScope* pScope) + : m_localName(name) + , m_pScope(pScope) + , m_nodeType(type) + , m_bImported(false) + , m_bInMainFile(false) + , m_bPredefined(false) + , m_lineNumber(0) +{ + if ( m_pScope ) + { + AstDeclaration* pDecl = scopeAsDecl(m_pScope); + if (pDecl) + { + m_scopedName = pDecl->getScopedName(); + if (!m_scopedName.isEmpty()) + m_scopedName += sGlobal; + m_scopedName += m_localName; + } + } else + { + m_scopedName = m_localName; + } + m_fullName = convertName(m_scopedName); + + if ( idlc()->getFileName() == idlc()->getRealFileName() ) + { + m_fileName = idlc()->getMainFileName(); + m_bInMainFile = true; + } else + { + m_fileName = idlc()->getFileName(); + m_bImported = true; + } + + m_documentation = idlc()->processDocumentation(); + + m_bPublished = idlc()->isPublished(); +} + + +AstDeclaration::~AstDeclaration() +{ + +} + +void AstDeclaration::setPredefined(bool bPredefined) +{ + m_bPredefined = bPredefined; + if ( m_bPredefined ) + { + m_fileName.clear(); + m_bInMainFile = false; + } +} + +bool AstDeclaration::isType() const { + switch (m_nodeType) { + case NT_interface: + case NT_instantiated_struct: + case NT_enum: + case NT_sequence: + case NT_typedef: + case NT_predefined: + case NT_type_parameter: + return true; + + default: + OSL_ASSERT(m_nodeType != NT_struct); // see AstStruct::isType + return false; + } +} + +bool AstDeclaration::hasAncestor(AstDeclaration* pDecl) +{ + if (this == pDecl) + return true; + if ( !m_pScope ) + return false; + return scopeAsDecl(m_pScope)->hasAncestor(pDecl); +} + +bool AstDeclaration::dump(RegistryKey& rKey) +{ + AstScope* pScope = declAsScope(this); + if ( !pScope ) + return true; + + bool bRet = true; + DeclList::const_iterator iter = pScope->getIteratorBegin(); + DeclList::const_iterator end = pScope->getIteratorEnd(); + AstDeclaration* pDecl = nullptr; + while ( iter != end && bRet) + { + pDecl = *iter; + if ( pDecl->isInMainfile() ) + { + switch ( pDecl->getNodeType() ) + { + case NT_module: + case NT_constants: + case NT_interface: + case NT_struct: + case NT_exception: + case NT_enum: + case NT_typedef: + case NT_service: + case NT_singleton: + bRet = pDecl->dump(rKey); + break; + default: + break; + } + } + + ++iter; + } + return bRet; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/source/astdump.cxx b/idlc/source/astdump.cxx new file mode 100644 index 000000000..79613e137 --- /dev/null +++ b/idlc/source/astdump.cxx @@ -0,0 +1,420 @@ +/* -*- 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 <astmodule.hxx> +#include <asttypedef.hxx> +#include <astservice.hxx> +#include <astconstant.hxx> +#include <astattribute.hxx> +#include <astinterfacemember.hxx> +#include <astservicemember.hxx> +#include <astobserves.hxx> +#include <astneeds.hxx> +#include <astsequence.hxx> +#include <astoperation.hxx> + +#include <osl/diagnose.h> + +#include <registry/version.h> +#include <registry/writer.hxx> + +bool AstModule::dump(RegistryKey& rKey) +{ + RegistryKey localKey; + if ( getNodeType() == NT_root ) + { + localKey = rKey; + }else + { + if (rKey.createKey( OStringToOUString(getFullName(), RTL_TEXTENCODING_UTF8 ), localKey) != RegError::NO_ERROR) + { + fprintf(stderr, "%s: warning, could not create key '%s' in '%s'\n", + idlc()->getOptions()->getProgramName().getStr(), + getFullName().getStr(), OUStringToOString(rKey.getRegistryName(), RTL_TEXTENCODING_UTF8).getStr()); + return false; + } + } + + sal_uInt16 nConst = getNodeCount(NT_const); + + if ( nConst > 0 ) + { + RTTypeClass typeClass = RT_TYPE_MODULE; + if ( getNodeType() == NT_constants ) + typeClass = RT_TYPE_CONSTANTS; + + typereg::Writer aBlob( + m_bPublished ? TYPEREG_VERSION_1 : TYPEREG_VERSION_0, + getDocumentation(), "", typeClass, + m_bPublished, + OStringToOUString(getRelativName(), RTL_TEXTENCODING_UTF8), 0, + nConst, 0, 0); + + DeclList::const_iterator iter = getIteratorBegin(); + DeclList::const_iterator end = getIteratorEnd(); + sal_uInt16 index = 0; + while ( iter != end ) + { + AstDeclaration* pDecl = *iter; + if ( pDecl->getNodeType() == NT_const && + pDecl->isInMainfile() ) + { + static_cast<AstConstant*>(pDecl)->dumpBlob( + aBlob, index++, + getNodeType() == NT_module && pDecl->isPublished()); + } + ++iter; + } + + sal_uInt32 aBlobSize; + void const * pBlob = aBlob.getBlob(&aBlobSize); + + if (localKey.setValue("", RegValueType::BINARY, + const_cast<RegValue>(pBlob), aBlobSize) != RegError::NO_ERROR) + { + fprintf(stderr, "%s: warning, could not set value of key \"%s\" in %s\n", + idlc()->getOptions()->getProgramName().getStr(), + getFullName().getStr(), OUStringToOString(localKey.getRegistryName(), RTL_TEXTENCODING_UTF8).getStr()); + return false; + } + } else + { + RTTypeClass typeClass = RT_TYPE_MODULE; + if ( getNodeType() == NT_constants ) + typeClass = RT_TYPE_CONSTANTS; + + typereg::Writer aBlob( + m_bPublished ? TYPEREG_VERSION_1 : TYPEREG_VERSION_0, + getDocumentation(), "", typeClass, m_bPublished, + OStringToOUString(getRelativName(), RTL_TEXTENCODING_UTF8), 0, 0, 0, + 0); + + sal_uInt32 aBlobSize; + void const * pBlob = aBlob.getBlob(&aBlobSize); + + if ( getNodeType() != NT_root ) + { + if (localKey.setValue("", RegValueType::BINARY, + const_cast<RegValue>(pBlob), aBlobSize) != RegError::NO_ERROR) + { + fprintf(stderr, "%s: warning, could not set value of key \"%s\" in %s\n", + idlc()->getOptions()->getProgramName().getStr(), + getFullName().getStr(), OUStringToOString(localKey.getRegistryName(), RTL_TEXTENCODING_UTF8).getStr()); + return false; + } + } + } + if ( getNodeType() == NT_root ) + { + localKey.releaseKey(); + } + return AstDeclaration::dump(rKey); +} + +bool AstTypeDef::dump(RegistryKey& rKey) +{ + RegistryKey localKey; + if (rKey.createKey( OStringToOUString(getFullName(), RTL_TEXTENCODING_UTF8 ), localKey) != RegError::NO_ERROR) + { + fprintf(stderr, "%s: warning, could not create key '%s' in '%s'\n", + idlc()->getOptions()->getProgramName().getStr(), + getFullName().getStr(), OUStringToOString(rKey.getRegistryName(), RTL_TEXTENCODING_UTF8).getStr()); + return false; + } + + typereg::Writer aBlob( + m_bPublished ? TYPEREG_VERSION_1 : TYPEREG_VERSION_0, + getDocumentation(), "", RT_TYPE_TYPEDEF, m_bPublished, + OStringToOUString(getRelativName(), RTL_TEXTENCODING_UTF8), 1, 0, 0, 0); + aBlob.setSuperTypeName( + 0, + OStringToOUString( + getBaseType()->getRelativName(), RTL_TEXTENCODING_UTF8)); + + sal_uInt32 aBlobSize; + void const * pBlob = aBlob.getBlob(&aBlobSize); + + if (localKey.setValue("", RegValueType::BINARY, const_cast<RegValue>(pBlob), aBlobSize) != RegError::NO_ERROR) + { + fprintf(stderr, "%s: warning, could not set value of key \"%s\" in %s\n", + idlc()->getOptions()->getProgramName().getStr(), + getFullName().getStr(), OUStringToOString(localKey.getRegistryName(), RTL_TEXTENCODING_UTF8).getStr()); + return false; + } + + return true; +} + +bool AstService::dump(RegistryKey& rKey) +{ + typereg_Version version = m_bPublished + ? TYPEREG_VERSION_1 : TYPEREG_VERSION_0; + OString superName; + sal_uInt16 constructors = 0; + sal_uInt16 properties = 0; + sal_uInt16 references = 0; + for (DeclList::const_iterator i(getIteratorBegin()); i != getIteratorEnd(); + ++i) + { + switch ((*i)->getNodeType()) { + case NT_interface: + case NT_typedef: + version = TYPEREG_VERSION_1; + OSL_ASSERT(superName.isEmpty()); + superName = (*i)->getRelativName(); + break; + + case NT_operation: + OSL_ASSERT(getNodeType() == NT_service); + ++constructors; + break; + + case NT_property: + OSL_ASSERT(getNodeType() == NT_service); + ++properties; + break; + + case NT_service_member: + if (getNodeType() == NT_singleton) { + OSL_ASSERT(superName.isEmpty()); + superName = static_cast<AstServiceMember *>(*i)-> + getRealService()->getRelativName(); + break; + } + [[fallthrough]]; + case NT_interface_member: + case NT_observes: + case NT_needs: + OSL_ASSERT(getNodeType() == NT_service); + ++references; + break; + + default: + OSL_ASSERT(false); + break; + } + } + OSL_ASSERT(constructors == 0 || !m_defaultConstructor); + if (m_defaultConstructor) { + constructors = 1; + } + RegistryKey localKey; + if (rKey.createKey( + OStringToOUString(getFullName(), RTL_TEXTENCODING_UTF8), + localKey) != RegError::NO_ERROR) { + fprintf( + stderr, "%s: warning, could not create key '%s' in '%s'\n", + idlc()->getOptions()->getProgramName().getStr(), + getFullName().getStr(), + OUStringToOString( + rKey.getRegistryName(), RTL_TEXTENCODING_UTF8).getStr()); + return false; + } + typereg::Writer writer( + version, getDocumentation(), "", + getNodeType() == NT_singleton ? RT_TYPE_SINGLETON : RT_TYPE_SERVICE, + m_bPublished, + OStringToOUString(getRelativName(), RTL_TEXTENCODING_UTF8), + superName.isEmpty() ? 0 : 1, properties, constructors, + references); + if (!superName.isEmpty()) { + writer.setSuperTypeName( + 0, OStringToOUString(superName, RTL_TEXTENCODING_UTF8)); + } + sal_uInt16 constructorIndex = 0; + sal_uInt16 propertyIndex = 0; + sal_uInt16 referenceIndex = 0; + for (DeclList::const_iterator i(getIteratorBegin()); i != getIteratorEnd(); ++i) + { + switch ((*i)->getNodeType()) { + case NT_operation: + static_cast<AstOperation *>(*i)->dumpBlob(writer, constructorIndex++); + break; + + case NT_property: + static_cast<AstAttribute *>(*i)->dumpBlob(writer, propertyIndex++, nullptr); + break; + + case NT_interface_member: + { + AstInterfaceMember * decl = static_cast<AstInterfaceMember *>(*i); + writer.setReferenceData( + referenceIndex++, decl->getDocumentation(), RTReferenceType::SUPPORTS, + (decl->isOptional() ? RTFieldAccess::OPTIONAL : RTFieldAccess::INVALID), + OStringToOUString( decl->getRealInterface()->getRelativName(), + RTL_TEXTENCODING_UTF8)); + break; + } + + case NT_service_member: + if (getNodeType() == NT_service) + { + AstServiceMember * decl = static_cast<AstServiceMember *>(*i); + writer.setReferenceData(referenceIndex++, decl->getDocumentation(), RTReferenceType::EXPORTS, + (decl->isOptional() ? RTFieldAccess::OPTIONAL : RTFieldAccess::INVALID), + OStringToOUString(decl->getRealService()->getRelativName(), + RTL_TEXTENCODING_UTF8)); + } + break; + + case NT_observes: + { + AstObserves * decl = static_cast<AstObserves *>(*i); + writer.setReferenceData(referenceIndex++, decl->getDocumentation(), RTReferenceType::OBSERVES, + RTFieldAccess::INVALID, + OStringToOUString( decl->getRealInterface()->getRelativName(), + RTL_TEXTENCODING_UTF8)); + break; + } + + case NT_needs: + { + AstNeeds * decl = static_cast<AstNeeds *>(*i); + writer.setReferenceData( referenceIndex++, decl->getDocumentation(), RTReferenceType::NEEDS, + RTFieldAccess::INVALID, + OStringToOUString( decl->getRealService()->getRelativName(), + RTL_TEXTENCODING_UTF8)); + break; + } + + default: + OSL_ASSERT( (*i)->getNodeType() == NT_interface || (*i)->getNodeType() == NT_typedef); + break; + } + } + if (m_defaultConstructor) { + writer.setMethodData( + constructorIndex++, "", RTMethodMode::TWOWAY, + "", "void", + 0, 0); + } + sal_uInt32 size; + void const * blob = writer.getBlob(&size); + if (localKey.setValue( + "", RegValueType::BINARY, const_cast< void * >(blob), + size) != RegError::NO_ERROR) + { + fprintf( + stderr, "%s: warning, could not set value of key \"%s\" in %s\n", + idlc()->getOptions()->getProgramName().getStr(), + getFullName().getStr(), + OUStringToOString( + localKey.getRegistryName(), RTL_TEXTENCODING_UTF8).getStr()); + return false; + } + return true; +} + +void AstAttribute::dumpBlob( + typereg::Writer & rBlob, sal_uInt16 index, sal_uInt16 * methodIndex) const +{ + RTFieldAccess accessMode = RTFieldAccess::INVALID; + + if (isReadonly()) + { + accessMode |= RTFieldAccess::READONLY; + } else + { + accessMode |= RTFieldAccess::READWRITE; + } + if (isOptional()) + { + accessMode |= RTFieldAccess::OPTIONAL; + } + if (isBound()) + { + accessMode |= RTFieldAccess::BOUND; + } + if (isMayBeVoid()) + { + accessMode |= RTFieldAccess::MAYBEVOID; + } + if (isConstrained()) + { + accessMode |= RTFieldAccess::CONSTRAINED; + } + if (isTransient()) + { + accessMode |= RTFieldAccess::TRANSIENT; + } + if (isMayBeAmbiguous()) + { + accessMode |= RTFieldAccess::MAYBEAMBIGUOUS; + } + if (isMayBeDefault()) + { + accessMode |= RTFieldAccess::MAYBEDEFAULT; + } + if (isRemoveable()) + { + accessMode |= RTFieldAccess::REMOVABLE; + } + + OUString name(OStringToOUString(getLocalName(), RTL_TEXTENCODING_UTF8)); + rBlob.setFieldData( + index, getDocumentation(), OUString(), accessMode, name, + OStringToOUString(m_pType->getRelativName(), RTL_TEXTENCODING_UTF8), + RTConstValue()); + dumpExceptions( + rBlob, m_getDocumentation, m_getExceptions, RTMethodMode::ATTRIBUTE_GET, + methodIndex); + dumpExceptions( + rBlob, m_setDocumentation, m_setExceptions, RTMethodMode::ATTRIBUTE_SET, + methodIndex); +} + +void AstAttribute::dumpExceptions( + typereg::Writer & writer, OUString const & documentation, + DeclList const & exceptions, RTMethodMode flags, sal_uInt16 * methodIndex) const +{ + if (exceptions.empty()) + return; + + OSL_ASSERT(methodIndex != nullptr); + sal_uInt16 idx = (*methodIndex)++; + // exceptions.size() <= SAL_MAX_UINT16 already checked in + // AstInterface::dump: + writer.setMethodData( + idx, documentation, flags, + OStringToOUString(getLocalName(), RTL_TEXTENCODING_UTF8), + "void", 0, + static_cast< sal_uInt16 >(exceptions.size())); + sal_uInt16 exceptionIndex = 0; + for (auto const& elem : exceptions) + { + writer.setMethodExceptionTypeName( + idx, exceptionIndex++, + OStringToOUString( + elem->getRelativName(), RTL_TEXTENCODING_UTF8)); + } +} + +const char* AstSequence::getRelativName() const +{ + if ( !m_xRelativName ) + { + m_xRelativName = OString("[]"); + AstDeclaration const * pType = resolveTypedefs( m_pMemberType ); + *m_xRelativName += pType->getRelativName(); + } + + return m_xRelativName->getStr(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/source/astenum.cxx b/idlc/source/astenum.cxx new file mode 100644 index 000000000..7dff49d36 --- /dev/null +++ b/idlc/source/astenum.cxx @@ -0,0 +1,105 @@ +/* -*- 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 <astenum.hxx> + +#include <registry/version.h> +#include <registry/writer.hxx> + +AstEnum::AstEnum(const OString& name, AstScope* pScope) + : AstType(NT_enum, name, pScope) + , AstScope(NT_enum) + , m_enumValueCount(0) +{ +} + +AstEnum::~AstEnum() +{ +} + +AstConstant* AstEnum::checkValue(AstExpression* pExpr) +{ + DeclList::const_iterator iter = getIteratorBegin(); + DeclList::const_iterator end = getIteratorEnd(); + + iter = std::find_if(iter, end, [&pExpr](AstDeclaration* pDecl) { + return static_cast<AstConstant*>(pDecl)->getConstValue()->compareLong(pExpr); }); + + if (iter != end) + return static_cast<AstConstant*>(*iter); + + if ( pExpr->getExprValue()->u.lval > m_enumValueCount ) + m_enumValueCount = pExpr->getExprValue()->u.lval + 1; + + return nullptr; +} + +bool AstEnum::dump(RegistryKey& rKey) +{ + RegistryKey localKey; + if (rKey.createKey( OStringToOUString(getFullName(), RTL_TEXTENCODING_UTF8 ), localKey) != RegError::NO_ERROR) + { + fprintf(stderr, "%s: warning, could not create key '%s' in '%s'\n", + idlc()->getOptions()->getProgramName().getStr(), + getFullName().getStr(), OUStringToOString(rKey.getRegistryName(), RTL_TEXTENCODING_UTF8).getStr()); + return false; + } + + sal_uInt16 nConst = getNodeCount(NT_enum_val); + if ( nConst <= 0 ) + return true; + + typereg::Writer aBlob( + m_bPublished ? TYPEREG_VERSION_1 : TYPEREG_VERSION_0, + getDocumentation(), "", RT_TYPE_ENUM, m_bPublished, + OStringToOUString(getRelativName(), RTL_TEXTENCODING_UTF8), 0, + nConst, 0, 0); + + DeclList::const_iterator iter = getIteratorBegin(); + DeclList::const_iterator end = getIteratorEnd(); + sal_uInt16 index = 0; + while ( iter != end ) + { + AstDeclaration* pDecl = *iter; + if ( pDecl->getNodeType() == NT_enum_val ) + static_cast<AstConstant*>(pDecl)->dumpBlob(aBlob, index++, false); + + ++iter; + } + + sal_uInt32 aBlobSize; + void const * pBlob = aBlob.getBlob(&aBlobSize); + + if (localKey.setValue("", RegValueType::BINARY, + const_cast<RegValue>(pBlob), aBlobSize) != RegError::NO_ERROR) + { + fprintf(stderr, "%s: warning, could not set value of key \"%s\" in %s\n", + idlc()->getOptions()->getProgramName().getStr(), + getFullName().getStr(), OUStringToOString(localKey.getRegistryName(), RTL_TEXTENCODING_UTF8).getStr()); + return false; + } + + return true; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/source/astexpression.cxx b/idlc/source/astexpression.cxx new file mode 100644 index 000000000..1afa91dbf --- /dev/null +++ b/idlc/source/astexpression.cxx @@ -0,0 +1,1327 @@ +/* -*- 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 <astexpression.hxx> +#include <astconstant.hxx> +#include <astscope.hxx> +#include <errorhandler.hxx> + +#include <o3tl/float_int_conversion.hxx> +#include <osl/diagnose.h> + +#include <limits.h> +#include <float.h> +#include <memory> + +AstExpression::AstExpression(ExprComb c, AstExpression* pExpr1, AstExpression* pExpr2) + : m_combOperator(c) + , m_subExpr1(pExpr1) + , m_subExpr2(pExpr2) +{ +} + +AstExpression::AstExpression(sal_Int32 l) + : m_combOperator(ExprComb::NONE) +{ + m_exprValue.reset(new AstExprValue); + m_exprValue->et = ET_long; + m_exprValue->u.lval = l; +} + +AstExpression::AstExpression(sal_Int32 l, ExprType et) + : m_combOperator(ExprComb::NONE) +{ + m_exprValue.reset(new AstExprValue); + m_exprValue->et = et; + m_exprValue->u.lval = l; +} + +AstExpression::AstExpression(sal_Int64 h) + : m_combOperator(ExprComb::NONE) +{ + m_exprValue.reset(new AstExprValue); + m_exprValue->et = ET_hyper; + m_exprValue->u.hval = h; +} + +AstExpression::AstExpression(sal_uInt64 uh) + : m_combOperator(ExprComb::NONE) +{ + m_exprValue.reset(new AstExprValue); + m_exprValue->et = ET_uhyper; + m_exprValue->u.uhval = uh; +} + +AstExpression::AstExpression(double d) + : m_combOperator(ExprComb::NONE) +{ + m_exprValue.reset(new AstExprValue); + m_exprValue->et = ET_double; + m_exprValue->u.dval = d; +} + +AstExpression::AstExpression(OString* scopedName) + : m_combOperator(ExprComb::Symbol) +{ + if (scopedName) + m_xSymbolicName = *scopedName; +} + +AstExpression::~AstExpression() {} + +/* + * Perform the coercion from the given AstExprValue to the requested + * ExprType. Return an AstExprValue if successful, NULL if failed. + * must be done for hyper, uhyper + */ +static bool coerce_value(AstExprValue* ev, ExprType t) +{ + if (ev == nullptr) + return false; + + switch (t) + { + case ET_short: + switch (ev->et) + { + case ET_short: + return true; + case ET_ushort: + { + if (ev->u.usval > SAL_MAX_INT16) + return false; + auto tmp = static_cast<sal_Int16>(ev->u.usval); + ev->u.sval = tmp; + ev->et = ET_short; + return true; + } + case ET_long: + { + if (ev->u.lval < SAL_MIN_INT16 || ev->u.lval > SAL_MAX_INT16) + return false; + auto tmp = static_cast<sal_Int16>(ev->u.lval); + ev->u.sval = tmp; + ev->et = ET_short; + return true; + } + case ET_ulong: + { + if (ev->u.ulval > SAL_MAX_INT16) + return false; + auto tmp = static_cast<sal_Int16>(ev->u.ulval); + ev->u.sval = tmp; + ev->et = ET_short; + return true; + } + case ET_hyper: + { + if (ev->u.hval < SAL_MIN_INT16 || ev->u.hval > SAL_MAX_INT16) + return false; + auto tmp = static_cast<sal_Int16>(ev->u.hval); + ev->u.sval = tmp; + ev->et = ET_short; + return true; + } + case ET_uhyper: + { + if (ev->u.uhval > SAL_MAX_INT16) + return false; + auto tmp = static_cast<sal_Int16>(ev->u.uhval); + ev->u.sval = tmp; + ev->et = ET_short; + return true; + } + case ET_boolean: + { + auto tmp = static_cast<sal_Int16>(ev->u.bval); + ev->u.sval = tmp; + ev->et = ET_short; + return true; + } + case ET_float: + { + if (!(o3tl::convertsToAtLeast(o3tl::roundAway(ev->u.fval), SAL_MIN_INT16) + && o3tl::convertsToAtMost(o3tl::roundAway(ev->u.fval), SAL_MAX_INT16))) + { + return false; + } + auto tmp = static_cast<sal_Int16>(ev->u.fval); + ev->u.sval = tmp; + ev->et = ET_short; + return true; + } + case ET_double: + { + if (!(o3tl::convertsToAtLeast(o3tl::roundAway(ev->u.dval), SAL_MIN_INT16) + && o3tl::convertsToAtMost(o3tl::roundAway(ev->u.dval), SAL_MAX_INT16))) + { + return false; + } + auto tmp = static_cast<sal_Int16>(ev->u.dval); + ev->u.sval = tmp; + ev->et = ET_short; + return true; + } + case ET_byte: + { + auto tmp = static_cast<sal_Int16>(ev->u.byval); + ev->u.sval = tmp; + ev->et = ET_short; + return true; + } + default: + OSL_ASSERT(false); + return false; + } + case ET_ushort: + switch (ev->et) + { + case ET_short: + { + if (ev->u.sval < 0) + return false; + auto tmp = static_cast<sal_uInt16>(ev->u.sval); + ev->u.usval = tmp; + ev->et = ET_ushort; + return true; + } + case ET_ushort: + return true; + case ET_long: + { + if (ev->u.lval < 0 || ev->u.lval > SAL_MAX_UINT16) + return false; + auto tmp = static_cast<sal_uInt16>(ev->u.lval); + ev->u.usval = tmp; + ev->et = ET_ushort; + return true; + } + case ET_ulong: + { + if (ev->u.ulval > SAL_MAX_UINT16) + return false; + auto tmp = static_cast<sal_uInt16>(ev->u.ulval); + ev->u.usval = tmp; + ev->et = ET_ushort; + return true; + } + case ET_hyper: + { + if (ev->u.hval < 0 || ev->u.hval > SAL_MAX_UINT16) + return false; + auto tmp = static_cast<sal_uInt16>(ev->u.hval); + ev->u.usval = tmp; + ev->et = ET_ushort; + return true; + } + case ET_uhyper: + { + if (ev->u.uhval > SAL_MAX_UINT16) + return false; + auto tmp = static_cast<sal_uInt16>(ev->u.uhval); + ev->u.usval = tmp; + ev->et = ET_ushort; + return true; + } + case ET_boolean: + { + auto tmp = static_cast<sal_uInt16>(ev->u.bval); + ev->u.usval = tmp; + ev->et = ET_short; + return true; + } + case ET_float: + { + if (ev->u.fval < 0.0 + || !o3tl::convertsToAtMost(o3tl::roundAway(ev->u.fval), SAL_MAX_UINT16)) + { + return false; + } + auto tmp = static_cast<sal_uInt16>(ev->u.fval); + ev->u.usval = tmp; + ev->et = ET_short; + return true; + } + case ET_double: + { + if (ev->u.dval < 0.0 + || !o3tl::convertsToAtMost(o3tl::roundAway(ev->u.dval), SAL_MAX_UINT16)) + { + return false; + } + auto tmp = static_cast<sal_uInt16>(ev->u.dval); + ev->u.usval = tmp; + ev->et = ET_short; + return true; + } + case ET_byte: + { + auto tmp = static_cast<sal_uInt16>(ev->u.byval); + ev->u.usval = tmp; + ev->et = ET_ushort; + return true; + } + default: + OSL_ASSERT(false); + return false; + } + case ET_long: + switch (ev->et) + { + case ET_short: + { + auto tmp = static_cast<sal_Int32>(ev->u.sval); + ev->u.lval = tmp; + ev->et = ET_long; + return true; + } + case ET_ushort: + { + auto tmp = static_cast<sal_Int32>(ev->u.usval); + ev->u.lval = tmp; + ev->et = ET_long; + return true; + } + case ET_long: + return true; + case ET_ulong: + { + if (ev->u.ulval > SAL_MAX_INT32) + return false; + auto tmp = static_cast<sal_Int32>(ev->u.ulval); + ev->u.lval = tmp; + ev->et = ET_long; + return true; + } + case ET_hyper: + { + if (ev->u.hval < SAL_MIN_INT32 || ev->u.hval > SAL_MAX_INT32) + return false; + auto tmp = static_cast<sal_Int32>(ev->u.hval); + ev->u.lval = tmp; + ev->et = ET_long; + return true; + } + case ET_uhyper: + { + if (ev->u.uhval > SAL_MAX_INT32) + return false; + auto tmp = static_cast<sal_Int32>(ev->u.uhval); + ev->u.lval = tmp; + ev->et = ET_long; + return true; + } + case ET_boolean: + { + auto tmp = static_cast<sal_Int32>(ev->u.bval); + ev->u.lval = tmp; + ev->et = ET_long; + return true; + } + case ET_float: + { + if (!(o3tl::convertsToAtLeast(o3tl::roundAway(ev->u.fval), SAL_MIN_INT32) + && o3tl::convertsToAtMost(o3tl::roundAway(ev->u.fval), SAL_MAX_INT32))) + { + return false; + } + auto tmp = static_cast<sal_Int32>(ev->u.fval); + ev->u.lval = tmp; + ev->et = ET_long; + return true; + } + case ET_double: + { + if (!(o3tl::convertsToAtLeast(o3tl::roundAway(ev->u.dval), SAL_MIN_INT32) + && o3tl::convertsToAtMost(o3tl::roundAway(ev->u.dval), SAL_MAX_INT32))) + { + return false; + } + auto tmp = static_cast<sal_Int32>(ev->u.dval); + ev->u.lval = tmp; + ev->et = ET_long; + return true; + } + case ET_byte: + { + auto tmp = static_cast<sal_Int32>(ev->u.byval); + ev->u.lval = tmp; + ev->et = ET_long; + return true; + } + default: + OSL_ASSERT(false); + return false; + } + case ET_ulong: + switch (ev->et) + { + case ET_short: + { + if (ev->u.sval < 0) + return false; + auto tmp = static_cast<sal_uInt32>(ev->u.sval); + ev->u.ulval = tmp; + ev->et = ET_ulong; + return true; + } + case ET_ushort: + { + auto tmp = static_cast<sal_uInt32>(ev->u.usval); + ev->u.ulval = tmp; + ev->et = ET_ulong; + return true; + } + case ET_long: + { + if (ev->u.lval < 0) + return false; + auto tmp = static_cast<sal_uInt32>(ev->u.lval); + ev->u.ulval = tmp; + ev->et = ET_ulong; + return true; + } + case ET_ulong: + return true; + case ET_hyper: + { + if (ev->u.hval < 0 || ev->u.hval > SAL_MAX_UINT32) + return false; + auto tmp = static_cast<sal_uInt32>(ev->u.hval); + ev->u.lval = tmp; + ev->et = ET_ulong; + return true; + } + case ET_uhyper: + { + if (ev->u.uhval > SAL_MAX_UINT32) + return false; + auto tmp = static_cast<sal_uInt32>(ev->u.uhval); + ev->u.ulval = tmp; + ev->et = ET_ulong; + return true; + } + case ET_boolean: + { + auto tmp = static_cast<sal_uInt32>(ev->u.bval); + ev->u.ulval = tmp; + ev->et = ET_ulong; + return true; + } + case ET_float: + { + if (ev->u.fval < 0.0 + || !o3tl::convertsToAtMost(o3tl::roundAway(ev->u.fval), SAL_MAX_UINT32)) + { + return false; + } + auto tmp = static_cast<sal_uInt32>(ev->u.fval); + ev->u.ulval = tmp; + ev->et = ET_ulong; + return true; + } + case ET_double: + { + if (ev->u.dval < 0.0 + || !o3tl::convertsToAtMost(o3tl::roundAway(ev->u.dval), SAL_MAX_UINT32)) + { + return false; + } + auto tmp = static_cast<sal_uInt32>(ev->u.dval); + ev->u.ulval = tmp; + ev->et = ET_ulong; + return true; + } + case ET_byte: + { + auto tmp = static_cast<sal_uInt32>(ev->u.byval); + ev->u.ulval = tmp; + ev->et = ET_ulong; + return true; + } + default: + OSL_ASSERT(false); + return false; + } + case ET_hyper: + switch (ev->et) + { + case ET_short: + { + auto tmp = static_cast<sal_Int64>(ev->u.sval); + ev->u.hval = tmp; + ev->et = ET_hyper; + return true; + } + case ET_ushort: + { + auto tmp = static_cast<sal_Int64>(ev->u.usval); + ev->u.hval = tmp; + ev->et = ET_hyper; + return true; + } + case ET_long: + { + auto tmp = static_cast<sal_Int64>(ev->u.lval); + ev->u.hval = tmp; + ev->et = ET_hyper; + return true; + } + case ET_ulong: + { + auto tmp = static_cast<sal_Int64>(ev->u.ulval); + ev->u.hval = tmp; + ev->et = ET_hyper; + return true; + } + case ET_hyper: + return true; + case ET_uhyper: + { + if (ev->u.uhval > SAL_MAX_INT64) + return false; + auto tmp = static_cast<sal_Int64>(ev->u.uhval); + ev->u.hval = tmp; + ev->et = ET_long; + return true; + } + case ET_boolean: + { + auto tmp = static_cast<sal_Int64>(ev->u.bval); + ev->u.hval = tmp; + ev->et = ET_hyper; + return true; + } + case ET_float: + { + if (!(o3tl::convertsToAtLeast(o3tl::roundAway(ev->u.fval), SAL_MIN_INT64) + && o3tl::convertsToAtMost(o3tl::roundAway(ev->u.fval), SAL_MAX_INT64))) + { + return false; + } + auto tmp = static_cast<sal_Int64>(ev->u.fval); + ev->u.hval = tmp; + ev->et = ET_hyper; + return true; + } + case ET_double: + { + if (!(o3tl::convertsToAtLeast(o3tl::roundAway(ev->u.dval), SAL_MIN_INT64) + && o3tl::convertsToAtMost(o3tl::roundAway(ev->u.dval), SAL_MAX_INT64))) + { + return false; + } + auto tmp = static_cast<sal_Int64>(ev->u.dval); + ev->u.hval = tmp; + ev->et = ET_hyper; + return true; + } + case ET_byte: + { + auto tmp = static_cast<sal_Int64>(ev->u.byval); + ev->u.hval = tmp; + ev->et = ET_hyper; + return true; + } + default: + OSL_ASSERT(false); + return false; + } + case ET_uhyper: + switch (ev->et) + { + case ET_short: + { + if (ev->u.sval < 0) + return false; + auto tmp = static_cast<sal_uInt64>(ev->u.sval); + ev->u.uhval = tmp; + ev->et = ET_uhyper; + return true; + } + case ET_ushort: + { + auto tmp = static_cast<sal_uInt64>(ev->u.usval); + ev->u.uhval = tmp; + ev->et = ET_uhyper; + return true; + } + case ET_long: + { + if (ev->u.lval < 0) + return false; + auto tmp = static_cast<sal_uInt64>(ev->u.lval); + ev->u.uhval = tmp; + ev->et = ET_uhyper; + return true; + } + case ET_ulong: + { + auto tmp = static_cast<sal_uInt64>(ev->u.ulval); + ev->u.uhval = tmp; + ev->et = ET_uhyper; + return true; + } + case ET_hyper: + { + if (ev->u.hval < 0) + return false; + auto tmp = static_cast<sal_uInt64>(ev->u.hval); + ev->u.uhval = tmp; + ev->et = ET_uhyper; + return true; + } + case ET_uhyper: + return true; + case ET_boolean: + { + auto tmp = static_cast<sal_uInt64>(ev->u.bval); + ev->u.uhval = tmp; + ev->et = ET_uhyper; + return true; + } + case ET_float: + { + if (ev->u.fval < 0.0 + || !o3tl::convertsToAtMost(o3tl::roundAway(ev->u.fval), SAL_MAX_UINT64)) + { + return false; + } + auto tmp = static_cast<sal_uInt64>(ev->u.fval); + ev->u.uhval = tmp; + ev->et = ET_uhyper; + return true; + } + case ET_double: + { + if (ev->u.dval < 0.0 + || !o3tl::convertsToAtMost(o3tl::roundAway(ev->u.dval), SAL_MAX_UINT64)) + { + return false; + } + auto tmp = static_cast<sal_uInt64>(ev->u.dval); + ev->u.uhval = tmp; + ev->et = ET_uhyper; + return true; + } + case ET_byte: + { + auto tmp = static_cast<sal_uInt64>(ev->u.byval); + ev->u.uhval = tmp; + ev->et = ET_uhyper; + return true; + } + default: + OSL_ASSERT(false); + return false; + } + case ET_boolean: + switch (ev->et) + { + case ET_short: + ev->u.bval = ev->u.sval != 0; + ev->et = ET_boolean; + return true; + case ET_ushort: + ev->u.bval = ev->u.usval != 0; + ev->et = ET_boolean; + return true; + case ET_long: + ev->u.bval = ev->u.lval != 0; + ev->et = ET_boolean; + return true; + case ET_ulong: + ev->u.bval = ev->u.ulval != 0; + ev->et = ET_boolean; + return true; + case ET_hyper: + ev->u.bval = ev->u.hval != 0; + ev->et = ET_boolean; + return true; + case ET_uhyper: + ev->u.bval = ev->u.uhval != 0; + ev->et = ET_boolean; + return true; + case ET_boolean: + return true; + case ET_float: + ev->u.bval = ev->u.fval != 0.0; + ev->et = ET_boolean; + return true; + case ET_double: + ev->u.bval = ev->u.dval != 0.0; + ev->et = ET_boolean; + return true; + case ET_byte: + ev->u.bval = ev->u.byval != 0; + ev->et = ET_boolean; + return true; + default: + OSL_ASSERT(false); + return false; + } + case ET_float: + switch (ev->et) + { + case ET_short: + { + auto tmp = static_cast<float>(ev->u.sval); + ev->u.fval = tmp; + ev->et = ET_float; + return true; + } + case ET_ushort: + { + auto tmp = static_cast<float>(ev->u.usval); + ev->u.fval = tmp; + ev->et = ET_float; + return true; + } + case ET_long: + { + auto tmp = static_cast<float>(ev->u.lval); + ev->u.fval = tmp; + ev->et = ET_float; + return true; + } + case ET_ulong: + { + auto tmp = static_cast<float>(ev->u.ulval); + ev->u.fval = tmp; + ev->et = ET_float; + return true; + } + case ET_hyper: + { + auto tmp = static_cast<float>(ev->u.hval); + ev->u.fval = tmp; + ev->et = ET_float; + return true; + } + case ET_uhyper: + { + if (static_cast<float>(ev->u.ulval) > FLT_MAX) + return false; + auto tmp = static_cast<float>(ev->u.ulval); + ev->u.fval = tmp; + ev->et = ET_float; + return true; + } + case ET_boolean: + ev->u.fval = ev->u.bval ? 1.0f : 0.0f; + ev->et = ET_float; + return true; + case ET_float: + return true; + case ET_double: + { + if (static_cast<float>(ev->u.dval) > FLT_MAX + || static_cast<float>(ev->u.dval) < -FLT_MAX) + return false; + auto tmp = static_cast<float>(ev->u.dval); + ev->u.fval = tmp; + ev->et = ET_float; + return true; + } + case ET_byte: + { + auto tmp = static_cast<float>(ev->u.byval); + ev->u.fval = tmp; + ev->et = ET_float; + return true; + } + default: + OSL_ASSERT(false); + return false; + } + case ET_double: + switch (ev->et) + { + case ET_short: + { + auto tmp = static_cast<double>(ev->u.sval); + ev->u.dval = tmp; + ev->et = ET_double; + return true; + } + case ET_ushort: + { + auto tmp = static_cast<double>(ev->u.usval); + ev->u.dval = tmp; + ev->et = ET_double; + return true; + } + case ET_long: + { + auto tmp = static_cast<double>(ev->u.lval); + ev->u.dval = tmp; + ev->et = ET_double; + return true; + } + case ET_ulong: + { + auto tmp = static_cast<double>(ev->u.ulval); + ev->u.dval = tmp; + ev->et = ET_double; + return true; + } + case ET_hyper: + { + auto tmp = static_cast<double>(ev->u.hval); + ev->u.dval = tmp; + ev->et = ET_double; + return true; + } + case ET_uhyper: + { + if (ev->u.dval > FLT_MAX || ev->u.dval < -FLT_MAX) + return false; + auto tmp = static_cast<double>(ev->u.ulval); + ev->u.dval = tmp; + ev->et = ET_double; + return true; + } + case ET_boolean: + ev->u.dval = ev->u.bval ? 1.0 : 0.0; + ev->et = ET_double; + return true; + case ET_float: + { + auto tmp = static_cast<double>(ev->u.fval); + ev->u.dval = tmp; + ev->et = ET_double; + return true; + } + case ET_double: + return true; + case ET_byte: + { + auto tmp = static_cast<double>(ev->u.byval); + ev->u.dval = tmp; + ev->et = ET_double; + return true; + } + default: + OSL_ASSERT(false); + return false; + } + case ET_byte: + switch (ev->et) + { + case ET_short: + { + if (ev->u.sval < SAL_MIN_INT8 || ev->u.sval > SAL_MAX_UINT8) + return false; + auto tmp = static_cast<unsigned char>(ev->u.sval); + ev->u.byval = tmp; + ev->et = ET_byte; + return true; + } + case ET_ushort: + { + if (ev->u.usval > SAL_MAX_UINT8) + return false; + auto tmp = static_cast<unsigned char>(ev->u.usval); + ev->u.byval = tmp; + ev->et = ET_byte; + return true; + } + case ET_long: + { + if (ev->u.lval < SAL_MIN_INT8 || ev->u.lval > SAL_MAX_UINT8) + return false; + auto tmp = static_cast<unsigned char>(ev->u.lval); + ev->u.byval = tmp; + ev->et = ET_byte; + return true; + } + case ET_ulong: + { + if (ev->u.ulval > SAL_MAX_UINT8) + return false; + auto tmp = static_cast<unsigned char>(ev->u.ulval); + ev->u.byval = tmp; + ev->et = ET_byte; + return true; + } + case ET_hyper: + { + if (ev->u.hval < SAL_MIN_INT8 || ev->u.hval > SAL_MAX_UINT8) + return false; + auto tmp = static_cast<unsigned char>(ev->u.hval); + ev->u.byval = tmp; + ev->et = ET_byte; + return true; + } + case ET_uhyper: + { + if (ev->u.uhval > SAL_MAX_UINT8) + return false; + auto tmp = static_cast<unsigned char>(ev->u.uhval); + ev->u.byval = tmp; + ev->et = ET_byte; + return true; + } + case ET_boolean: + ev->u.byval = ev->u.bval ? 1 : 0; + ev->et = ET_byte; + return true; + case ET_float: + { + if (!(o3tl::convertsToAtLeast(o3tl::roundAway(ev->u.fval), SAL_MIN_INT8) + && o3tl::convertsToAtMost(o3tl::roundAway(ev->u.fval), SAL_MAX_UINT8))) + { + return false; + } + auto tmp = static_cast<unsigned char>(static_cast<sal_Int32>(ev->u.fval)); + ev->u.byval = tmp; + ev->et = ET_byte; + return true; + } + case ET_double: + { + if (!(o3tl::convertsToAtLeast(o3tl::roundAway(ev->u.dval), SAL_MIN_INT8) + && o3tl::convertsToAtMost(o3tl::roundAway(ev->u.dval), SAL_MAX_UINT8))) + { + return false; + } + auto tmp = static_cast<unsigned char>(static_cast<sal_Int32>(ev->u.dval)); + ev->u.byval = tmp; + ev->et = ET_byte; + return true; + } + case ET_byte: + return true; + default: + OSL_ASSERT(false); + return false; + } + default: + OSL_ASSERT(false); + return false; + } +} + +bool AstExpression::coerce(ExprType t) +{ + /* + * Is it already of the right type? + */ + if (m_exprValue != nullptr && m_exprValue->et == t) + return true; + /* + * OK, must coerce + * + * First, evaluate it, then try to coerce result type + * If already evaluated, return the result + */ + evaluate(); + if (m_exprValue == nullptr) + return false; + + if (!coerce_value(m_exprValue.get(), t)) + m_exprValue.reset(); + + return m_exprValue != nullptr; +} + +bool AstExpression::compareLong(AstExpression* pExpr) +{ + bool bRet = false; + if (m_combOperator != pExpr->m_combOperator) + return bRet; + evaluate(); + pExpr->evaluate(); + if (m_exprValue == nullptr || pExpr->getExprValue() == nullptr) + return bRet; + if (m_exprValue->et != pExpr->getExprValue()->et) + return bRet; + switch (m_exprValue->et) + { + case ET_long: + bRet = m_exprValue->u.lval == pExpr->getExprValue()->u.lval; + break; + default: + OSL_ASSERT(false); + bRet = false; + break; + } + return bRet; +} + +void AstExpression::evaluate() +{ + /* + * Already evaluated? + */ + if (m_exprValue != nullptr) + return; + /* + * OK, must evaluate operator + */ + switch (m_combOperator) + { + case ExprComb::Add: + case ExprComb::Minus: + case ExprComb::Mul: + case ExprComb::Div: + case ExprComb::Mod: + m_exprValue = eval_bin_op(); + break; + case ExprComb::Or: + case ExprComb::Xor: + case ExprComb::And: + case ExprComb::Left: + case ExprComb::Right: + m_exprValue = eval_bit_op(); + break; + case ExprComb::UPlus: + case ExprComb::UMinus: + m_exprValue = eval_un_op(); + break; + case ExprComb::Symbol: + m_exprValue = eval_symbol(); + break; + case ExprComb::NONE: + break; + } +} + +std::unique_ptr<AstExprValue> AstExpression::eval_bin_op() +{ + ExprType eType = ET_double; + + if (m_combOperator == ExprComb::Mod) + eType = ET_hyper; + + if (m_subExpr1 == nullptr || m_subExpr2 == nullptr) + return nullptr; + m_subExpr1->evaluate(); + if (m_subExpr1->getExprValue() == nullptr) + return nullptr; + if (!m_subExpr1->coerce(eType)) + return nullptr; + m_subExpr2->evaluate(); + if (m_subExpr2->getExprValue() == nullptr) + return nullptr; + if (!m_subExpr2->coerce(eType)) + return nullptr; + + std::unique_ptr<AstExprValue> retval(new AstExprValue); + retval->et = eType; + + switch (m_combOperator) + { + case ExprComb::Mod: + if (m_subExpr2->getExprValue()->u.hval == 0) + return nullptr; + retval->u.hval + = m_subExpr1->getExprValue()->u.hval % m_subExpr2->getExprValue()->u.hval; + break; + case ExprComb::Add: + retval->u.dval + = m_subExpr1->getExprValue()->u.dval + m_subExpr2->getExprValue()->u.dval; + break; + case ExprComb::Minus: + retval->u.dval + = m_subExpr1->getExprValue()->u.dval - m_subExpr2->getExprValue()->u.dval; + break; + case ExprComb::Mul: + retval->u.dval + = m_subExpr1->getExprValue()->u.dval * m_subExpr2->getExprValue()->u.dval; + break; + case ExprComb::Div: + if (m_subExpr2->getExprValue()->u.dval == 0.0) + return nullptr; + retval->u.dval + = m_subExpr1->getExprValue()->u.dval / m_subExpr2->getExprValue()->u.dval; + break; + default: + return nullptr; + } + + return retval; +} + +std::unique_ptr<AstExprValue> AstExpression::eval_bit_op() +{ + if (m_subExpr1 == nullptr || m_subExpr2 == nullptr) + return nullptr; + m_subExpr1->evaluate(); + if (m_subExpr1->getExprValue() == nullptr) + return nullptr; + if (!m_subExpr1->coerce(ET_long)) + return nullptr; + m_subExpr2->evaluate(); + if (m_subExpr2->getExprValue() == nullptr) + return nullptr; + if (!m_subExpr2->coerce(ET_long)) + return nullptr; + + std::unique_ptr<AstExprValue> retval(new AstExprValue); + retval->et = ET_long; + + switch (m_combOperator) + { + case ExprComb::Or: + retval->u.lval + = m_subExpr1->getExprValue()->u.lval | m_subExpr2->getExprValue()->u.lval; + break; + case ExprComb::Xor: + retval->u.lval + = m_subExpr1->getExprValue()->u.lval ^ m_subExpr2->getExprValue()->u.lval; + break; + case ExprComb::And: + retval->u.lval + = m_subExpr1->getExprValue()->u.lval & m_subExpr2->getExprValue()->u.lval; + break; + case ExprComb::Left: + retval->u.lval = m_subExpr1->getExprValue()->u.lval + << m_subExpr2->getExprValue()->u.lval; + break; + case ExprComb::Right: + retval->u.lval + = m_subExpr1->getExprValue()->u.lval >> m_subExpr2->getExprValue()->u.lval; + break; + default: + return nullptr; + } + + return retval; +} + +std::unique_ptr<AstExprValue> AstExpression::eval_un_op() +{ + if (m_subExpr1 == nullptr) + return nullptr; + m_subExpr1->evaluate(); + if (m_subExpr1->getExprValue() == nullptr) + return nullptr; + if (!m_subExpr1->coerce(ET_double)) + return nullptr; + + std::unique_ptr<AstExprValue> retval(new AstExprValue); + retval->et = ET_double; + + switch (m_combOperator) + { + case ExprComb::UPlus: + retval->u.lval = m_subExpr1->getExprValue()->u.lval; + break; + case ExprComb::UMinus: + retval->u.lval = -(m_subExpr1->getExprValue()->u.lval); + break; + default: + return nullptr; + } + + return retval; +} + +std::unique_ptr<AstExprValue> AstExpression::eval_symbol() +{ + AstScope* pScope = nullptr; + AstDeclaration* pDecl; + AstConstant* pConst; + + /* + * Is there a symbol stored? + */ + if (!m_xSymbolicName) + { + ErrorHandler::evalError(this); + return nullptr; + } + /* + * Get current scope for lookup + */ + if (idlc()->scopes()->depth() > 0) + pScope = idlc()->scopes()->topNonNull(); + if (!pScope) + { + ErrorHandler::lookupError(*m_xSymbolicName); + return nullptr; + } + /* + * Do lookup + */ + pDecl = pScope->lookupByName(*m_xSymbolicName); + if (pDecl == nullptr) + { + ErrorHandler::lookupError(*m_xSymbolicName); + return nullptr; + } + /* + * Is it a constant? + */ + if (pDecl->getNodeType() != NT_const && pDecl->getNodeType() != NT_enum_val) + { + ErrorHandler::constantExpected(pDecl, *m_xSymbolicName); + return nullptr; + } + if (!ErrorHandler::checkPublished(pDecl)) + { + return nullptr; + } + /* + * OK, now evaluate the constant we just got, to produce its value + */ + pConst = static_cast<AstConstant*>(pDecl); + pConst->getConstValue()->evaluate(); + auto const val = pConst->getConstValue()->getExprValue(); + return val == nullptr ? nullptr : std::make_unique<AstExprValue>(*val); +} + +OString AstExpression::toString() +{ + OString exprStr; + if (m_combOperator == ExprComb::Symbol) + return m_xSymbolicName ? *m_xSymbolicName : OString("<Undefined Name>"); + + if (m_exprValue) + { + switch (m_exprValue->et) + { + case ET_short: + return OString::number(m_exprValue->u.sval); + case ET_ushort: + return OString::number(m_exprValue->u.usval); + case ET_long: + return OString::number(m_exprValue->u.lval); + case ET_ulong: + return OString::number(m_exprValue->u.ulval); + case ET_hyper: + return OString::number(m_exprValue->u.hval); + case ET_uhyper: + return OString::number(m_exprValue->u.uhval); + case ET_float: + return OString::number(m_exprValue->u.fval); + case ET_double: + return OString::number(m_exprValue->u.dval); + case ET_byte: + return OString::number(m_exprValue->u.byval); + case ET_boolean: + if (m_exprValue->u.lval == 0) + return "FALSE"; + else + return "TRUE"; + default: + OSL_ASSERT(false); + return OString(); + } + } + + switch (m_combOperator) + { + case ExprComb::UPlus: + exprStr += "+"; + break; + case ExprComb::UMinus: + exprStr += "-"; + break; + default: + break; + } + if (m_subExpr1) + exprStr += m_subExpr1->toString(); + switch (m_combOperator) + { + case ExprComb::Add: + exprStr += " + "; + break; + case ExprComb::Minus: + exprStr += " - "; + break; + case ExprComb::Mul: + exprStr += " * "; + break; + case ExprComb::Div: + exprStr += " / "; + break; + case ExprComb::Mod: + exprStr += " % "; + break; + case ExprComb::Or: + exprStr += " | "; + break; + case ExprComb::Xor: + exprStr += " ^ "; + break; + case ExprComb::And: + exprStr += " & "; + break; + case ExprComb::Left: + exprStr += " << "; + break; + case ExprComb::Right: + exprStr += " >> "; + break; + default: + break; + } + + if (m_subExpr2) + exprStr += m_subExpr2->toString(); + + return exprStr; +} + +// Convert the type of an AST_Expression to a char * +const char* exprTypeToString(ExprType t) +{ + switch (t) + { + case ET_short: + return "short"; + case ET_ushort: + return "unsigned short"; + case ET_long: + return "long"; + case ET_ulong: + return "unsigned long"; + case ET_hyper: + return "hyper"; + case ET_uhyper: + return "unsigned hyper"; + case ET_float: + return "float"; + case ET_double: + return "double"; + case ET_char: + return "char"; + case ET_byte: + return "byte"; + case ET_boolean: + return "boolean"; + case ET_string: + return "string"; + case ET_any: + return "any"; + case ET_type: + return "type"; + case ET_void: + return "void"; + case ET_none: + return "none"; + } + + return "unknown"; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/source/astinterface.cxx b/idlc/source/astinterface.cxx new file mode 100644 index 000000000..50e24d1fd --- /dev/null +++ b/idlc/source/astinterface.cxx @@ -0,0 +1,399 @@ +/* -*- 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 <astinterface.hxx> +#include <astattribute.hxx> +#include <astoperation.hxx> +#include <idlc.hxx> + +#include <registry/version.h> +#include <registry/writer.hxx> + +#include <osl/diagnose.h> + +AstInterface::AstInterface(const OString& name, + AstInterface const * pInherits, + AstScope* pScope) + : AstType(NT_interface, name, pScope) + , AstScope(NT_interface) + , m_mandatoryInterfaces(0) + , m_bIsDefined(false) + , m_bSingleInheritance(pInherits != nullptr) +{ + if (pInherits != nullptr) { + addInheritedInterface(pInherits, false, OUString()); + } +} + +AstInterface::~AstInterface() +{ +} + +AstInterface::DoubleDeclarations AstInterface::checkInheritedInterfaceClashes( + AstInterface const * ifc, bool optional) const +{ + DoubleDeclarations doubleDecls; + std::set< OString > seen; + checkInheritedInterfaceClashes( + doubleDecls, seen, ifc, true, optional, optional); + return doubleDecls; +} + +void AstInterface::addInheritedInterface( + AstType const * ifc, bool optional, OUString const & documentation) +{ + m_inheritedInterfaces.emplace_back(ifc, optional, documentation); + if (!optional) { + ++m_mandatoryInterfaces; + } + AstInterface const * resolved = resolveInterfaceTypedefs(ifc); + addVisibleInterface(resolved, true, optional); + if (optional) { + addOptionalVisibleMembers(resolved); + } +} + +AstInterface::DoubleMemberDeclarations AstInterface::checkMemberClashes( + AstDeclaration const * member) const +{ + DoubleMemberDeclarations doubleMembers; + checkMemberClashes(doubleMembers, member, true); + return doubleMembers; +} + +void AstInterface::addMember(AstDeclaration /*TODO: const*/ * member) { + addDeclaration(member); + m_visibleMembers.emplace(member->getLocalName(), VisibleMember(member)); +} + +void AstInterface::forwardDefined(AstInterface const & def) +{ + setImported(def.isImported()); + setInMainfile(def.isInMainfile()); + setLineNumber(def.getLineNumber()); + setFileName(def.getFileName()); + setDocumentation(def.getDocumentation()); + m_inheritedInterfaces = def.m_inheritedInterfaces; + m_mandatoryInterfaces = def.m_mandatoryInterfaces; + m_bIsDefined = true; +} + +bool AstInterface::dump(RegistryKey& rKey) +{ + if ( !isDefined() ) + return true; + + RegistryKey localKey; + if (rKey.createKey( OStringToOUString(getFullName(), RTL_TEXTENCODING_UTF8 ), localKey) != RegError::NO_ERROR) + { + fprintf(stderr, "%s: warning, could not create key '%s' in '%s'\n", + idlc()->getOptions()->getProgramName().getStr(), + getFullName().getStr(), OUStringToOString(rKey.getRegistryName(), RTL_TEXTENCODING_UTF8).getStr()); + return false; + } + + if (m_mandatoryInterfaces > SAL_MAX_UINT16 + || m_inheritedInterfaces.size() - m_mandatoryInterfaces + > SAL_MAX_UINT16) + { + fprintf( + stderr, "%s: interface %s has too many direct base interfaces\n", + idlc()->getOptions()->getProgramName().getStr(), + getScopedName().getStr()); + return false; + } + sal_uInt16 nBaseTypes = static_cast< sal_uInt16 >(m_mandatoryInterfaces); + sal_uInt16 nAttributes = 0; + sal_uInt16 nMethods = 0; + sal_uInt16 nReferences = static_cast< sal_uInt16 >( + m_inheritedInterfaces.size() - m_mandatoryInterfaces); + typereg_Version version + = (nBaseTypes <= 1 && nReferences == 0 && !m_bPublished + ? TYPEREG_VERSION_0 : TYPEREG_VERSION_1); + for (DeclList::const_iterator i(getIteratorBegin()); i != getIteratorEnd(); + ++i) + { + switch ((*i)->getNodeType()) { + case NT_attribute: + { + if (!increment(&nAttributes, "attributes")) { + return false; + } + AstAttribute * attr = static_cast<AstAttribute *>(*i); + if (attr->isBound()) { + version = TYPEREG_VERSION_1; + } + DeclList::size_type getCount = attr->getGetExceptionCount(); + if (getCount > SAL_MAX_UINT16) { + fprintf( + stderr, + ("%s: raises clause of getter for attribute %s of" + " interface %s is too long\n"), + idlc()->getOptions()->getProgramName().getStr(), + (*i)->getLocalName().getStr(), + getScopedName().getStr()); + return false; + } + if (getCount > 0) { + version = TYPEREG_VERSION_1; + if (!increment(&nMethods, "attributes")) { + return false; + } + } + DeclList::size_type setCount = attr->getSetExceptionCount(); + if (setCount > SAL_MAX_UINT16) { + fprintf( + stderr, + ("%s: raises clause of setter for attribute %s of" + " interface %s is too long\n"), + idlc()->getOptions()->getProgramName().getStr(), + (*i)->getLocalName().getStr(), + getScopedName().getStr()); + return false; + } + if (setCount > 0) { + version = TYPEREG_VERSION_1; + if (!increment(&nMethods, "attributes")) { + return false; + } + } + break; + } + + case NT_operation: + if (!increment(&nMethods, "methods")) { + return false; + } + break; + + default: + OSL_ASSERT(false); + break; + } + } + + typereg::Writer aBlob( + version, getDocumentation(), "", RT_TYPE_INTERFACE, m_bPublished, + OStringToOUString(getRelativName(), RTL_TEXTENCODING_UTF8), nBaseTypes, + nAttributes, nMethods, nReferences); + + sal_uInt16 superTypeIndex = 0; + sal_uInt16 referenceIndex = 0; + for (auto const& elem : m_inheritedInterfaces) + { + if (elem.isOptional()) { + aBlob.setReferenceData( + referenceIndex++, elem.getDocumentation(), RTReferenceType::SUPPORTS, + RTFieldAccess::OPTIONAL, + OStringToOUString( + elem.getInterface()->getRelativName(), + RTL_TEXTENCODING_UTF8)); + } else { + aBlob.setSuperTypeName( + superTypeIndex++, + OStringToOUString( + elem.getInterface()->getRelativName(), + RTL_TEXTENCODING_UTF8)); + } + } + + sal_uInt16 attributeIndex = 0; + sal_uInt16 methodIndex = 0; + for (DeclList::const_iterator i(getIteratorBegin()); i != getIteratorEnd(); + ++i) + { + switch ((*i)->getNodeType()) { + case NT_attribute: + static_cast<AstAttribute *>(*i)->dumpBlob( + aBlob, attributeIndex++, &methodIndex); + break; + + case NT_operation: + static_cast<AstOperation *>(*i)->dumpBlob(aBlob, methodIndex++); + break; + + default: + OSL_ASSERT(false); + break; + } + } + + sal_uInt32 aBlobSize; + void const * pBlob = aBlob.getBlob(&aBlobSize); + + if (localKey.setValue("", RegValueType::BINARY, const_cast<RegValue>(pBlob), aBlobSize) != RegError::NO_ERROR) + { + fprintf(stderr, "%s: warning, could not set value of key \"%s\" in %s\n", + idlc()->getOptions()->getProgramName().getStr(), + getFullName().getStr(), OUStringToOString(localKey.getRegistryName(), RTL_TEXTENCODING_UTF8).getStr()); + return false; + } + + return true; +} + +void AstInterface::checkInheritedInterfaceClashes( + DoubleDeclarations & doubleDeclarations, + std::set< OString > & seenInterfaces, AstInterface const * ifc, + bool direct, bool optional, bool mainOptional) const +{ + if (!(direct || optional + || seenInterfaces.insert(ifc->getScopedName()).second)) + return; + + VisibleInterfaces::const_iterator visible( + m_visibleInterfaces.find(ifc->getScopedName())); + if (visible != m_visibleInterfaces.end()) { + switch (visible->second) { + case INTERFACE_INDIRECT_OPTIONAL: + if (direct && optional) { + doubleDeclarations.interfaces.push_back(ifc); + return; + } + break; + + case INTERFACE_DIRECT_OPTIONAL: + if (direct || !mainOptional) { + doubleDeclarations.interfaces.push_back(ifc); + } + return; + + case INTERFACE_INDIRECT_MANDATORY: + if (direct) { + doubleDeclarations.interfaces.push_back(ifc); + } + return; + + case INTERFACE_DIRECT_MANDATORY: + if (direct || (!optional && !mainOptional)) { + doubleDeclarations.interfaces.push_back(ifc); + } + return; + } + } + if (!direct && optional) + return; + + for (DeclList::const_iterator i(ifc->getIteratorBegin()); + i != ifc->getIteratorEnd(); ++i) + { + checkMemberClashes( + doubleDeclarations.members, *i, !mainOptional); + } + for (auto const& elem : ifc->m_inheritedInterfaces) + { + checkInheritedInterfaceClashes( + doubleDeclarations, seenInterfaces, elem.getResolved(), + false, elem.isOptional(), mainOptional); + } +} + +void AstInterface::checkMemberClashes( + DoubleMemberDeclarations & doubleMembers, AstDeclaration const * member, + bool checkOptional) const +{ + VisibleMembers::const_iterator i( + m_visibleMembers.find(member->getLocalName())); + if (i == m_visibleMembers.end()) + return; + + if (i->second.mandatory != nullptr) { + if (i->second.mandatory->getScopedName() != member->getScopedName()) + { + DoubleMemberDeclaration d; + d.first = i->second.mandatory; + d.second = member; + doubleMembers.push_back(d); + } + } else if (checkOptional) { + for (auto const& elem : i->second.optionals) + { + if (elem.second->getScopedName() != member->getScopedName()) { + DoubleMemberDeclaration d; + d.first = elem.second; + d.second = member; + doubleMembers.push_back(d); + } + } + } +} + +void AstInterface::addVisibleInterface( + AstInterface const * ifc, bool direct, bool optional) +{ + InterfaceKind kind = optional + ? direct ? INTERFACE_DIRECT_OPTIONAL : INTERFACE_INDIRECT_OPTIONAL + : direct ? INTERFACE_DIRECT_MANDATORY : INTERFACE_INDIRECT_MANDATORY; + std::pair< VisibleInterfaces::iterator, bool > result( + m_visibleInterfaces.emplace(ifc->getScopedName(), kind)); + bool seen = !result.second + && result.first->second >= INTERFACE_INDIRECT_MANDATORY; + if (!result.second && kind > result.first->second) { + result.first->second = kind; + } + if (optional || seen) + return; + + for (DeclList::const_iterator i(ifc->getIteratorBegin()); + i != ifc->getIteratorEnd(); ++i) + { + m_visibleMembers.emplace( + (*i)->getLocalName(), VisibleMember(*i)); + } + for (auto const& elem : ifc->m_inheritedInterfaces) + { + addVisibleInterface(elem.getResolved(), false, elem.isOptional()); + } +} + +void AstInterface::addOptionalVisibleMembers(AstInterface const * ifc) { + for (DeclList::const_iterator i(ifc->getIteratorBegin()); + i != ifc->getIteratorEnd(); ++i) + { + VisibleMembers::iterator visible( + m_visibleMembers.find((*i)->getLocalName())); + if (visible == m_visibleMembers.end()) { + visible = m_visibleMembers.emplace( + (*i)->getLocalName(), VisibleMember()).first; + } + if (visible->second.mandatory == nullptr) { + visible->second.optionals.emplace(ifc->getScopedName(), *i); + } + } + for (auto const& elem : ifc->m_inheritedInterfaces) + { + if (!elem.isOptional()) { + addOptionalVisibleMembers(elem.getResolved()); + } + } +} + +bool AstInterface::increment(sal_uInt16 * counter, char const * sort) const { + if (*counter == SAL_MAX_UINT16) { + fprintf( + stderr, "%s: interface %s has too many direct %s\n", + idlc()->getOptions()->getProgramName().getStr(), + getScopedName().getStr(), sort); + return false; + } + ++*counter; + return true; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/source/astoperation.cxx b/idlc/source/astoperation.cxx new file mode 100644 index 000000000..4dea37576 --- /dev/null +++ b/idlc/source/astoperation.cxx @@ -0,0 +1,115 @@ +/* -*- 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 <astoperation.hxx> +#include <asttype.hxx> +#include <astbasetype.hxx> +#include <astparameter.hxx> +#include <errorhandler.hxx> + +#include <registry/writer.hxx> + +void AstOperation::setExceptions(DeclList const * pExceptions) +{ + if (pExceptions != nullptr) { + m_exceptions = *pExceptions; + } +} + +bool AstOperation::isVariadic() const { + DeclList::const_iterator i(getIteratorEnd()); + return i != getIteratorBegin() + && static_cast< AstParameter const * >(*(--i))->isRest(); +} + +void AstOperation::dumpBlob(typereg::Writer & rBlob, sal_uInt16 index) +{ + sal_uInt16 nParam = getNodeCount(NT_parameter); + sal_uInt16 nExcep = static_cast<sal_uInt16>(m_exceptions.size()); + + OUString returnTypeName; + if (m_pReturnType == nullptr) { + returnTypeName = "void"; + } else { + returnTypeName = OStringToOUString( + m_pReturnType->getRelativName(), RTL_TEXTENCODING_UTF8); + } + rBlob.setMethodData( + index, getDocumentation(), RTMethodMode::TWOWAY, + OStringToOUString(getLocalName(), RTL_TEXTENCODING_UTF8), + returnTypeName, nParam, nExcep); + + if ( nParam ) + { + DeclList::const_iterator iter = getIteratorBegin(); + DeclList::const_iterator end = getIteratorEnd(); + RTParamMode paramMode; + sal_uInt16 paramIndex = 0; + while ( iter != end ) + { + AstDeclaration* pDecl = *iter; + if ( pDecl->getNodeType() == NT_parameter ) + { + AstParameter* pParam = static_cast<AstParameter*>(pDecl); + switch (pParam->getDirection()) + { + case DIR_IN : + paramMode = RT_PARAM_IN; + break; + case DIR_OUT : + paramMode = RT_PARAM_OUT; + break; + case DIR_INOUT : + paramMode = RT_PARAM_INOUT; + break; + default: + paramMode = RT_PARAM_INVALID; + break; + } + if (pParam->isRest()) { + paramMode = static_cast< RTParamMode >( + paramMode | RT_PARAM_REST); + } + + rBlob.setMethodParameterData( + index, paramIndex++, paramMode, + OStringToOUString( + pDecl->getLocalName(), RTL_TEXTENCODING_UTF8), + OStringToOUString( + pParam->getType()->getRelativName(), + RTL_TEXTENCODING_UTF8)); + } + ++iter; + } + } + + if ( nExcep ) + { + sal_uInt16 exceptIndex = 0; + for (auto const& exception : m_exceptions) + { + rBlob.setMethodExceptionTypeName( + index, exceptIndex++, + OStringToOUString( + exception->getRelativName(), RTL_TEXTENCODING_UTF8)); + } + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/source/astscope.cxx b/idlc/source/astscope.cxx new file mode 100644 index 000000000..f8309a766 --- /dev/null +++ b/idlc/source/astscope.cxx @@ -0,0 +1,314 @@ +/* -*- 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 <string_view> + +#include <astscope.hxx> +#include <astbasetype.hxx> +#include <astinterface.hxx> +#include <errorhandler.hxx> +#include <o3tl/string_view.hxx> +#include <osl/diagnose.h> + + +static bool isGlobal(std::string_view scopedName) +{ + return scopedName.empty() || o3tl::starts_with(scopedName, ":"); +} + +AstScope::AstScope(NodeType nodeType) + : m_nodeType(nodeType) +{ + +} + +AstScope::~AstScope() +{ + +} + +AstDeclaration* AstScope::addDeclaration(AstDeclaration* pDecl) +{ + AstDeclaration* pDeclaration = nullptr; + + if ((pDeclaration = lookupForAdd(pDecl)) != nullptr) + { + if ( pDecl->hasAncestor(pDeclaration) ) + { + ErrorHandler::error2(ErrorCode::RedefScope, pDecl, pDeclaration); + return nullptr; + } + if ( (pDecl->getNodeType() == pDeclaration->getNodeType()) && + (pDecl->getNodeType() == NT_sequence + || pDecl->getNodeType() == NT_instantiated_struct) ) + { + return pDeclaration; + } + if ( (pDeclaration->getNodeType() == NT_interface) + && (pDecl->getNodeType() == NT_interface) + && !(static_cast<AstInterface*>(pDeclaration)->isDefined()) ) + { + m_declarations.push_back(pDecl); + return pDecl; + } + if ( (NT_service == m_nodeType) && + ( ((pDecl->getNodeType() == NT_interface_member) + && (pDeclaration->getNodeType() == NT_interface)) || + ((pDecl->getNodeType() == NT_service_member) + && (pDeclaration->getNodeType() == NT_service)) ) + ) + { + m_declarations.push_back(pDecl); + return pDecl; + } + + ErrorHandler::error2(ErrorCode::RedefScope, scopeAsDecl(this), pDecl); + return nullptr; + } + + m_declarations.push_back(pDecl); + return pDecl; +} + +sal_uInt16 AstScope::getNodeCount(NodeType nodeType) const +{ + return static_cast<sal_uInt16>(std::count_if(getIteratorBegin(), getIteratorEnd(), + [&nodeType](const AstDeclaration* pDecl) { return pDecl->getNodeType() == nodeType; })); +} + +AstDeclaration* AstScope::lookupByName(const OString& scopedName) +{ + AstDeclaration* pDecl = nullptr; + AstScope* pScope = nullptr; + if (scopedName.isEmpty()) + return nullptr; + + // If name starts with "::" start look up in global scope + if ( isGlobal(scopedName) ) + { + pDecl = scopeAsDecl(this); + if ( !pDecl ) + return nullptr; + + pScope = pDecl->getScope(); + // If this is the global scope ... + if ( !pScope ) + { + // look up the scopedName part after "::" + OString subName = scopedName.copy(2); + pDecl = lookupByName(subName); + return pDecl; + //return pScope->lookupByName(); + } + // OK, not global scope yet, so simply iterate with parent scope + pDecl = pScope->lookupByName(scopedName); + return pDecl; + } + + // The name does not start with "::" + // Look up in the local scope and start with the first scope + sal_Int32 nIndex = scopedName.indexOf(':'); + OString firstScope = nIndex > 0 ? scopedName.copy(0, nIndex) : scopedName; + bool bFindFirstScope = true; + pDecl = lookupByNameLocal(firstScope); + if ( !pDecl ) + { + bFindFirstScope = false; + + // OK, not found. Go down parent scope chain + pDecl = scopeAsDecl(this); + if ( pDecl ) + { + pScope = pDecl->getScope(); + if ( pScope ) + pDecl = pScope->lookupByName(scopedName); + else + pDecl = nullptr; + + // Special case for scope which is an interface. We + // have to look in the inherited interfaces as well. + if ( !pDecl && m_nodeType == NT_interface ) + pDecl = lookupInInherited(scopedName); + } + } + + if ( !bFindFirstScope || (firstScope == scopedName) ) + return pDecl; + + sal_Int32 i = 0; + sal_Int32 nOffset = 2; + do + { + pScope = declAsScope(pDecl); + if( pScope ) + { + pDecl = pScope->lookupByNameLocal(o3tl::getToken(scopedName, nOffset, ':', i )); + nOffset = 1; + } + if( !pDecl ) + break; + } while( i != -1 ); + + if ( !pDecl ) + { + // last try if is not the global scope and the scopeName isn't specify global too + pDecl = scopeAsDecl(this); + if ( pDecl && !pDecl->getLocalName().isEmpty() ) + { + pScope = pDecl->getScope(); + if ( pScope ) + pDecl = pScope->lookupByName(scopedName); + } else + { + pDecl = nullptr; + } + } + + return pDecl; +} + +AstDeclaration* AstScope::lookupByNameLocal(std::string_view name) const +{ + for (auto const& declaration : m_declarations) + { + if ( declaration->getLocalName() == name ) + return declaration; + } + return nullptr; +} + +AstDeclaration* AstScope::lookupInInherited(const OString& scopedName) const +{ + const AstInterface* pInterface = dynamic_cast<const AstInterface*>(this); + + if ( !pInterface ) + return nullptr; + + // Can't look in an interface which was not yet defined + if ( !pInterface->getScope() ) + { + ErrorHandler::forwardLookupError(pInterface, scopedName); + } + + // OK, loop through inherited interfaces. Stop when you find it + for (auto const& elem : pInterface->getAllInheritedInterfaces()) + { + AstInterface const * resolved = elem.getResolved(); + AstDeclaration* pDecl = resolved->lookupByNameLocal(scopedName); + if ( pDecl ) + return pDecl; + pDecl = resolved->lookupInInherited(scopedName); + if ( pDecl ) + return pDecl; + } + // Not found + return nullptr; +} + +AstDeclaration* AstScope::lookupPrimitiveType(ExprType type) +{ + AstDeclaration* pDecl = nullptr; + AstScope* pScope = nullptr; + OString typeName; + pDecl = scopeAsDecl(this); + if ( !pDecl ) + return nullptr; + pScope = pDecl->getScope(); + if ( pScope) + return pScope->lookupPrimitiveType(type); + + switch (type) + { + case ET_none: + OSL_ASSERT(false); + break; + case ET_short: + typeName = OString("short"); + break; + case ET_ushort: + typeName = OString("unsigned short"); + break; + case ET_long: + typeName = OString("long"); + break; + case ET_ulong: + typeName = OString("unsigned long"); + break; + case ET_hyper: + typeName = OString("hyper"); + break; + case ET_uhyper: + typeName = OString("unsigned hyper"); + break; + case ET_float: + typeName = OString("float"); + break; + case ET_double: + typeName = OString("double"); + break; + case ET_char: + typeName = OString("char"); + break; + case ET_byte: + typeName = OString("byte"); + break; + case ET_boolean: + typeName = OString("boolean"); + break; + case ET_any: + typeName = OString("any"); + break; + case ET_void: + typeName = OString("void"); + break; + case ET_type: + typeName = OString("type"); + break; + case ET_string: + typeName = OString("string"); + break; + } + + pDecl = lookupByNameLocal(typeName); + + if ( pDecl && (pDecl->getNodeType() == NT_predefined) ) + { + AstBaseType* pBaseType = static_cast<AstBaseType*>(pDecl); + + if ( pBaseType->getExprType() == type ) + return pDecl; + } + + return nullptr; +} + +AstDeclaration* AstScope::lookupForAdd(AstDeclaration const * pDecl) const +{ + if ( !pDecl ) + return nullptr; + + AstDeclaration* pRetDecl = lookupByNameLocal(pDecl->getLocalName()); + + return pRetDecl; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/source/astservice.cxx b/idlc/source/astservice.cxx new file mode 100644 index 000000000..c90ded6b4 --- /dev/null +++ b/idlc/source/astservice.cxx @@ -0,0 +1,54 @@ +/* -*- 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 <astmember.hxx> +#include <astoperation.hxx> +#include <astservice.hxx> +#include <asttype.hxx> + +bool AstService::checkLastConstructor() const { + AstOperation const * last = static_cast< AstOperation const * >(getLast()); + for (DeclList::const_iterator i(getIteratorBegin()); i != getIteratorEnd(); + ++i) + { + if (*i != last && (*i)->getNodeType() == NT_operation) { + AstOperation const * ctor = static_cast< AstOperation * >(*i); + if (ctor->isVariadic() && last->isVariadic()) { + return true; + } + sal_uInt32 n = ctor->nMembers(); + if (n == last->nMembers()) { + return std::equal(ctor->getIteratorBegin(), ctor->getIteratorEnd(), last->getIteratorBegin(), + [](AstDeclaration* a, AstDeclaration* b) { + sal_Int32 r1; + AstDeclaration const * t1 = deconstructAndResolveTypedefs(static_cast< AstMember * >(a)->getType(), &r1); + sal_Int32 r2; + AstDeclaration const * t2 = deconstructAndResolveTypedefs(static_cast< AstMember * >(b)->getType(), &r2); + return r1 == r2 && t1->getScopedName() == t2->getScopedName(); + }); + } + } + } + return false; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/source/aststack.cxx b/idlc/source/aststack.cxx new file mode 100644 index 000000000..fcddc810d --- /dev/null +++ b/idlc/source/aststack.cxx @@ -0,0 +1,79 @@ +/* -*- 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 <rtl/alloc.h> +#include <aststack.hxx> +#include <astscope.hxx> + +AstStack::AstStack() {} + +AstStack::~AstStack() +{ + for (AstScope* p : m_stack) + delete p; +} + +AstScope* AstStack::top() +{ + if (m_stack.empty()) + return nullptr; + return m_stack.back(); +} + +AstScope* AstStack::bottom() +{ + if (m_stack.empty()) + return nullptr; + return m_stack.front(); +} + +AstScope* AstStack::nextToTop() +{ + if (m_stack.size() < 2) + return nullptr; + + return m_stack[m_stack.size() - 2]; +} + +AstScope* AstStack::topNonNull() +{ + for (sal_uInt32 i = m_stack.size(); i > 0; i--) + { + if (m_stack[i - 1]) + return m_stack[i - 1]; + } + return nullptr; +} + +AstStack* AstStack::push(AstScope* pScope) +{ + m_stack.push_back(pScope); + return this; +} + +void AstStack::pop() +{ + if (m_stack.empty()) + return; + m_stack.pop_back(); +} + +void AstStack::clear() { m_stack.clear(); } + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/source/aststruct.cxx b/idlc/source/aststruct.cxx new file mode 100644 index 000000000..00ac33021 --- /dev/null +++ b/idlc/source/aststruct.cxx @@ -0,0 +1,167 @@ +/* -*- 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 <aststruct.hxx> +#include <astmember.hxx> + +#include <registry/version.h> +#include <registry/writer.hxx> + +AstStruct::AstStruct( + const OString& name, std::vector< OString > const & typeParameters, + AstStruct const* pBaseType, AstScope* pScope) + : AstType(NT_struct, name, pScope) + , AstScope(NT_struct) + , m_pBaseType(pBaseType) +{ + for (auto const& elem : typeParameters) + { + m_typeParameters.emplace_back( + new AstType(NT_type_parameter, elem, nullptr)); + } +} + +AstStruct::AstStruct(const NodeType type, + const OString& name, + AstStruct const* pBaseType, + AstScope* pScope) + : AstType(type, name, pScope) + , AstScope(type) + , m_pBaseType(pBaseType) +{ +} + +AstStruct::~AstStruct() +{ +} + +AstDeclaration const * AstStruct::findTypeParameter(std::string_view name) + const +{ + for (auto const& elem : m_typeParameters) + { + if (elem->getLocalName() == name) { + return elem.get(); + } + } + return nullptr; +} + +bool AstStruct::isType() const { + return getNodeType() == NT_struct + ? getTypeParameterCount() == 0 : AstDeclaration::isType(); +} + +bool AstStruct::dump(RegistryKey& rKey) +{ + RegistryKey localKey; + if (rKey.createKey( OStringToOUString(getFullName(), RTL_TEXTENCODING_UTF8 ), localKey) != RegError::NO_ERROR) + { + fprintf(stderr, "%s: warning, could not create key '%s' in '%s'\n", + idlc()->getOptions()->getProgramName().getStr(), + getFullName().getStr(), OUStringToOString(rKey.getRegistryName(), RTL_TEXTENCODING_UTF8).getStr()); + return false; + } + + if (m_typeParameters.size() > SAL_MAX_UINT16) { + fprintf( + stderr, + ("%s: polymorphic struct type template %s has too many type" + " parameters\n"), + idlc()->getOptions()->getProgramName().getStr(), + getScopedName().getStr()); + return false; + } + + sal_uInt16 nMember = getNodeCount(NT_member); + + RTTypeClass typeClass = RT_TYPE_STRUCT; + if ( getNodeType() == NT_exception ) + typeClass = RT_TYPE_EXCEPTION; + + typereg::Writer aBlob( + (m_typeParameters.empty() && !m_bPublished + ? TYPEREG_VERSION_0 : TYPEREG_VERSION_1), + getDocumentation(), "", typeClass, m_bPublished, + OStringToOUString(getRelativName(), RTL_TEXTENCODING_UTF8), + m_pBaseType == nullptr ? 0 : 1, nMember, 0, + static_cast< sal_uInt16 >(m_typeParameters.size())); + if (m_pBaseType != nullptr) { + aBlob.setSuperTypeName( + 0, + OStringToOUString( + m_pBaseType->getRelativName(), RTL_TEXTENCODING_UTF8)); + } + + if ( nMember > 0 ) + { + DeclList::const_iterator iter = getIteratorBegin(); + DeclList::const_iterator end = getIteratorEnd(); + AstMember* pMember = nullptr; + sal_uInt16 index = 0; + while ( iter != end ) + { + AstDeclaration* pDecl = *iter; + if ( pDecl->getNodeType() == NT_member ) + { + pMember = static_cast<AstMember*>(pDecl); + RTFieldAccess flags = RTFieldAccess::READWRITE; + OString typeName; + if (pMember->getType()->getNodeType() == NT_type_parameter) { + flags |= RTFieldAccess::PARAMETERIZED_TYPE; + typeName = pMember->getType()->getLocalName(); + } else { + typeName = pMember->getType()->getRelativName(); + } + aBlob.setFieldData( + index++, pMember->getDocumentation(), "", flags, + OStringToOUString( + pMember->getLocalName(), RTL_TEXTENCODING_UTF8), + OStringToOUString(typeName, RTL_TEXTENCODING_UTF8), + RTConstValue()); + } + ++iter; + } + } + + sal_uInt16 index = 0; + for (auto const& elem : m_typeParameters) + { + aBlob.setReferenceData( + index++, "", RTReferenceType::TYPE_PARAMETER, RTFieldAccess::INVALID, + OStringToOUString( + elem->getLocalName(), RTL_TEXTENCODING_UTF8)); + } + + sal_uInt32 aBlobSize; + void const * pBlob = aBlob.getBlob(&aBlobSize); + + if (localKey.setValue("", RegValueType::BINARY, + const_cast<RegValue>(pBlob), aBlobSize) != RegError::NO_ERROR) + { + fprintf(stderr, "%s: warning, could not set value of key \"%s\" in %s\n", + idlc()->getOptions()->getProgramName().getStr(), + getFullName().getStr(), OUStringToOString(localKey.getRegistryName(), RTL_TEXTENCODING_UTF8).getStr()); + return false; + } + + return true; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/source/aststructinstance.cxx b/idlc/source/aststructinstance.cxx new file mode 100644 index 000000000..878745793 --- /dev/null +++ b/idlc/source/aststructinstance.cxx @@ -0,0 +1,63 @@ +/* -*- 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 <aststructinstance.hxx> + +#include <asttype.hxx> +#include <idlctypes.hxx> + +#include <rtl/strbuf.hxx> +#include <rtl/string.hxx> + +namespace { + +OString createName( + AstType const * typeTemplate, DeclList const * typeArguments) +{ + OStringBuffer buf(64); + buf.append(typeTemplate->getScopedName()); + if (typeArguments != nullptr) { + buf.append('<'); + for (DeclList::const_iterator i(typeArguments->begin()); + i != typeArguments->end(); ++i) + { + if (i != typeArguments->begin()) { + buf.append(','); + } + if (*i != nullptr) { + buf.append((*i)->getScopedName()); + } + } + buf.append('>'); + } + return buf.makeStringAndClear(); +} + +} + +AstStructInstance::AstStructInstance( + AstType const * typeTemplate, DeclList const * typeArguments, + AstScope * scope): + AstType( + NT_instantiated_struct, createName(typeTemplate, typeArguments), scope), + m_typeTemplate(typeTemplate), m_typeArguments(*typeArguments) +{} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/source/attributeexceptions.hxx b/idlc/source/attributeexceptions.hxx new file mode 100644 index 000000000..82ce1cf19 --- /dev/null +++ b/idlc/source/attributeexceptions.hxx @@ -0,0 +1,38 @@ +/* -*- 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 . + */ + +#ifndef INCLUDED_IDLC_SOURCE_ATTRIBUTEEXCEPTIONS_HXX +#define INCLUDED_IDLC_SOURCE_ATTRIBUTEEXCEPTIONS_HXX + +#include <rtl/ustring.hxx> + +struct AttributeExceptions +{ + struct Part + { + OUString const* documentation; + DeclList const* exceptions; + }; + Part get; + Part set; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/source/errorhandler.cxx b/idlc/source/errorhandler.cxx new file mode 100644 index 000000000..aa2de56bc --- /dev/null +++ b/idlc/source/errorhandler.cxx @@ -0,0 +1,583 @@ +/* -*- 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 <errorhandler.hxx> +#include <astinterface.hxx> + +static const char* errorCodeToMessage(ErrorCode eCode) +{ + switch (eCode) + { + case ErrorCode::SyntaxError: + return ""; + case ErrorCode::RedefScope: + return "illegal redefinition in scope "; + case ErrorCode::CoercionFailure: + return "coercion failure "; + case ErrorCode::ScopeConflict: + return "definition scope is different than fwd declare scope, "; + case ErrorCode::IllegalAdd: + return "illegal add operation, "; + case ErrorCode::IllegalRaises: + return "non-exception type in raises(..) clause, "; + case ErrorCode::CantInherit: + return "cannot inherit "; + case ErrorCode::IdentNotFound: + return "error in lookup of symbol: "; + case ErrorCode::CannotInheritFromForward: + return ""; + case ErrorCode::ExpectedConstant: + return "constant expected: "; + case ErrorCode::Eval: + return "expression evaluation error: "; + case ErrorCode::ForwardDeclLookup: + return ""; + case ErrorCode::RecursiveType: + return "illegal recursive use of type: "; + case ErrorCode::NotAType: + return "specified symbol is not a type: "; + case ErrorCode::InterfaceMemberLookup: + return "error in lookup of symbol, expected interface is not defined and no forward exists: "; + case ErrorCode::ServiceMemberLookup: + return "error in lookup of symbol, expected service is not defined: "; + case ErrorCode::DefinedAttributeFlag: + return "flag is already set: "; + case ErrorCode::WrongAttributeKeyword: + return "keyword not allowed: "; + case ErrorCode::MissingAttributeKeyword: + return "missing keyword: "; + case ErrorCode::BadAttributeFlags: + return + "the 'attribute' flag is mandatory, and only the 'bound' and" + " 'readonly' optional flags are accepted: "; + case ErrorCode::ExpectedOptional: + return "only the 'optional' flag is accepted: "; + case ErrorCode::MixedInheritance: + return "interface inheritance declarations cannot appear in both an" + " interface's header and its body"; + case ErrorCode::DoubleInheritance: + return + "interface is (directly or indirectly) inherited more than once: "; + case ErrorCode::DoubleMember: + return + "member is (directly or indirectly) declared more than once: "; + case ErrorCode::ConstructorParameterNotIn: + return + "a service constructor parameter may not be an out or inout" + " parameter"; + case ErrorCode::ConstructorRestParameterNotFirst: + return + "no parameters may precede a rest parameter in a service" + " constructor"; + case ErrorCode::RestParameterNotLast: + return "no parameters may follow a rest parameter"; + case ErrorCode::RestParameterNotAny: + return "a rest parameter must be of type any"; + case ErrorCode::MethodHasRestParameter: + return "a rest parameter may not be used on an interface method"; + case ErrorCode::ReadOnlyAttributeSetExceptions: + return "a readonly attribute may not have a setter raises clause"; + case ErrorCode::UnsignedTypeArgument: + return "an unsigned type cannot be used as a type argument"; + case ErrorCode::WrongNumberOfTypeArguments: + return + "the number of given type arguments does not match the expected" + " number of type parameters"; + case ErrorCode::InstantiatedStructTypeTypedef: + return + "an instantiated polymorphic struct type cannot be used in a" + " typedef"; + case ErrorCode::IdenticalTypeParameters: + return "two type parameters have the same name"; + case ErrorCode::StructTypeTemplateWithBase: + return "a polymorphic struct type template may not have a base type"; + case ErrorCode::PublishedForward: + return + "a published forward declaration of an interface type cannot be" + " followed by an unpublished declaration of that type"; + case ErrorCode::PublishedusesUnpublished: + return + "an unpublished entity cannot be used in the declaration of a" + " published entity: "; + case ErrorCode::SimilarConstructors: + return "two constructors have identical lists of parameter types"; + } + return "unknown error"; +} + +static const char* warningCodeToMessage(WarningCode wCode) +{ + switch (wCode) + { + case WarningCode::WrongNamingConvention: + return "type or identifier doesn't fulfill the UNO naming convention: "; + } + return "unknown warning"; +} + +static const char* parseStateToMessage(ParseState state) +{ + switch (state) + { + case PS_NoState: + return "Statement can not be parsed"; + case PS_TypeDeclSeen: + return "Malformed type declaration"; + case PS_ConstantDeclSeen: + return "Malformed const declaration"; + case PS_ExceptionDeclSeen: + return "Malformed exception declaration"; + case PS_InterfaceDeclSeen: + return "Malformed interface declaration"; + case PS_ServiceDeclSeen: + return "Malformed service declaration"; + case PS_ModuleDeclSeen: + return "Malformed module declaration"; + case PS_AttributeDeclSeen: + return "Malformed attribute declaration"; + case PS_PropertyDeclSeen: + return "Malformed property declaration"; + case PS_OperationDeclSeen: + return "Malformed operation declaration"; + case PS_InterfaceInheritanceDeclSeen: + return "Malformed interface inheritance declaration"; + case PS_ConstantsDeclSeen: + return "Malformed constants declaration"; + case PS_ServiceSeen: + return "Missing service identifier following SERVICE keyword"; + case PS_ServiceIDSeen: + return "Missing '{' or illegal syntax following service identifier"; + case PS_ServiceSqSeen: + return "Illegal syntax following service '{' opener"; + case PS_ServiceBodySeen: + return "Illegal syntax following service '}' closer"; + case PS_ServiceMemberSeen: + return "Illegal syntax following service member declaration"; + case PS_ServiceIFHeadSeen: + return "Illegal syntax following header of an interface member"; + case PS_ServiceSHeadSeen: + return "Illegal syntax following header of a service member"; + case PS_ModuleSeen: + return "Missing module identifier following MODULE keyword"; + case PS_ModuleIDSeen: + return "Missing '{' or illegal syntax following module identifier"; + case PS_ModuleSqSeen: + return "Illegal syntax following module '{' opener"; + case PS_ModuleQsSeen: + return "Illegal syntax following module '}' closer"; + case PS_ModuleBodySeen: + return "Illegal syntax following module export(s)"; + case PS_ConstantsSeen: + return "Missing constants identifier following CONSTANTS keyword"; + case PS_ConstantsIDSeen: + return "Missing '{' or illegal syntax following constants identifier"; + case PS_ConstantsSqSeen: + return "Illegal syntax following module '{' opener"; + case PS_ConstantsQsSeen: + return "Illegal syntax following module '}' closer"; + case PS_ConstantsBodySeen: + return "Illegal syntax following constants export(s)"; + case PS_InterfaceSeen: + return "Missing interface identifier following INTERFACE keyword"; + case PS_InterfaceIDSeen: + return "Illegal syntax following interface identifier"; + case PS_InterfaceHeadSeen: + return "Illegal syntax following interface head"; + case PS_InheritSpecSeen: + return "Missing '{' or illegal syntax following inheritance spec"; + case PS_ForwardDeclSeen: + return "Missing ';' following forward interface declaration"; + case PS_InterfaceSqSeen: + return "Illegal syntax following interface '{' opener"; + case PS_InterfaceQsSeen: + return "Illegal syntax following interface '}' closer"; + case PS_InterfaceBodySeen: + return "Illegal syntax following interface export(s)"; + case PS_InheritColonSeen: + return "Illegal syntax following ':' starting inheritance list"; + case PS_SNListCommaSeen: + return "Found illegal scoped name in scoped name list"; + case PS_ScopedNameSeen: + return "Missing ',' following scoped name in scoped name list"; + case PS_SN_IDSeen: + return "Illegal component in scoped name"; + case PS_ScopeDelimSeen: + return "Illegal component in scoped name following '::'"; + case PS_ConstSeen: + return "Missing type or illegal syntax following CONST keyword"; + case PS_ConstTypeSeen: + return "Missing identifier or illegal syntax following const type"; + case PS_ConstIDSeen: + return "Missing '=' or illegal syntax after const identifier"; + case PS_ConstAssignSeen: + return "Missing value expr or illegal syntax following '='"; + case PS_ConstExprSeen: + return "Missing ';' or illegal syntax following value expr in const"; + case PS_TypedefSeen: + return "Missing type or illegal syntax following TYPEDEF keyword"; + case PS_TypeSpecSeen: + return "Missing declarators or illegal syntax following type spec"; + case PS_DeclaratorsSeen: + return "Illegal syntax following declarators in TYPEDEF declaration"; + case PS_StructSeen: + return "Missing struct identifier following STRUCT keyword"; + case PS_StructHeaderSeen: + return "Missing '{' or illegal syntax following struct inheritance spec"; + case PS_StructIDSeen: + return "Missing '{' or illegal syntax following struct identifier"; + case PS_StructSqSeen: + return "Illegal syntax following struct '{' opener"; + case PS_StructQsSeen: + return "Illegal syntax following struct '}' closer"; + case PS_StructBodySeen: + return "Illegal syntax following struct member(s)"; + case PS_MemberTypeSeen: + return "Illegal syntax or missing identifier following member type"; + case PS_MemberDeclsSeen: + return "Illegal syntax following member declarator(s)"; + case PS_MemberDeclsCompleted: + return "Missing ',' between member decls of same type(?)"; + case PS_EnumSeen: + return "Illegal syntax or missing identifier following ENUM keyword"; + case PS_EnumIDSeen: + return "Illegal syntax or missing '{' following enum identifier"; + case PS_EnumSqSeen: + return "Illegal syntax following enum '{' opener"; + case PS_EnumQsSeen: + return "Illegal syntax following enum '}' closer"; + case PS_EnumBodySeen: + return "Illegal syntax following enum enumerator(s)"; + case PS_EnumCommaSeen: + return "Illegal syntax or missing identifier following ',' in enum"; + case PS_SequenceSeen: + return "Illegal syntax or missing '<' following SEQUENCE keyword"; + case PS_SequenceSqSeen: + return "Illegal syntax or missing type following '<' in sequence"; + case PS_SequenceQsSeen: + return "Illegal syntax following '>' in sequence"; + case PS_SequenceTypeSeen: + return "Illegal syntax following sequence type declaration"; + case PS_FlagHeaderSeen: + return "Illegal syntax after flags"; + case PS_AttrSeen: + return "Illegal syntax after ATTRIBUTE keyword"; + case PS_AttrTypeSeen: + return "Illegal syntax after type in attribute declaration"; + case PS_AttrCompleted: + return "Illegal syntax after attribute declaration"; + case PS_ReadOnlySeen: + return "Illegal syntax after READONLY keyword"; + case PS_OptionalSeen: + return "Illegal syntax after OPTIONAL keyword"; + case PS_MayBeVoidSeen: + return "Illegal syntax after MAYBEVOID keyword"; + case PS_BoundSeen: + return "Illegal syntax after BOUND keyword"; + case PS_ConstrainedSeen: + return "Illegal syntax after CONSTRAINED keyword"; + case PS_TransientSeen: + return "Illegal syntax after TRANSIENT keyword"; + case PS_MayBeAmbiguousSeen: + return "Illegal syntax after MAYBEAMBIGUOUS keyword"; + case PS_MayBeDefaultSeen: + return "Illegal syntax after MAYBEDEFAULT keyword"; + case PS_RemoveableSeen: + return "Illegal syntax after REMOVABLE keyword"; + case PS_PropertySeen: + return "Illegal syntax after PROPERTY keyword"; + case PS_PropertyTypeSeen: + return "Illegal syntax after type in property declaration"; + case PS_PropertyCompleted: + return "Illegal syntax after property declaration"; + case PS_ExceptSeen: + return "Illegal syntax or missing identifier after EXCEPTION keyword"; + case PS_ExceptHeaderSeen: + return "Missing '{' or illegal syntax following exception inheritance spec"; + case PS_ExceptIDSeen: + return "Illegal syntax or missing '{' after exception identifier"; + case PS_ExceptSqSeen: + return "Illegal syntax after exception '{' opener"; + case PS_ExceptQsSeen: + return "Illegal syntax after exception '}' closer"; + case PS_ExceptBodySeen: + return "Illegal syntax after exception member(s)"; + case PS_OpTypeSeen: + return "Illegal syntax or missing identifier after operation type"; + case PS_OpIDSeen: + return "Illegal syntax or missing '(' after operation identifier"; + case PS_OpParsCompleted: + return "Illegal syntax after operation parameter list"; + case PS_OpSqSeen: + return "Illegal syntax after operation parameter list '(' opener"; + case PS_OpQsSeen: + return "Illegal syntax after operation parameter list ')' closer"; + case PS_OpParCommaSeen: + return "Illegal syntax or missing direction in parameter declaration"; + case PS_OpParDirSeen: + return "Illegal syntax or missing type in parameter declaration"; + case PS_OpParTypeSeen: + return "Illegal syntax or missing declarator in parameter declaration"; + case PS_OpParDeclSeen: + return "Illegal syntax following parameter declarator"; + case PS_RaiseSeen: + return "Illegal syntax or missing '(' after RAISES keyword"; + case PS_RaiseSqSeen: + return "Illegal syntax after RAISES '(' opener"; + case PS_RaiseQsSeen: + return "Illegal syntax after RAISES ')' closer"; + case PS_DeclsCommaSeen: + return "Illegal syntax after ',' in declarators list"; + case PS_DeclsDeclSeen: + return "Illegal syntax after declarator in declarators list"; + default: + return "no wider described syntax error"; + } +} + +static OString flagToString(sal_uInt32 flag) +{ + OString flagStr; + if ( (flag & AF_READONLY) == AF_READONLY ) + flagStr += "'readonly'"; + if ( (flag & AF_OPTIONAL) == AF_OPTIONAL ) + flagStr += "'optional'"; + if ( (flag & AF_MAYBEVOID) == AF_MAYBEVOID ) + flagStr += "'maybevoid'"; + if ( (flag & AF_BOUND) == AF_BOUND ) + flagStr += "'bound'"; + if ( (flag & AF_CONSTRAINED) == AF_CONSTRAINED ) + flagStr += "'constrained'"; + if ( (flag & AF_TRANSIENT) == AF_TRANSIENT ) + flagStr += "'transient'"; + if ( (flag & AF_MAYBEAMBIGUOUS) == AF_MAYBEAMBIGUOUS ) + flagStr += "'maybeambiguous'"; + if ( (flag & AF_MAYBEDEFAULT) == AF_MAYBEDEFAULT ) + flagStr += "'maybedefault'"; + if ( (flag & AF_REMOVABLE) == AF_REMOVABLE ) + flagStr += "'removable'"; + if ( (flag & AF_ATTRIBUTE) == AF_ATTRIBUTE ) + flagStr += "'attribute'"; + if ( (flag & AF_PROPERTY) == AF_PROPERTY ) + flagStr += "'property'"; + if ( flagStr.isEmpty() ) + flagStr += "'unknown'"; + + return flagStr; +} + +static void errorHeader(ErrorCode eCode, sal_Int32 lineNumber, sal_uInt32 start, sal_uInt32 end) +{ + OString file; + if ( idlc()->getFileName() == idlc()->getRealFileName() ) + file = idlc()->getMainFileName(); + else + file = idlc()->getFileName(); + + fprintf(stderr, "%s:%" SAL_PRIdINT64 " [%" SAL_PRIdINT64 ":%" SAL_PRIdINT64 "] : %s", file.getStr(), + sal_Int64(lineNumber), + sal_Int64(start), + sal_Int64(end), + errorCodeToMessage(eCode)); +} + +static void errorHeader(ErrorCode eCode, sal_uInt32 lineNumber) +{ + errorHeader(eCode, lineNumber, + idlc()->getOffsetStart(), idlc()->getOffsetEnd()); +} + +static void errorHeader(ErrorCode eCode) +{ + errorHeader(eCode, idlc()->getLineNumber(), + idlc()->getOffsetStart(), idlc()->getOffsetEnd()); +} + +static void warningHeader(WarningCode wCode) +{ + OString file; + if ( idlc()->getFileName() == idlc()->getRealFileName() ) + file = idlc()->getMainFileName(); + else + file = idlc()->getFileName(); + + fprintf(stderr, "%s(%" SAL_PRIdINT64 ") : WARNING, %s", file.getStr(), + sal_Int64(idlc()->getLineNumber()), + warningCodeToMessage(wCode)); +} + +void ErrorHandler::error0(ErrorCode e) +{ + errorHeader(e); + fprintf(stderr, "\n"); + idlc()->incErrorCount(); +} + +void ErrorHandler::error1(ErrorCode e, AstDeclaration const * d) +{ + errorHeader(e); + fprintf(stderr, "'%s'\n", d->getScopedName().getStr()); + idlc()->incErrorCount(); +} + +void ErrorHandler::error2( + ErrorCode e, AstDeclaration const * d1, AstDeclaration const * d2) +{ + errorHeader(e); + fprintf(stderr, "'%s', '%s'\n", d1->getScopedName().getStr(), + d2->getScopedName().getStr()); + idlc()->incErrorCount(); +} + +void ErrorHandler::error3(ErrorCode e, AstDeclaration const * d1, AstDeclaration const * d2, AstDeclaration const * d3) +{ + errorHeader(e); + fprintf(stderr, "'%s', '%s', '%s'\n", d1->getScopedName().getStr(), + d2->getScopedName().getStr(), d3->getScopedName().getStr()); + idlc()->incErrorCount(); +} + +void ErrorHandler::warning0(WarningCode w, const char* warningmsg) +{ + if ( idlc()->getOptions()->isValid("-w") || idlc()->getOptions()->isValid("-we") ) { + warningHeader(w); + fprintf(stderr, "%s\n", warningmsg); + } + + if ( idlc()->getOptions()->isValid("-we") ) + idlc()->incErrorCount(); + else + idlc()->incWarningCount(); +} + +void ErrorHandler::syntaxError(ParseState ps, sal_Int32 lineNumber, const char* errmsg) +{ + errorHeader(ErrorCode::SyntaxError, lineNumber); + fprintf(stderr, "%s: %s\n", parseStateToMessage(ps), errmsg); + idlc()->incErrorCount(); +} + +void ErrorHandler::coercionError(AstExpression *pExpr, ExprType et) +{ + errorHeader(ErrorCode::CoercionFailure); + fprintf(stderr, "'%s' to '%s'\n", pExpr->toString().getStr(), + exprTypeToString(et)); + idlc()->incErrorCount(); +} + +void ErrorHandler::lookupError(const OString& n) +{ + errorHeader(ErrorCode::IdentNotFound); + fprintf(stderr, "'%s'\n", n.getStr()); + idlc()->incErrorCount(); +} + +void ErrorHandler::lookupError(ErrorCode e, const OString& n, AstDeclaration const * pScope) +{ + errorHeader(e); + fprintf(stderr, "'%s' in '%s'\n", n.getStr(), pScope->getFullName().getStr()); + idlc()->incErrorCount(); +} + +void ErrorHandler::flagError(ErrorCode e, sal_uInt32 flag) +{ + errorHeader(e); + fprintf(stderr, "'%s'\n", flagToString(flag).getStr()); + idlc()->incErrorCount(); +} + +void ErrorHandler::noTypeError(AstDeclaration const * pDecl) +{ + errorHeader(ErrorCode::NotAType); + fprintf(stderr, "'%s'\n", pDecl->getScopedName().getStr()); + idlc()->incErrorCount(); +} + +namespace { + +char const * nodeTypeName(NodeType nodeType) { + switch (nodeType) { + case NT_interface: + return "interface"; + + case NT_exception: + return "exception"; + + case NT_struct: + return "struct"; + + default: + return ""; + } +} + +} + +void ErrorHandler::inheritanceError(NodeType nodeType, const OString* name, AstDeclaration const * pDecl) +{ + if ( nodeType == NT_interface && + (pDecl->getNodeType() == NT_interface) && + !(static_cast<AstInterface const *>(pDecl)->isDefined()) ) + { + errorHeader(ErrorCode::CannotInheritFromForward); + fprintf(stderr, "interface '%s' cannot inherit from forward declared interface '%s'\n", + name->getStr(), pDecl->getScopedName().getStr()); + } else + { + errorHeader(ErrorCode::CantInherit); + fprintf(stderr, "%s '%s' from '%s'\n", + nodeTypeName(nodeType), name->getStr(), + pDecl->getScopedName().getStr()); + } + idlc()->incErrorCount(); +} + +void ErrorHandler::forwardLookupError(const AstDeclaration* pForward, + const OString& name) +{ + errorHeader(ErrorCode::ForwardDeclLookup); + fprintf(stderr, "trying to look up '%s' in undefined forward declared interface '%s'\n", + pForward->getScopedName().getStr(), name.getStr()); + idlc()->incErrorCount(); +} + +void ErrorHandler::constantExpected(AstDeclaration const * pDecl, + const OString& name) +{ + errorHeader(ErrorCode::ExpectedConstant); + fprintf(stderr, "'%s' is bound to '%s'\n", name.getStr(), pDecl->getScopedName().getStr()); + idlc()->incErrorCount(); +} + +void ErrorHandler::evalError(AstExpression* pExpr) +{ + errorHeader(ErrorCode::Eval); + fprintf(stderr, "'%s'\n", pExpr->toString().getStr()); + idlc()->incErrorCount(); +} + +bool ErrorHandler::checkPublished(AstDeclaration const * decl, bool bOptional) { + if (idlc()->isPublished() && !decl->isPublished() && !bOptional) { + error1(ErrorCode::PublishedusesUnpublished, decl); + return false; + } else { + return true; + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/source/fehelper.cxx b/idlc/source/fehelper.cxx new file mode 100644 index 000000000..607f5a145 --- /dev/null +++ b/idlc/source/fehelper.cxx @@ -0,0 +1,102 @@ +/* -*- 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 <fehelper.hxx> +#include <errorhandler.hxx> +#include <idlc.hxx> + +FeDeclarator::FeDeclarator(const OString& name) + : m_name(name) +{ +} + +FeDeclarator::~FeDeclarator() +{ +} + +bool FeDeclarator::checkType(AstDeclaration const * type) const +{ + OString tmp(m_name); + sal_Int32 count = m_name.lastIndexOf( ':' ); + if( count != -1 ) + tmp = m_name.copy( count+1 ); + + return tmp != type->getLocalName(); +} + +AstType const * FeDeclarator::compose(AstDeclaration const * pDecl) +{ + if ( pDecl == nullptr ) + { + return nullptr; + } + if ( !pDecl->isType() ) + { + ErrorHandler::noTypeError(pDecl); + return nullptr; + } + return static_cast<const AstType*>(pDecl); +} + +FeInheritanceHeader::FeInheritanceHeader( + NodeType nodeType, OString* pName, OString const * pInherits, + std::vector< OString > const * typeParameters) + : m_nodeType(nodeType) + , m_pName(pName) + , m_pInherits(nullptr) +{ + if (typeParameters != nullptr) { + m_typeParameters = *typeParameters; + } + initializeInherits(pInherits); +} + +void FeInheritanceHeader::initializeInherits(OString const * pInherits) +{ + if ( !pInherits ) + return; + + AstScope* pScope = idlc()->scopes()->topNonNull(); + AstDeclaration* pDecl = pScope->lookupByName(*pInherits); + if ( pDecl ) + { + AstDeclaration const * resolved = resolveTypedefs(pDecl); + if ( resolved->getNodeType() == getNodeType() + && (resolved->getNodeType() != NT_interface + || static_cast< AstInterface const * >( + resolved)->isDefined()) ) + { + if ( ErrorHandler::checkPublished( pDecl ) ) + { + m_pInherits = pDecl; + } + } + else + { + ErrorHandler::inheritanceError( + getNodeType(), getName(), pDecl); + } + } + else + { + ErrorHandler::lookupError(*pInherits); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/source/idlc.cxx b/idlc/source/idlc.cxx new file mode 100644 index 000000000..ca47b34fe --- /dev/null +++ b/idlc/source/idlc.cxx @@ -0,0 +1,400 @@ +/* -*- 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 <idlc.hxx> +#include <errorhandler.hxx> +#include <astscope.hxx> +#include <astmodule.hxx> +#include <astservice.hxx> +#include <astconstants.hxx> +#include <astexception.hxx> +#include <astenum.hxx> +#include <astinterface.hxx> +#include <astoperation.hxx> +#include <astbasetype.hxx> +#include <astdeclaration.hxx> +#include <astparameter.hxx> +#include <astsequence.hxx> +#include <asttype.hxx> +#include <asttypedef.hxx> + +#include <osl/diagnose.h> +#include <osl/file.hxx> +#include <osl/thread.h> + +#include <algorithm> + +AstDeclaration* scopeAsDecl(AstScope* pScope) +{ + if (pScope == nullptr) return nullptr; + + switch( pScope->getScopeNodeType() ) + { + case NT_service: + case NT_singleton: + return static_cast<AstService*>(pScope); + case NT_module: + case NT_root: + return static_cast<AstModule*>(pScope); + case NT_constants: + return static_cast<AstConstants*>(pScope); + case NT_interface: + return static_cast<AstInterface*>(pScope); + case NT_operation: + return static_cast<AstOperation*>(pScope); + case NT_exception: + return static_cast<AstException*>(pScope); + case NT_struct: + return static_cast<AstStruct*>(pScope); + case NT_enum: + return static_cast<AstEnum*>(pScope); + default: + return nullptr; + } +} + +AstScope* declAsScope(AstDeclaration* pDecl) +{ + if (pDecl == nullptr) return nullptr; + + switch(pDecl->getNodeType()) + { + case NT_interface: + return static_cast<AstInterface*>(pDecl); + case NT_service: + case NT_singleton: + return static_cast<AstService*>(pDecl); + case NT_module: + case NT_root: + return static_cast<AstModule*>(pDecl); + case NT_constants: + return static_cast<AstConstants*>(pDecl); + case NT_exception: + return static_cast<AstException*>(pDecl); + case NT_struct: + return static_cast<AstStruct*>(pDecl); + case NT_enum: + return static_cast<AstEnum*>(pDecl); + case NT_operation: + return static_cast<AstOperation*>(pDecl); + default: + return nullptr; + } +} + +static void predefineXInterface(AstModule* pRoot) +{ + // define the modules com::sun::star::uno + AstModule* pParentScope = pRoot; + AstModule* pModule = new AstModule("com", pParentScope); + pModule->setPredefined(true); + pParentScope->addDeclaration(pModule); + pParentScope = pModule; + pModule = new AstModule("sun", pParentScope); + pModule->setPredefined(true); + pParentScope->addDeclaration(pModule); + pParentScope = pModule; + pModule = new AstModule("star", pParentScope); + pModule->setPredefined(true); + pParentScope->addDeclaration(pModule); + pParentScope = pModule; + pModule = new AstModule("uno", pParentScope); + pModule->setPredefined(true); + pParentScope->addDeclaration(pModule); + pParentScope = pModule; + + // define XInterface + AstInterface* pInterface = new AstInterface("XInterface", nullptr, pParentScope); + pInterface->setDefined(); + pInterface->setPredefined(true); + pInterface->setPublished(); + pParentScope->addDeclaration(pInterface); + + // define XInterface::queryInterface + AstOperation* pOp = new AstOperation(static_cast<AstType*>(pRoot->lookupPrimitiveType(ET_any)), + "queryInterface", pInterface); + AstParameter* pParam = new AstParameter(DIR_IN, false, + static_cast<AstType*>(pRoot->lookupPrimitiveType(ET_type)), + "aType", pOp); + pOp->addDeclaration(pParam); + pInterface->addMember(pOp); + + // define XInterface::acquire + pOp = new AstOperation(static_cast<AstType*>(pRoot->lookupPrimitiveType(ET_void)), + "acquire", pInterface); + pInterface->addMember(pOp); + + // define XInterface::release + pOp = new AstOperation(static_cast<AstType*>(pRoot->lookupPrimitiveType(ET_void)), + "release", pInterface); + pInterface->addMember(pOp); +} + +static void initializePredefinedTypes(AstModule* pRoot) +{ + if ( !pRoot ) + return; + + AstBaseType* pPredefined = new AstBaseType(ET_long, "long", pRoot); + pRoot->addDeclaration(pPredefined); + + pPredefined = new AstBaseType(ET_ulong, "unsigned long", pRoot); + pRoot->addDeclaration(pPredefined); + + pPredefined = new AstBaseType(ET_hyper, "hyper", pRoot); + pRoot->addDeclaration(pPredefined); + + pPredefined = new AstBaseType(ET_uhyper, "unsigned hyper", pRoot); + pRoot->addDeclaration(pPredefined); + + pPredefined = new AstBaseType(ET_short, "short", pRoot); + pRoot->addDeclaration(pPredefined); + + pPredefined = new AstBaseType(ET_ushort, "unsigned short", pRoot); + pRoot->addDeclaration(pPredefined); + + pPredefined = new AstBaseType(ET_float, "float", pRoot); + pRoot->addDeclaration(pPredefined); + + pPredefined = new AstBaseType(ET_double, "double", pRoot); + pRoot->addDeclaration(pPredefined); + + pPredefined = new AstBaseType(ET_char, "char", pRoot); + pRoot->addDeclaration(pPredefined); + + pPredefined = new AstBaseType(ET_byte, "byte", pRoot); + pRoot->addDeclaration(pPredefined); + + pPredefined = new AstBaseType(ET_any, "any", pRoot); + pRoot->addDeclaration(pPredefined); + + pPredefined = new AstBaseType(ET_string, "string", pRoot); + pRoot->addDeclaration(pPredefined); + + pPredefined = new AstBaseType(ET_type, "type", pRoot); + pRoot->addDeclaration(pPredefined); + + pPredefined = new AstBaseType(ET_boolean, "boolean", pRoot); + pRoot->addDeclaration(pPredefined); + + pPredefined = new AstBaseType(ET_void, "void", pRoot); + pRoot->addDeclaration(pPredefined); +} + +Idlc::Idlc(Options* pOptions) + : m_pOptions(pOptions) + , m_bIsDocValid(false) + , m_bIsInMainfile(true) + , m_published(false) + , m_errorCount(0) + , m_warningCount(0) + , m_lineNumber(0) + , m_offsetStart(0) + , m_offsetEnd(0) + , m_parseState(PS_NoState) +{ + m_pScopes.reset( new AstStack() ); + // init root object after construction + m_pRoot = nullptr; + m_bGenerateDoc = m_pOptions->isValid("-C"); +} + +Idlc::~Idlc() +{ +} + +void Idlc::init() +{ + m_pRoot.reset(new AstModule(NT_root, OString(), nullptr)); + + // push the root node on the stack + m_pScopes->push(m_pRoot.get()); + initializePredefinedTypes(m_pRoot.get()); + predefineXInterface(m_pRoot.get()); +} + +void Idlc::reset() +{ + m_bIsDocValid = false; + m_bIsInMainfile = true; + m_published = false; + + m_errorCount = 0; + m_warningCount = 0; + m_lineNumber = 0; + m_parseState = PS_NoState; + + m_fileName.clear(); + m_mainFileName.clear(); + m_realFileName.clear(); + m_documentation.clear(); + + m_pScopes->clear(); + m_pRoot.reset( new AstModule(NT_root, OString(), nullptr) ); + + // push the root node on the stack + m_pScopes->push(m_pRoot.get()); + initializePredefinedTypes(m_pRoot.get()); + + m_includes.clear(); +} + +OUString Idlc::processDocumentation() +{ + OUString doc; + if (m_bIsDocValid) { + OString raw(getDocumentation()); + if (m_bGenerateDoc) { + doc = OStringToOUString(raw, RTL_TEXTENCODING_UTF8); + } else if (raw.indexOf("@deprecated") != -1) { + //TODO: this check is somewhat crude + doc = "@deprecated"; + } + } + return doc; +} + +static void lcl_writeString(::osl::File & rFile, ::osl::FileBase::RC & o_rRC, + OString const& rString) +{ + if (::osl::FileBase::E_None == o_rRC) { + sal_uInt64 nWritten(0); + o_rRC = rFile.write(rString.getStr(), rString.getLength(), nWritten); + if (static_cast<sal_uInt64>(rString.getLength()) != nWritten) { + o_rRC = ::osl::FileBase::E_INVAL; //? + } + } +} + +namespace { + +struct WriteDep +{ + ::osl::File& m_rFile; + ::osl::FileBase::RC & m_rRC; + explicit WriteDep(::osl::File & rFile, ::osl::FileBase::RC & rRC) + : m_rFile(rFile), m_rRC(rRC) { } + void operator() (OString const& rEntry) + { + lcl_writeString(m_rFile, m_rRC, " \\\n "); + lcl_writeString(m_rFile, m_rRC, rEntry); + } +}; + +// 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 +{ + ::osl::File& m_rFile; + ::osl::FileBase::RC & m_rRC; + explicit WriteDummy(::osl::File & rFile, ::osl::FileBase::RC & rRC) + : m_rFile(rFile), m_rRC(rRC) { } + void operator() (OString const& rEntry) + { + lcl_writeString(m_rFile, m_rRC, rEntry); + lcl_writeString(m_rFile, m_rRC, ":\n\n"); + } +}; + +} + +bool +Idlc::dumpDeps(std::string_view rDepFile, OString const& rTarget) +{ + ::osl::File depFile( + OStringToOUString(rDepFile, osl_getThreadTextEncoding())); + ::osl::FileBase::RC rc = + depFile.open(osl_File_OpenFlag_Write | osl_File_OpenFlag_Create); + if (::osl::FileBase::E_None != rc) { + return false; + } + lcl_writeString(depFile, rc, rTarget); + if (::osl::FileBase::E_None != rc) { + return false; + } + lcl_writeString(depFile, rc, " :"); + if (::osl::FileBase::E_None != rc) { + return false; + } + m_includes.erase(getRealFileName()); // eeek, that is a temp file... + ::std::for_each(m_includes.begin(), m_includes.end(), + WriteDep(depFile, rc)); + lcl_writeString(depFile, rc, "\n\n"); + ::std::for_each(m_includes.begin(), m_includes.end(), + WriteDummy(depFile, rc)); + if (::osl::FileBase::E_None != rc) { + return false; + } + rc = depFile.close(); + return ::osl::FileBase::E_None == rc; +} + +static Idlc* pStaticIdlc = nullptr; + +Idlc* idlc() +{ + return pStaticIdlc; +} + +Idlc* setIdlc(Options* pOptions) +{ + delete pStaticIdlc; + pStaticIdlc = new Idlc(pOptions); + pStaticIdlc->init(); + return pStaticIdlc; +} + +AstDeclaration const * resolveTypedefs(AstDeclaration const * type) { + if (type != nullptr) { + while (type->getNodeType() == NT_typedef) { + type = static_cast< AstTypeDef const * >(type)->getBaseType(); + } + } + return type; +} + +AstDeclaration const * deconstructAndResolveTypedefs( + AstDeclaration const * type, sal_Int32 * rank) +{ + *rank = 0; + for (;;) { + if (type == nullptr) { + return nullptr; + } + switch (type->getNodeType()) { + case NT_typedef: + type = static_cast< AstTypeDef const * >(type)->getBaseType(); + break; + case NT_sequence: + ++(*rank); + type = static_cast< AstSequence const * >(type)->getMemberType(); + break; + default: + return type; + } + } +} + +AstInterface const * resolveInterfaceTypedefs(AstType const * type) { + AstDeclaration const * decl = resolveTypedefs(type); + OSL_ASSERT(decl->getNodeType() == NT_interface); + return static_cast< AstInterface const * >(decl); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/source/idlccompile.cxx b/idlc/source/idlccompile.cxx new file mode 100644 index 000000000..5aec20912 --- /dev/null +++ b/idlc/source/idlccompile.cxx @@ -0,0 +1,394 @@ +/* -*- 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 <idlc.hxx> +#include <rtl/alloc.h> +#include <rtl/ustring.hxx> +#include <rtl/strbuf.hxx> +#include <o3tl/safeint.hxx> +#include <o3tl/string_view.hxx> +#include <osl/process.h> +#include <osl/diagnose.h> +#include <osl/thread.h> +#include <osl/file.hxx> + +#if defined(_WIN32) +#include <io.h> +#endif + +#ifdef SAL_UNX +#include <errno.h> +#include <unistd.h> +#include <sys/wait.h> +#endif + +#include <string.h> + +using namespace ::osl; + +extern int yyparse(); +extern FILE* yyin; +extern int yydebug; + +static char tmpFilePattern[512]; + +bool isFileUrl(std::string_view fileName) +{ + return o3tl::starts_with(fileName, "file://"); +} + +OString convertToAbsoluteSystemPath(const OString& fileName) +{ + OUString uSysFileName; + OUString uFileName(fileName.getStr(), fileName.getLength(), osl_getThreadTextEncoding()); + if ( isFileUrl(fileName) ) + { + if (FileBase::getSystemPathFromFileURL(uFileName, uSysFileName) + != FileBase::E_None) + { + OSL_ASSERT(false); + } + } else + { + OUString uWorkingDir, uUrlFileName, uTmp; + if (osl_getProcessWorkingDir(&uWorkingDir.pData) != osl_Process_E_None) + { + OSL_ASSERT(false); + } + if (FileBase::getFileURLFromSystemPath(uFileName, uTmp) + != FileBase::E_None) + { + OSL_ASSERT(false); + } + if (FileBase::getAbsoluteFileURL(uWorkingDir, uTmp, uUrlFileName) + != FileBase::E_None) + { + OSL_ASSERT(false); + } + if (FileBase::getSystemPathFromFileURL(uUrlFileName, uSysFileName) + != FileBase::E_None) + { + OSL_ASSERT(false); + } + } + + return OUStringToOString(uSysFileName, osl_getThreadTextEncoding()); +} + +OString convertToFileUrl(const OString& fileName) +{ + if ( !isFileUrl(fileName) ) + { + OString tmp = convertToAbsoluteSystemPath(fileName); + OUString uFileName(tmp.getStr(), tmp.getLength(), osl_getThreadTextEncoding()); + OUString uUrlFileName; + if (FileBase::getFileURLFromSystemPath(uFileName, uUrlFileName) + != FileBase::E_None) + { + OSL_ASSERT(false); + } + return OUStringToOString(uUrlFileName, osl_getThreadTextEncoding()); + } + + return fileName; +} + +static OString makeTempName(const OString& prefix) +{ + OUString uTmpPath; + OString tmpPath; + + if ( osl_getEnvironment(OUString("TMP").pData, &uTmpPath.pData) != osl_Process_E_None ) + { + if ( osl_getEnvironment(OUString("TEMP").pData, &uTmpPath.pData) != osl_Process_E_None ) + { +#if defined(_WIN32) + tmpPath = OString("c:\\temp"); +#else + tmpPath = OString("/tmp"); +#endif + } + } + + if ( !uTmpPath.isEmpty() ) + tmpPath = OUStringToOString(uTmpPath, RTL_TEXTENCODING_UTF8); + +#if defined(_WIN32) || defined(SAL_UNX) + + OSL_ASSERT( sizeof(tmpFilePattern) > + o3tl::make_unsigned( tmpPath.getLength() + + RTL_CONSTASCII_LENGTH( PATH_SEPARATOR ) + + prefix.getLength() + + RTL_CONSTASCII_LENGTH( "XXXXXX") ) ); + + tmpFilePattern[ sizeof(tmpFilePattern)-1 ] = '\0'; + strncpy(tmpFilePattern, tmpPath.getStr(), sizeof(tmpFilePattern)-1); + strncat(tmpFilePattern, PATH_SEPARATOR, sizeof(tmpFilePattern)-1-strlen(tmpFilePattern)); + strncat(tmpFilePattern, prefix.getStr(), sizeof(tmpFilePattern)-1-strlen(tmpFilePattern)); + strncat(tmpFilePattern, "XXXXXX", sizeof(tmpFilePattern)-1-strlen(tmpFilePattern)); + +#ifdef SAL_UNX + // coverity[secure_temp] - https://communities.coverity.com/thread/3179 + int nDescriptor = mkstemp(tmpFilePattern); + if( -1 == nDescriptor ) + { + fprintf(stderr, "idlc: mkstemp(\"%s\") failed: %s\n", tmpFilePattern, strerror(errno)); + exit( 1 ); + } + // the file shall later be reopened by stdio functions + close( nDescriptor ); +#else + (void) mktemp(tmpFilePattern); +#endif +#endif + + return tmpFilePattern; +} + +bool copyFile(const OString* source, const OString& target) +{ + bool bRet = true; + + FILE* pSource = source == nullptr ? stdin : fopen(source->getStr(), "rb"); + if ( !pSource ) + return false; + + FILE* pTarget = fopen(target.getStr(), "wb"); + if ( !pTarget ) + { + fclose(pSource); + return false; + } + + size_t const totalSize = 512; + char pBuffer[totalSize + 1]; + + while ( !feof(pSource) ) + { + size_t readSize = fread(pBuffer, 1, totalSize, pSource); + if ( readSize > 0 && !ferror(pSource) ) + { + if ( (fwrite(pBuffer, 1, readSize, pTarget)) != readSize || ferror(pTarget) ) + { + if (source != nullptr) { + fclose(pSource); + } + fclose(pTarget); + return false; + } + } + } + + if (source != nullptr) { + fclose(pSource); + } + if ( fclose(pTarget) ) + bRet = false; + + return bRet; +} + +sal_Int32 compileFile(const OString * pathname) +{ + // preprocess input file + OString tmpFile = makeTempName("idli_"); + OString preprocFile = makeTempName("idlf_"); + + OString fileName; + if (pathname == nullptr) { + fileName = "stdin"; + } else { + fileName = *pathname; + } + + if ( !copyFile(pathname, tmpFile) ) + { + fprintf(stderr, "%s: could not copy %s%s to %s\n", + idlc()->getOptions()->getProgramName().getStr(), + pathname == nullptr ? "" : "file ", fileName.getStr(), + tmpFile.getStr()); + exit(99); + } + + idlc()->setFileName(fileName); + idlc()->setMainFileName(fileName); + idlc()->setRealFileName(tmpFile); + + ::std::vector< OUString> lCppArgs; + lCppArgs.emplace_back("-DIDL"); + lCppArgs.emplace_back("-C"); +#ifdef SYSTEM_UCPP_IS_GCC + // -nostdinc Do not search the standard system directories for header files + lCppArgs.emplace_back("-nostdinc"); + // with gcc cpp, even when not explicitly including anything, /usr/include/stdc-predef.h + // gets inserted without -nostdinc +#else + // -zI Do not use the standard (compile-time) include path. + lCppArgs.emplace_back("-zI"); +#endif + + Options* pOptions = idlc()->getOptions(); + + OString filePath; + sal_Int32 index = fileName.lastIndexOf(SEPARATOR); + + if ( index > 0) + { + filePath = fileName.copy(0, index); + + if ( !filePath.isEmpty() ) + { + OString cppArgs = "-I" + filePath; + lCppArgs.push_back(OStringToOUString( + cppArgs.replace('\\', '/'), + RTL_TEXTENCODING_UTF8)); + } + } + + if ( pOptions->isValid("-D") ) + { + OString dOpt = pOptions->getOption("-D"); + sal_Int32 nIndex = 0; + do + { + std::string_view token = o3tl::getToken(dOpt, 0, ' ', nIndex ); + if (token.size()) + lCppArgs.push_back("-D" + OStringToOUString(token, RTL_TEXTENCODING_UTF8)); + } while( nIndex != -1 ); + } + + if ( pOptions->isValid("-I") ) + { + OString incOpt = pOptions->getOption("-I"); + sal_Int32 nIndex = 0; + do + { + std::string_view token = o3tl::getToken(incOpt, 0, ' ', nIndex ); + if (token.size()) + lCppArgs.push_back("-I" + OStringToOUString(token, RTL_TEXTENCODING_UTF8)); + } while( nIndex != -1 ); + } + + lCppArgs.emplace_back("-o"); + + lCppArgs.push_back(OStringToOUString(preprocFile, RTL_TEXTENCODING_UTF8)); + + lCppArgs.push_back(OStringToOUString(tmpFile, RTL_TEXTENCODING_UTF8)); + + OUString cpp; + OUString startDir; +#ifndef SYSTEM_UCPP + if (osl_getExecutableFile(&cpp.pData) != osl_Process_E_None) { + OSL_ASSERT(false); + } + + sal_Int32 idx= cpp.lastIndexOf("idlc"); + cpp = cpp.copy(0, idx); + +#if defined(_WIN32) + cpp += "ucpp.exe"; +#else + cpp += "ucpp"; +#endif +#else // SYSTEM_UCPP + cpp = OUString(UCPP); +#endif + oslProcess hProcess = nullptr; + oslProcessError procError = osl_Process_E_None; + + const int nCmdArgs = lCppArgs.size(); + std::unique_ptr<rtl_uString*[]> pCmdArgs(new rtl_uString*[nCmdArgs]); + + int i = 0; + for (auto const& elem : lCppArgs) + { + pCmdArgs[i++] = elem.pData; + } + + procError = osl_executeProcess( cpp.pData, pCmdArgs.get(), nCmdArgs, osl_Process_WAIT, + nullptr, startDir.pData, nullptr, 0, &hProcess ); + + oslProcessInfo hInfo; + hInfo.Size = sal_uInt32(sizeof(oslProcessInfo)); + if (osl_getProcessInfo(hProcess, osl_Process_EXITCODE, &hInfo) + != osl_Process_E_None) + { + OSL_ASSERT(false); + } + + if ( procError || (hInfo.Code != 0) ) + { + if ( procError != osl_Process_E_None ) + fprintf(stderr, "%s: starting preprocessor failed\n", pOptions->getProgramName().getStr()); + else + fprintf(stderr, "%s: preprocessing %s%s failed\n", + pOptions->getProgramName().getStr(), + pathname == nullptr ? "" : "file ", fileName.getStr()); + + osl_freeProcessHandle(hProcess); + exit(hInfo.Code ? hInfo.Code : 99); + } + osl_freeProcessHandle(hProcess); + + if (unlink(tmpFile.getStr()) != 0) + { + fprintf(stderr, "%s: Could not remove cpp input file %s\n", + pOptions->getProgramName().getStr(), tmpFile.getStr()); + exit(99); + } + + if ( pOptions->isValid("-E") ) + { + if (unlink(preprocFile.getStr()) != 0) + { + fprintf(stderr, "%s: Could not remove parser input file %s\n", + pOptions->getProgramName().getStr(), preprocFile.getStr()); + exit(99); + } + exit(0); + } + + // parse file + yyin = fopen(preprocFile.getStr(), "r"); + if (yyin == nullptr) + { + fprintf(stderr, "%s: Could not open cpp output file %s\n", + pOptions->getProgramName().getStr(), preprocFile.getStr()); + exit(99); + } + + //yydebug = 0 no trace information + //yydebug = 1 parser produce trace information + yydebug = 0; + + yyparse(); + sal_Int32 nErrors = idlc()->getErrorCount(); + + fclose(yyin); + if (unlink(preprocFile.getStr()) != 0) + { + fprintf(stderr, "%s: Could not remove parser input file %s\n", + pOptions->getProgramName().getStr(), preprocFile.getStr()); + exit(99); + } + + return nErrors; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/source/idlcmain.cxx b/idlc/source/idlcmain.cxx new file mode 100644 index 000000000..742dc4e81 --- /dev/null +++ b/idlc/source/idlcmain.cxx @@ -0,0 +1,164 @@ +/* -*- 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 <idlc.hxx> +#include <sal/main.h> + +#include <string.h> + +SAL_IMPLEMENT_MAIN_WITH_ARGS(argc, argv) +{ + std::vector< std::string > args; + for (int i = 1; i < argc; i++) + { + if (!Options::checkArgument (args, argv[i], strlen(argv[i]))) + return 1; + } + + Options options(argv[0]); + sal_Int32 nErrors = 0; + + try + { + if (!options.initOptions(args)) + return 0; + + setIdlc(&options); + + if (options.readStdin()) { + if ( !options.quiet() ) + fprintf( + stdout, "%s: Compiling stdin\n", + options.getProgramName().getStr()); + nErrors = compileFile(nullptr); + if ( ( idlc()->getWarningCount() > 0 ) && !options.quiet() ) { + fprintf( + stdout, "%s: detected %lu warnings compiling stdin\n", + options.getProgramName().getStr(), + sal::static_int_cast< unsigned long >( + idlc()->getWarningCount())); + } + OString outputUrl; + if (options.isValid("-O")) { + outputUrl = convertToFileUrl(options.getOption("-O")); + if (!outputUrl.endsWith("/")) { + outputUrl += "/"; + } + outputUrl += "stdin.urd"; + } else { + outputUrl = convertToFileUrl("stdin.urd"); + } + if (nErrors > 0) { + removeIfExists(outputUrl); + } else { + nErrors = produceFile(outputUrl, nullptr); + } + idlc()->reset(); + } + std::vector< OString > const & files = options.getInputFiles(); + if ( options.verbose() ) + { + fprintf( stdout, "%s: compiling %i source files ... \n", + options.getProgramName().getStr(), static_cast<int>(files.size()) ); + fflush( stdout ); + } + for (auto const& elem : files) + { + if (nErrors) + break; + OString sysFileName( convertToAbsoluteSystemPath(elem) ); + + if ( !options.quiet() ) + fprintf(stdout, "Compiling: %s\n", elem.getStr()); + nErrors = compileFile(&sysFileName); + + if ( idlc()->getWarningCount() && !options.quiet() ) + fprintf(stdout, "%s: detected %" SAL_PRIdINT64 " warnings compiling file '%s'\n", + options.getProgramName().getStr(), + sal_Int64(idlc()->getWarningCount()), + elem.getStr()); + + // prepare output file name + OString const strippedFileName( + sysFileName.copy(sysFileName.lastIndexOf(SEPARATOR) + 1)); + OString outputFile; + if ( options.isValid("-O") ) + { + outputFile = options.getOption("-O"); + if (!outputFile.endsWith("/")) { + outputFile += "/"; + } + outputFile += strippedFileName.replaceAt( + strippedFileName.getLength() -3 , 3, "urd"); + } else { + outputFile = + sysFileName.replaceAt(sysFileName.getLength() -3 , 3, "urd"); + } + OString const outputFileUrl = convertToFileUrl(outputFile); + + OString depFileUrl; + if (options.isValid("-M")) { + depFileUrl = convertToFileUrl(options.getOption("-M")); + if (!depFileUrl.endsWith("/")) { + depFileUrl += "/"; + } + depFileUrl += strippedFileName.replaceAt( + strippedFileName.getLength() -3 , 3, "d"); + } + + if ( nErrors ) { + if (options.isValid("-M")) { + removeIfExists(depFileUrl); + } + removeIfExists(outputFileUrl); + } else { + sPair_t const pair(depFileUrl, outputFile); + nErrors = produceFile(outputFileUrl, + (options.isValid("-M")) ? &pair : nullptr); + } + + idlc()->reset(); + } + + if ( nErrors > 0 ) + { + fprintf(stderr, "%s: detected %" SAL_PRIdINT64 " errors%s", + options.getProgramName().getStr(), + sal_Int64(nErrors), + options.prepareVersion().getStr()); + } else + { + if ( options.verbose() ) + fprintf(stdout, "%s: returned successful%s", + options.getProgramName().getStr(), + options.prepareVersion().getStr()); + } + } catch(const IllegalArgument& e) + { + fprintf(stderr, "Illegal argument: %s\n%s", + e.m_message.getStr(), + options.prepareVersion().getStr()); + return 99; + } + + return nErrors; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/source/idlcproduce.cxx b/idlc/source/idlcproduce.cxx new file mode 100644 index 000000000..2592fe0de --- /dev/null +++ b/idlc/source/idlcproduce.cxx @@ -0,0 +1,242 @@ +/* -*- 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 <idlc.hxx> +#include <astmodule.hxx> +#include <rtl/strbuf.hxx> +#include <osl/file.hxx> +#include <osl/thread.h> +#include <o3tl/string_view.hxx> + +#if defined(_WIN32) +#include <io.h> +#include <direct.h> +#include <errno.h> +#endif + +#ifdef SAL_UNX +#include <unistd.h> +#include <sys/stat.h> +#include <errno.h> +#endif + +#include <string.h> + +using namespace ::osl; + +static std::list< OString > gaCreatedDirectories; + +static bool checkOutputPath(const OString& completeName) +{ + OString sysPathName = convertToAbsoluteSystemPath(completeName); + OStringBuffer buffer(sysPathName.getLength()+16); + + if ( sysPathName.indexOf( SEPARATOR ) == -1 ) + return true; + + sal_Int32 nIndex = 0; + std::string_view token(o3tl::getToken(sysPathName, 0, SEPARATOR, nIndex)); + if (o3tl::starts_with(token, "..") + || (token.size() >= 2 && token[1] == ':') + || o3tl::starts_with(token, ".")) + { + buffer.append(token); + buffer.append(SEPARATOR); + } + else + nIndex = 0; + + do + { + buffer.append(o3tl::getToken(sysPathName, 0, SEPARATOR, nIndex)); + + if ( !buffer.isEmpty() && nIndex != -1 ) + { +#if defined(SAL_UNX) + if (mkdir(buffer.getStr(), 0777) == -1) +#else + if (mkdir(buffer.getStr()) == -1) +#endif + { + if (errno == ENOENT) + { + fprintf(stderr, "%s: cannot create directory '%s'\n", + idlc()->getOptions()->getProgramName().getStr(), buffer.getStr()); + return false; + } + } + else + { + gaCreatedDirectories.push_front(buffer.getStr()); + } + } + buffer.append(SEPARATOR); + } while( nIndex != -1 ); + return true; +} + +static bool cleanPath() +{ + for (auto const& createdDirectory : gaCreatedDirectories) + { +//#ifdef SAL_UNX +// if (rmdir((char*)createdDirectory.getStr(), 0777) == -1) +//#else + if (rmdir(createdDirectory.getStr()) == -1) +//#endif + { + fprintf(stderr, "%s: cannot remove directory '%s'\n", + idlc()->getOptions()->getProgramName().getStr(), createdDirectory.getStr()); + return false; + } + } + gaCreatedDirectories.clear(); + return true; +} + +void removeIfExists(std::string_view pathname) +{ + osl::File::remove(OStringToOUString(pathname, RTL_TEXTENCODING_UTF8)); +} + +sal_Int32 +produceFile(const OString& regFileName, sPair_t const*const pDepFile) +{ + Options* pOptions = idlc()->getOptions(); + + OString regTmpName = regFileName.replaceAt(regFileName.getLength() -3, 3, "_idlc_"); + + if ( !checkOutputPath(regFileName) ) + { + fprintf(stderr, "%s: could not create path of registry file '%s'.\n", + pOptions->getProgramName().getStr(), regFileName.getStr()); + return 1; + } + + OString depTmpName; + if (pDepFile) + { + depTmpName = pDepFile->first.replaceAt( + regFileName.getLength() -3, 3, "_idlc_"); + if ( !checkOutputPath(depTmpName) ) + { + fprintf(stderr, "%s: could not create path of dep file '%s'.\n", + pOptions->getProgramName().getStr(), pDepFile->first.getStr()); + return 1; + } + removeIfExists(depTmpName); + } + + removeIfExists(regTmpName); + OString urlRegTmpName = convertToFileUrl(regTmpName); + + Registry regFile; + if ( regFile.create(OStringToOUString(urlRegTmpName, RTL_TEXTENCODING_UTF8)) != RegError::NO_ERROR ) + { + fprintf(stderr, "%s: could not create registry file '%s'\n", + pOptions->getProgramName().getStr(), regTmpName.getStr()); + removeIfExists(regTmpName); + removeIfExists(regFileName); + cleanPath(); + return 1; + } + + RegistryKey rootKey; + if ( regFile.openRootKey(rootKey) != RegError::NO_ERROR ) + { + fprintf(stderr, "%s: could not open root of registry file '%s'\n", + pOptions->getProgramName().getStr(), regFileName.getStr()); + removeIfExists(regTmpName); + removeIfExists(regFileName); + cleanPath(); + return 1; + } + + // produce registry file + if ( !idlc()->getRoot()->dump(rootKey) ) + { + rootKey.releaseKey(); + if (regFile.close() != RegError::NO_ERROR) + { + fprintf(stderr, "%s: could not close registry file '%s'\n", + pOptions->getProgramName().getStr(), regFileName.getStr()); + } + regFile.destroy(OStringToOUString(regFileName, RTL_TEXTENCODING_UTF8)); + removeIfExists(regFileName); + cleanPath(); + return 1; + } + + rootKey.releaseKey(); + if ( regFile.close() != RegError::NO_ERROR ) + { + fprintf(stderr, "%s: could not close registry file '%s'\n", + pOptions->getProgramName().getStr(), regFileName.getStr()); + removeIfExists(regTmpName); + removeIfExists(regFileName); + cleanPath(); + return 1; + } + + if (pDepFile && !idlc()->dumpDeps(depTmpName, pDepFile->second)) + { + fprintf(stderr, "%s: could not write dep file '%s'\n", + pOptions->getProgramName().getStr(), pDepFile->first.getStr()); + removeIfExists(depTmpName); + removeIfExists(pDepFile->first); + removeIfExists(regTmpName); + removeIfExists(regFileName); + cleanPath(); + return 1; + } + + removeIfExists(regFileName); + + if ( File::move(OStringToOUString(regTmpName, osl_getThreadTextEncoding()), + OStringToOUString(regFileName, osl_getThreadTextEncoding())) != FileBase::E_None ) { + fprintf(stderr, "%s: cannot rename temporary registry '%s' to '%s'\n", + idlc()->getOptions()->getProgramName().getStr(), + regTmpName.getStr(), regFileName.getStr()); + removeIfExists(regTmpName); + cleanPath(); + return 1; + } + removeIfExists(regTmpName); + + if (pDepFile) + { + removeIfExists(pDepFile->first); + if ( File::move(OStringToOUString(depTmpName, osl_getThreadTextEncoding()), + OStringToOUString(pDepFile->first, osl_getThreadTextEncoding())) != FileBase::E_None ) { + fprintf(stderr, "%s: cannot rename dep file '%s' to '%s'\n", + idlc()->getOptions()->getProgramName().getStr(), + depTmpName.getStr(), pDepFile->first.getStr()); + removeIfExists(depTmpName); + removeIfExists(pDepFile->first); + removeIfExists(regFileName); + cleanPath(); + return 1; + } + removeIfExists(depTmpName); + } + + return 0; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/source/options.cxx b/idlc/source/options.cxx new file mode 100644 index 000000000..0fd06cc9f --- /dev/null +++ b/idlc/source/options.cxx @@ -0,0 +1,424 @@ +/* -*- 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 <string_view> + +#include <options.hxx> + +#include <osl/diagnose.h> +#include <rtl/string.hxx> +#include <rtl/strbuf.hxx> + +#include <rtl/ustring.hxx> +#include <osl/file.hxx> +#include <o3tl/char16_t2wchar_t.hxx> +#include <o3tl/string_view.hxx> + +#ifdef _WIN32 +# if !defined WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +# endif +# include <windows.h> +#endif + +#include <stdio.h> +#include <string.h> + + +Options::Options(char const * progname) + : m_program(progname), m_stdin(false), m_verbose(false), m_quiet(false) +{ +} + +Options::~Options() +{ +} + +// static +bool Options::checkArgument (std::vector< std::string > & rArgs, char const * arg, size_t len) +{ + bool result = ((arg != nullptr) && (len > 0)); + OSL_PRECOND(result, "idlc::Options::checkArgument(): invalid arguments"); + if (!result) + return false; + + switch(arg[0]) + { + case '@': + result = len > 1; + if (result) + { + // "@<cmdfile>" + result = Options::checkCommandFile (rArgs, &(arg[1])); + } + break; + case '-': + result = len > 1; + if (result) + { + // "-<option>" + switch (arg[1]) + { + case 'O': + case 'M': + case 'I': + case 'D': + { + // "-<option>[<param>] + std::string option(&(arg[0]), 2); + rArgs.push_back(option); + if (len > 2) + { + // "-<option><param>" + std::string param(&(arg[2]), len - 2); + rArgs.push_back(param); + } + break; + } + default: + // "-<option>" ([long] option, w/o param) + rArgs.emplace_back(arg, len); + break; + } + } + break; + default: + // "<param>" + rArgs.emplace_back(arg, len); + break; + } + return result; +} + +// static +bool Options::checkCommandFile (std::vector< std::string > & rArgs, char const * filename) +{ + FILE * fp = fopen(filename, "r"); + if (fp == nullptr) + { + fprintf(stderr, "ERROR: can't open command file \"%s\"\n", filename); + return false; + } + + std::string buffer; + buffer.reserve(256); + + bool quoted = false; + int c = EOF; + while ((c = fgetc(fp)) != EOF) + { + switch(c) + { + case '\"': + quoted = !quoted; + break; + case ' ': + case '\t': + case '\r': + case '\n': + if (!quoted) + { + if (!buffer.empty()) + { + // append current argument. + if (!Options::checkArgument(rArgs, buffer.c_str(), buffer.size())) + { + (void) fclose(fp); + return false; + } + buffer.clear(); + } + break; + } + [[fallthrough]]; + default: + buffer.push_back(sal::static_int_cast<char>(c)); + break; + } + } + if (!buffer.empty()) + { + // append unterminated argument. + if (!Options::checkArgument(rArgs, buffer.c_str(), buffer.size())) + { + (void) fclose(fp); + return false; + } + buffer.clear(); + } + return (fclose(fp) == 0); +} + +bool Options::badOption(char const * reason, std::string const & rArg) +{ + if (reason != nullptr) + { + OString message = OString::Concat(reason) + " option '" + rArg.c_str() + "'"; + throw IllegalArgument(message); + } + return false; +} + +bool Options::setOption(char const * option, std::string const & rArg) +{ + bool result = (0 == strcmp(option, rArg.c_str())); + if (result) + m_options[rArg.c_str()] = OString(rArg.c_str(), rArg.size()); + return result; +} + +#ifdef _WIN32 +/* Helper function to convert windows paths including spaces, brackets etc. into + a windows short Url. The ucpp preprocessor has problems with such paths and returns + with error. +*/ +static OString convertIncPathtoShortWindowsPath(const OString& incPath) { + OUString path = OStringToOUString(incPath, RTL_TEXTENCODING_UTF8); + + std::vector<sal_Unicode> vec(path.getLength() + 1); + //GetShortPathNameW only works if the file can be found! + const DWORD len = GetShortPathNameW( + o3tl::toW(path.getStr()), o3tl::toW(vec.data()), path.getLength() + 1); + + if (len > 0) + { + OUString ret(vec.data(), len); + return OUStringToOString(ret, RTL_TEXTENCODING_UTF8); + } + + return incPath; +} +#endif + +bool Options::initOptions(std::vector< std::string > & rArgs) +{ + std::vector< std::string >::const_iterator first = rArgs.begin(), last = rArgs.end(); + for (; first != last; ++first) + { + if ((*first)[0] != '-') + { + OString filename((*first).c_str(), (*first).size()); + OString tmp(filename.toAsciiLowerCase()); + if (tmp.lastIndexOf(".idl") != (tmp.getLength() - 4)) + { + throw IllegalArgument("'" + filename + "' is not a valid input file, only '*.idl' files will be accepted"); + } + m_inputFiles.push_back(filename); + continue; + } + + std::string const option(*first); + switch((*first)[1]) + { + case 'O': + { + if ((++first == last) || ((*first)[0] == '-')) + { + return badOption("invalid", option); + } + OString param((*first).c_str(), (*first).size()); + m_options["-O"] = param; + break; + } + case 'M': + { + if ((++first == last) || ((*first)[0] == '-')) + { + return badOption("invalid", option); + } + OString param((*first).c_str(), (*first).size()); + m_options["-M"] = param; + break; + } + case 'I': + { + if ((++first == last) || ((*first)[0] == '-')) + { + return badOption("invalid", option); + } + OString param((*first).c_str(), (*first).size()); + { + // quote param token(s). + OStringBuffer buffer; + sal_Int32 k = 0; + do + { + if (!buffer.isEmpty()) + buffer.append(' '); +// buffer.append("-I\""); +#ifdef _WIN32 + OString incpath = convertIncPathtoShortWindowsPath(param.getToken(0, ';', k)); +#else + std::string_view incpath = o3tl::getToken(param, 0, ';', k); +#endif + buffer.append(incpath); +// buffer.append("\""); + } while (k != -1); + param = buffer.makeStringAndClear(); + } + if (m_options.count("-I") > 0) + { + // append param. + param = m_options["-I"] + " " + param; + } + m_options["-I"] = param; + break; + } + case 'D': + { + if ((++first == last) || ((*first)[0] == '-')) + { + return badOption("invalid", option); + } + OString param = OString::Concat("-D") + std::string_view((*first).c_str(), (*first).size()); + if (m_options.count("-D") > 0) + { + param = m_options["-D"] + " " + param; + } + m_options["-D"] = param; + break; + } + case 'C': + { + if (!setOption("-C", option)) + { + return badOption("invalid", option); + } + break; + } + case 'c': + { + if (!setOption("-cid", option)) + { + return badOption("invalid", option); + } + break; + } + case 'q': + { + if (!setOption("-quiet", option)) + { + return badOption("invalid", option); + } + m_quiet = true; + break; + } + case 'v': + { + if (!setOption("-verbose", option)) + { + return badOption("invalid", option); + } + m_verbose = true; + break; + } + case 'w': + { + if (!(setOption("-w", option) || setOption("-we", option))) + { + return badOption("invalid", option); + } + break; + } + case 'h': + case '?': + { + if (!(setOption("-h", option) || setOption("-?", option))) + { + return badOption("invalid", option); + } + { + (void) fprintf(stdout, "%s", prepareHelp().getStr()); + return false; + } + // break; // Unreachable + } + case 's': + { + if (!setOption("-stdin", option)) + { + return badOption("invalid", option); + } + m_stdin = true; + break; + } + default: + return badOption("unknown", option); + } + } + return true; +} + +OString Options::prepareHelp() const +{ + OString help = "\nusing: " + + m_program + " [-options] <file_1> ... <file_n> | @<filename> | -stdin\n" + " <file_n> = file_n specifies one or more idl files.\n" + " Only files with the extension '.idl' are valid.\n" + " @<filename> = filename specifies the name of a command file.\n" + " -stdin = read idl file from standard input.\n" + " Options:\n" + " -O<path> = path specifies the output directory.\n" + " The generated output is a registry file with\n" + " the same name as the idl input file (or 'stdin'\n" + " for -stdin).\n" + " -M<path> = path specifies the output directory for deps.\n" + " Generate GNU make dependency files with the\n" + " same name as the idl input file.\n" + " -I<path> = path specifies a directory where include\n" + " files will be searched by the preprocessor.\n" + " Multiple directories can be combined with ';'.\n" + " -D<name> = name defines a macro for the preprocessor.\n" + " -C = generate complete type information, including\n" + " documentation.\n" + " -cid = check if identifiers fulfill the UNO naming\n" + " requirements.\n" + " -quiet = no output.\n" + " -verbose = verbose output.\n" + " -w = display warning messages.\n" + " -we = treat warnings as errors.\n" + " -h|-? = print this help message and exit.\n\n" + + prepareVersion(); + + return help; +} + +OString Options::prepareVersion() const +{ + return m_program + " Version 1.1\n\n"; +} + + +bool Options::isValid(const OString& option) const +{ + return (m_options.count(option) > 0); +} + +const OString& Options::getOption(const OString& option) +{ + if (!isValid(option)) + { + throw IllegalArgument("Option is not valid or currently not set."); + } + return m_options[option]; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/source/parser.y b/idlc/source/parser.y new file mode 100644 index 000000000..29654c32b --- /dev/null +++ b/idlc/source/parser.y @@ -0,0 +1,2737 @@ +/* -*- 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 . + */ + +/* + * parser.yy - BISON grammar for IDLC 1.0 + */ + +%{ +#include <string.h> + +#include <idlc.hxx> +#include <errorhandler.hxx> +#include <fehelper.hxx> +#include <astexpression.hxx> +#include <astconstants.hxx> +#include <astconstant.hxx> +#include <astbasetype.hxx> +#include <asttypedef.hxx> +#include <astexception.hxx> +#include <astmember.hxx> +#include <astenum.hxx> +#include <astsequence.hxx> +#include <astattribute.hxx> +#include <astoperation.hxx> +#include <astparameter.hxx> +#include <astinterfacemember.hxx> +#include <astservicemember.hxx> +#include <astobserves.hxx> +#include <astneeds.hxx> + +#include <aststructinstance.hxx> + +#include "attributeexceptions.hxx" + +#include <rtl/string.hxx> +#include <osl/diagnose.h> + +#include <algorithm> +#include <vector> + + +#define YYDEBUG 1 +#define YYERROR_VERBOSE 1 + +extern int yylex(void); +static void yyerror(char const *); + +static void checkIdentifier(OString const * id) +{ + static short check = 0; + if (check == 0) { + if (idlc()->getOptions()->isValid("-cid")) + check = 1; + else + check = 2; + } + + if ( id->indexOf('_') >= 0 ) + if ( (id->pData->buffer[0] >= 97 && id->pData->buffer[0] <= 122) + || id->pData->buffer[0] == '_') { + if (check == 1) { + OString msg = "mismatched identifier '" + *id + "'"; + ErrorHandler::syntaxError(idlc()->getParseState(), + idlc()->getLineNumber(), + msg.getStr()); + } + else + ErrorHandler::warning0(WarningCode::WrongNamingConvention, id->getStr()); + } +} + +static void reportDoubleMemberDeclarations( + AstInterface::DoubleMemberDeclarations const & doubleMembers) +{ + for (auto const& doubleMember : doubleMembers) + { + ErrorHandler::error2(ErrorCode::DoubleMember, doubleMember.first, doubleMember.second); + } +} + +static void addInheritedInterface( + AstInterface * ifc, OString const & name, bool optional, + OUString const & documentation) +{ + AstDeclaration * decl = ifc->lookupByName(name); + AstDeclaration const * resolved = resolveTypedefs(decl); + if (resolved != nullptr && resolved->getNodeType() == NT_interface) { + if (ErrorHandler::checkPublished(decl)) { + if (!static_cast< AstInterface const * >(resolved)->isDefined()) { + ErrorHandler::inheritanceError( + NT_interface, &ifc->getScopedName(), decl); + } else { + AstInterface::DoubleDeclarations doubleDecls( + ifc->checkInheritedInterfaceClashes( + static_cast< AstInterface const * >(resolved), + optional)); + if (doubleDecls.interfaces.empty() + && doubleDecls.members.empty()) + { + ifc->addInheritedInterface( + static_cast< AstType * >(decl), optional, + documentation); + } else { + for (auto const& elem : doubleDecls.interfaces) + { + ErrorHandler::error1( + ErrorCode::DoubleInheritance, elem); + } + reportDoubleMemberDeclarations(doubleDecls.members); + } + } + } + } else { + ErrorHandler::lookupError( + ErrorCode::InterfaceMemberLookup, name, scopeAsDecl(ifc)); + } +} + +static AstDeclaration const * createNamedType( + OString const * scopedName, DeclList const * typeArgs) +{ + AstDeclaration * decl = idlc()->scopes()->topNonNull()->lookupByName( + *scopedName); + AstDeclaration const * resolved = resolveTypedefs(decl); + if (decl == nullptr) { + ErrorHandler::lookupError(*scopedName); + } else if (!ErrorHandler::checkPublished(decl)) { + decl = nullptr; + } else if (resolved->getNodeType() == NT_struct) { + if (static_cast< AstStruct const * >(resolved)->getTypeParameterCount() + != (typeArgs == nullptr ? 0 : typeArgs->size())) + { + ErrorHandler::error0(ErrorCode::WrongNumberOfTypeArguments); + decl = nullptr; + } else if (typeArgs != nullptr) { + AstScope * global = idlc()->scopes()->bottom(); + AstDeclaration * inst = new AstStructInstance( + static_cast< AstType * >(decl), typeArgs, global); + decl = global->addDeclaration(inst); + if (decl != inst) { + delete inst; + } + } + } else if (decl->isType()) { + if (typeArgs != nullptr) { + ErrorHandler::error0(ErrorCode::WrongNumberOfTypeArguments); + decl = nullptr; + } + } else { + ErrorHandler::noTypeError(decl); + decl = nullptr; + } + delete scopedName; + delete typeArgs; + return decl; +} + +static bool includes(AstDeclaration const * type1, AstDeclaration const * type2) { + OSL_ASSERT(type2 != nullptr); + if (type1 != nullptr) { + if (type1->getNodeType() == NT_instantiated_struct) { + AstStructInstance const * inst + = static_cast< AstStructInstance const * >(type1); + if (inst->getTypeTemplate() == type2) { + return true; + } + for (DeclList::const_iterator i(inst->getTypeArgumentsBegin()); + i != inst->getTypeArgumentsEnd(); ++i) + { + if (includes(*i, type2)) { + return true; + } + } + } else if (type1 == type2) { + return true; + } + } + return false; +} + +// Suppress any warnings from generated code: +#if defined _MSC_VER +#pragma warning(disable: 4702) // unreachable code +#endif +%} +/* + * Declare the type of values in the grammar + */ +%union { + ExprType etval; /* Expression type */ + AstDeclaration* dclval; /* Declaration */ + AstDeclaration const * cdclval; + DeclList * dclsval; + AstExpression* exval; /* expression value */ + FeDeclarator* fdval; /* declarator value */ + FeDeclList* dlval; /* declarator list value */ + FeInheritanceHeader* ihval; /* inheritance header value */ + OString* sval; /* OString value */ + std::vector< OString > * svals; + char* strval; /* char* value */ + bool bval; /* sal_Boolean* value */ + sal_Int64 ival; /* sal_Int64 value */ + sal_uInt64 uval; /* sal_uInt64 value */ + sal_uInt32 ulval; /* sal_uInt32 value */ + double dval; /* double value */ + float fval; /* float value */ + std::list< OString >* slval; /* StringList value */ + AttributeExceptions::Part attexcpval; + AttributeExceptions attexcval; +} + +/* + * Token types: These are returned by the lexer + */ + +%token <sval> IDL_IDENTIFIER +%token IDL_ATTRIBUTE +%token IDL_BOUND +%token IDL_CONST +%token IDL_CONSTANTS +%token IDL_CONSTRAINED +%token IDL_ENUM +%token IDL_EXCEPTION +%token IDL_INTERFACE +%token IDL_MAYBEAMBIGUOUS +%token IDL_MAYBEDEFAULT +%token IDL_MAYBEVOID +%token IDL_MODULE +%token IDL_NEEDS +%token IDL_OBSERVES +%token IDL_OPTIONAL +%token IDL_PROPERTY +%token IDL_RAISES +%token IDL_READONLY +%token IDL_REMOVABLE +%token IDL_SERVICE +%token IDL_SEQUENCE +%token IDL_SINGLETON +%token IDL_STRUCT +%token IDL_TYPEDEF +%token IDL_TRANSIENT + +%token IDL_ANY +%token IDL_CHAR +%token IDL_BOOLEAN +%token IDL_BYTE +%token IDL_DOUBLE +%token IDL_FLOAT +%token IDL_HYPER +%token IDL_LONG +%token IDL_SHORT +%token IDL_VOID +%token IDL_STRING +%token IDL_TYPE +%token IDL_UNSIGNED + +%token IDL_TRUE +%token IDL_FALSE + +%token IDL_IN +%token IDL_OUT +%token IDL_INOUT + +%token IDL_GET +%token IDL_SET + +%token IDL_PUBLISHED + +%token IDL_ELLIPSIS + +%token <strval> IDL_LEFTSHIFT +%token <strval> IDL_RIGHTSHIFT +%token <strval> IDL_SCOPESEPARATOR + +%token <ival> IDL_INTEGER_LITERAL +%token <uval> IDL_INTEGER_ULITERAL +%token <dval> IDL_FLOATING_PT_LITERAL + +/* + * These are production names: + */ +%type <dclval> type_dcl +%type <dclval> exception_name +%type <cdclval> constructed_type_spec enum_type op_type_spec +%type <cdclval> sequence_type_spec simple_type_spec struct_type +%type <cdclval> type_spec +%type <cdclval> fundamental_type type_arg type_or_parameter +%type <dclsval> opt_raises raises exception_list +%type <attexcpval> opt_attribute_get_raises attribute_get_raises +%type <attexcpval> opt_attribute_set_raises attribute_set_raises +%type <dclsval> opt_type_args type_args + +%type <sval> identifier +%type <sval> interface_decl +%type <sval> scoped_name inheritance_spec +%type <slval> scoped_names at_least_one_scoped_name + +%type <etval> const_type integer_type char_type boolean_type +%type <etval> floating_pt_type any_type signed_int string_type +%type <etval> unsigned_int base_type_spec byte_type type_type + +%type <exval> expression const_expr or_expr xor_expr and_expr +%type <exval> add_expr mult_expr unary_expr primary_expr shift_expr +%type <exval> literal + +%type <fdval> declarator +%type <dlval> declarators at_least_one_declarator + +%type <ihval> exception_header structure_header interfaceheader + +%type <ulval> flag_header opt_attrflags opt_attrflag +%type <ulval> direction service_interface_header service_service_header + +%type <bval> optional_inherited_interface opt_rest opt_service_body + +%type <attexcval> opt_attribute_block attribute_block_rest opt_attribute_raises + +%type <svals> opt_type_params type_params + +%% +/* + * Grammar start here + */ +start : definitions; + +definitions : + definition definitions + | /* EMPTY */ + ; + +definition : + opt_published publishable_definition + | module_dcl + { + idlc()->setParseState(PS_ModuleDeclSeen); + } + ';' + { + idlc()->setParseState(PS_NoState); + } + | error ';' + { + yyerror("definitions"); + yyerrok; + } + ; + +opt_published: + IDL_PUBLISHED { idlc()->setPublished(true); } + | /* empty */ { idlc()->setPublished(false); } + ; + +publishable_definition: + type_dcl + { + idlc()->setParseState(PS_TypeDeclSeen); + } + ';' + { + idlc()->setParseState(PS_NoState); + } + | exception_dcl + { + idlc()->setParseState(PS_ExceptionDeclSeen); + } + ';' + { + idlc()->setParseState(PS_NoState); + } + | interface + { + idlc()->setParseState(PS_InterfaceDeclSeen); + } + ';' + { + idlc()->setParseState(PS_NoState); + } + | service_dcl + { + idlc()->setParseState(PS_ServiceDeclSeen); + } + ';' + { + idlc()->setParseState(PS_NoState); + } + | singleton_dcl + { + idlc()->setParseState(PS_SingletonDeclSeen); + } + ';' + { + idlc()->setParseState(PS_NoState); + } + | constants_dcl + { + idlc()->setParseState(PS_ConstantsDeclSeen); + } + ';' + { + idlc()->setParseState(PS_NoState); + } + ; + +module_dcl : + IDL_MODULE + { + idlc()->setParseState(PS_ModuleSeen); + idlc()->setPublished(false); + } + identifier + { + idlc()->setParseState(PS_ModuleIDSeen); + checkIdentifier($3); + + AstScope* pScope = idlc()->scopes()->topNonNull(); + AstModule* pModule = nullptr; + + if ( pScope ) + { + pModule = new AstModule(*$3, pScope); + if( AstDeclaration* pExists = pScope->lookupForAdd(pModule) ) + { + pExists->setInMainfile(idlc()->isInMainFile()); + pExists->setFileName(pModule->getFileName()); + if (pExists->isPredefined()) + { + pExists->setPredefined(false); + if (pExists->getDocumentation().getLength() == 0 && + pModule->getDocumentation().getLength() > 0) + { + pExists->setDocumentation(pModule->getDocumentation()); + } + } + delete(pModule); + pModule = static_cast<AstModule*>(pExists); + } else + { + pScope->addDeclaration(pModule); + } + idlc()->scopes()->push(pModule); + } + delete $3; + } + '{' + { + idlc()->setParseState(PS_ModuleSqSeen); + } + definitions + { + idlc()->setParseState(PS_ModuleBodySeen); + } + '}' + { + idlc()->setParseState(PS_ModuleQsSeen); + /* + * Finished with this module - pop it from the scope stack + */ + idlc()->scopes()->pop(); + } + ; + +interface : + interface_dcl + | forward_dcl + ; + +interface_decl : + IDL_INTERFACE + { + idlc()->setParseState(PS_InterfaceSeen); + } + identifier + { + idlc()->setParseState(PS_InterfaceIDSeen); + checkIdentifier($3); + $$ = $3; + } + ; + +forward_dcl : + interface_decl + { + idlc()->setParseState(PS_ForwardDeclSeen); + + AstScope* pScope = idlc()->scopes()->topNonNull(); + AstInterface* pForward = nullptr; + AstDeclaration* pDecl = nullptr; + + /* + * Make a new forward interface node and add it to its enclosing scope + */ + if ( pScope && $1 ) + { + pForward = new AstInterface(*$1, nullptr, pScope); + + pDecl = pScope->lookupByName(pForward->getScopedName()); + if ( pDecl ) + { + if ( (pDecl != pForward) && + (pDecl->getNodeType() == NT_interface) ) + { + delete pForward; + } else + { + ErrorHandler::error2(ErrorCode::RedefScope, scopeAsDecl(pScope), pDecl); + } + } else + { + /* + * Add the interface to its definition scope + */ + pScope->addDeclaration(pForward); + } + } + delete $1; + } + ; + +interface_dcl : + interfaceheader + { + idlc()->setParseState(PS_InterfaceHeadSeen); + + AstScope* pScope = idlc()->scopes()->topNonNull(); + AstInterface* pInterface = nullptr; + AstInterface* pForward = nullptr; + + /* + * Make a new interface node and add it to its enclosing scope + */ + if ( pScope && $1 ) + { + pInterface = new AstInterface( + *$1->getName(), + static_cast< AstInterface const * >(resolveTypedefs($1->getInherits())), pScope); + if ( AstDeclaration* pDecl = pScope->lookupByName(pInterface->getScopedName()) ) + { + /* + * See if we're defining a forward declared interface. + */ + if (pDecl->getNodeType() == NT_interface) + { + pForward = static_cast<AstInterface*>(pDecl); + if ( !pForward->isDefined() ) + { + /* + * Check if redefining in same scope + */ + if ( pForward->getScope() != pScope ) + { + if ( pForward->getScopedName() != pInterface->getScopedName() ) + { + ErrorHandler::error3(ErrorCode::ScopeConflict, + pInterface, pForward, scopeAsDecl(pScope)); + } + } + else if ( !pInterface->isPublished() + && pForward->isPublished() ) + { + ErrorHandler::error0(ErrorCode::PublishedForward); + } + /* + * All OK, set full definition + */ + else + { + pForward->forwardDefined(*pInterface); + delete pInterface; + pInterface = pForward; + } + } else { + // special handling for XInterface because it is predefined + if ( pForward->isPredefined() && + pForward->getScopedName() == "com::sun::star::uno::XInterface") + { + /* replace the predefined XInterface */ + *pForward = *pInterface; + delete pInterface; + pInterface = pForward; + } + + } + } + } else + { + /* + * Add the interface to its definition scope + */ + pScope->addDeclaration(pInterface); + } + } + /* + * Push it on the scope stack + */ + idlc()->scopes()->push(pInterface); + delete $1; + } + '{' + { + idlc()->setParseState(PS_InterfaceSqSeen); + } + exports + { + AstInterface * ifc = static_cast< AstInterface * >( + idlc()->scopes()->topNonNull()); + if (!ifc->hasMandatoryInheritedInterfaces() + && ifc->getScopedName() != "com::sun::star::uno::XInterface") + { + addInheritedInterface( + ifc, "::com::sun::star::uno::XInterface", false, + OUString()); + } + ifc->setDefined(); + idlc()->setParseState(PS_InterfaceBodySeen); + } + '}' + { + idlc()->setParseState(PS_InterfaceQsSeen); + /* + * Done with this interface - pop it off the scopes stack + */ + idlc()->scopes()->pop(); + } + | error '}' + { + yyerror("interface definition"); + yyerrok; + } + ; + +interfaceheader : + interface_decl inheritance_spec + { + idlc()->setParseState(PS_InheritSpecSeen); + + $$ = new FeInheritanceHeader(NT_interface, $1, $2, nullptr); + delete $2; + } + ; + +inheritance_spec : + ':' + { + idlc()->setParseState(PS_InheritColonSeen); + } + scoped_name + { + $$ = $3; + } + | /* EMPTY */ + { + $$ = nullptr; + } + ; + +exports : + exports export + | /* EMPTY */ + ; + +export : + attribute + { + idlc()->setParseState(PS_AttributeDeclSeen); + } + ';' + { + idlc()->setParseState(PS_NoState); + } + | operation + { + idlc()->setParseState(PS_OperationDeclSeen); + } + ';' + { + idlc()->setParseState(PS_NoState); + } + | interface_inheritance_decl + { + idlc()->setParseState(PS_InterfaceInheritanceDeclSeen); + } + ';' + { + idlc()->setParseState(PS_NoState); + } + ; + +attribute : + flag_header + simple_type_spec + { + idlc()->setParseState(PS_AttrTypeSeen); + } + declarator + { + idlc()->setParseState(PS_AttrCompleted); + if (($1 & ~(AF_BOUND | AF_READONLY)) != AF_ATTRIBUTE) { + ErrorHandler::flagError(ErrorCode::BadAttributeFlags, $1); + } + AstInterface * scope = static_cast< AstInterface * >( + idlc()->scopes()->top()); + AstAttribute * attr = new AstAttribute( + $1, FeDeclarator::compose($2), $4->getName(), scope); + delete $4; + AstInterface::DoubleMemberDeclarations doubleMembers( + scope->checkMemberClashes(attr)); + if (doubleMembers.empty()) { + scope->addMember(attr); + } else { + reportDoubleMemberDeclarations(doubleMembers); + } + idlc()->scopes()->push(attr); + } + opt_attribute_block + { + static_cast< AstAttribute * >(idlc()->scopes()->top())->setExceptions( + $6.get.documentation, $6.get.exceptions, $6.set.documentation, + $6.set.exceptions); + delete $6.get.documentation; + delete $6.get.exceptions; + delete $6.set.documentation; + delete $6.set.exceptions; + idlc()->scopes()->pop(); + } + ; + +flag_header : + '[' opt_attrflags ']' + { + idlc()->setParseState(PS_FlagHeaderSeen); + $$ = $2; + } + ; + +opt_attrflags : + opt_attrflags ',' opt_attrflag + { + if ( ($1 & $3) == $3 ) + ErrorHandler::flagError(ErrorCode::DefinedAttributeFlag, $3); + + $$ = $1 | $3; + } + | opt_attrflag + { + $$ = $1; + } + ; + +opt_attrflag : + IDL_ATTRIBUTE + { + idlc()->setParseState(PS_AttrSeen); + $$ = AF_ATTRIBUTE; + } + | IDL_PROPERTY + { + idlc()->setParseState(PS_PropertySeen); + $$ = AF_PROPERTY; + } + | IDL_READONLY + { + idlc()->setParseState(PS_ReadOnlySeen); + $$ = AF_READONLY; + } + | IDL_OPTIONAL + { + idlc()->setParseState(PS_OptionalSeen); + $$ = AF_OPTIONAL; + } + | IDL_MAYBEVOID + { + idlc()->setParseState(PS_MayBeVoidSeen); + $$ = AF_MAYBEVOID; + } + | IDL_BOUND + { + idlc()->setParseState(PS_BoundSeen); + $$ = AF_BOUND; + } + | IDL_CONSTRAINED + { + idlc()->setParseState(PS_ConstrainedSeen); + $$ = AF_CONSTRAINED; + } + | IDL_TRANSIENT + { + idlc()->setParseState(PS_TransientSeen); + $$ = AF_TRANSIENT; + } + | IDL_MAYBEAMBIGUOUS + { + idlc()->setParseState(PS_MayBeAmbiguousSeen); + $$ = AF_MAYBEAMBIGUOUS; + } + | IDL_MAYBEDEFAULT + { + idlc()->setParseState(PS_MayBeDefaultSeen); + $$ = AF_MAYBEDEFAULT; + } + | IDL_REMOVABLE + { + idlc()->setParseState(PS_RemoveableSeen); + $$ = AF_REMOVABLE; + } + | error ']' + { + yyerror("unknown property|attribute flag"); + yyerrok; + } + ; + +opt_attribute_block: + '{' attribute_block_rest { $$ = $2; } + | /* empty */ + { + $$.get.documentation = nullptr; + $$.get.exceptions = nullptr; + $$.set.documentation = nullptr; + $$.set.exceptions = nullptr; + } + ; + +attribute_block_rest: + opt_attribute_raises '}' + | error '}' + { + yyerror("bad attribute raises block"); + yyerrok; + $$.get.documentation = nullptr; + $$.get.exceptions = nullptr; + $$.set.documentation = nullptr; + $$.set.exceptions = nullptr; + } + ; + +opt_attribute_raises: + attribute_get_raises + opt_attribute_set_raises + { + $$.get = $1; + $$.set = $2; + } + | attribute_set_raises + opt_attribute_get_raises + { + $$.get = $2; + $$.set = $1; + } + | /* empty */ + { + $$.get.documentation = nullptr; + $$.get.exceptions = nullptr; + $$.set.documentation = nullptr; + $$.set.exceptions = nullptr; + } + ; + +opt_attribute_get_raises: + attribute_get_raises + | /* empty */ { $$.documentation = nullptr; $$.exceptions = nullptr; } + ; + +attribute_get_raises: + IDL_GET raises ';' + { + $$.documentation = new OUString( + OStringToOUString( + idlc()->getDocumentation(), RTL_TEXTENCODING_UTF8)); + $$.exceptions = $2; + } + ; + +opt_attribute_set_raises: + attribute_set_raises + | /* empty */ { $$.documentation = nullptr; $$.exceptions = nullptr; } + ; + +attribute_set_raises: + IDL_SET + { + if (static_cast< AstAttribute * >(idlc()->scopes()->top())-> + isReadonly()) + { + ErrorHandler::error0(ErrorCode::ReadOnlyAttributeSetExceptions); + } + } + raises ';' + { + $$.documentation = new OUString( + OStringToOUString( + idlc()->getDocumentation(), RTL_TEXTENCODING_UTF8)); + $$.exceptions = $3; + } + ; + +operation : + op_type_spec + { + idlc()->setParseState(PS_OpTypeSeen); + } + identifier + { + idlc()->setParseState(PS_OpIDSeen); + checkIdentifier($3); + + AstInterface * pScope = static_cast< AstInterface * >( + idlc()->scopes()->top()); + AstOperation* pOp = nullptr; + + /* + * Create a node representing an operation on an interface + * and add it to its enclosing scope + */ + if ( pScope && $1 ) + { + AstType const *pType = static_cast<AstType const *>($1); + if ( !pType || (pType->getNodeType() == NT_exception) ) + { + // type ERROR + } else + { + pOp = new AstOperation(pType, *$3, pScope); + + AstInterface::DoubleMemberDeclarations doubleMembers( + pScope->checkMemberClashes(pOp)); + if (doubleMembers.empty()) { + pScope->addMember(pOp); + } else { + reportDoubleMemberDeclarations(doubleMembers); + } + } + } + delete $3; + /* + * Push the operation scope onto the scopes stack + */ + idlc()->scopes()->push(pOp); + } + '(' + { + idlc()->setParseState(PS_OpSqSeen); + } + parameters + { + idlc()->setParseState(PS_OpParsCompleted); + } + ')' + { + idlc()->setParseState(PS_OpQsSeen); + } + opt_raises + { + AstScope* pScope = idlc()->scopes()->topNonNull(); + AstOperation* pOp = nullptr; + /* + * Add exceptions and context to the operation + */ + if ( pScope && pScope->getScopeNodeType() == NT_operation) + { + pOp = static_cast<AstOperation*>(pScope); + + if ( pOp ) + pOp->setExceptions($11); + } + delete $11; + /* + * Done with this operation. Pop its scope from the scopes stack + */ + idlc()->scopes()->pop(); + } + ; + +op_type_spec : + simple_type_spec + | IDL_VOID + { + $$ = idlc()->scopes()->bottom()->lookupPrimitiveType(ET_void); + } + ; + +parameters : + parameter + | parameters + ',' + { + idlc()->setParseState(PS_OpParCommaSeen); + } + parameter + | /* EMPTY */ + | error ',' + { + yyerror("parameter definition"); + yyerrok; + } + ; + +parameter : + '[' + direction + ']' + { + idlc()->setParseState(PS_OpParDirSeen); + } + simple_type_spec + { + idlc()->setParseState(PS_OpParTypeSeen); + } + opt_rest + declarator + { + idlc()->setParseState(PS_OpParDeclSeen); + + AstOperation * pScope = static_cast< AstOperation * >( + idlc()->scopes()->top()); + AstParameter* pParam = nullptr; + + /* + * Create a node representing an argument to an operation + * Add it to the enclosing scope (the operation scope) + */ + if ( pScope && $5 && $8 ) + { + AstType const * pType = FeDeclarator::compose($5); + if ( pType ) + { + if (pScope->isConstructor() && $2 != DIR_IN) { + ErrorHandler::error0(ErrorCode::ConstructorParameterNotIn); + } + if (pScope->isVariadic()) { + ErrorHandler::error0(ErrorCode::RestParameterNotLast); + } + if ($7) { + AstDeclaration const * type = resolveTypedefs(pType); + if (type->getNodeType() != NT_predefined + || (static_cast< AstBaseType const * >(type)-> + getExprType() != ET_any)) + { + ErrorHandler::error0(ErrorCode::RestParameterNotAny); + } + if (pScope->isConstructor()) { + if (pScope->getIteratorBegin() + != pScope->getIteratorEnd()) + { + ErrorHandler::error0( + ErrorCode::ConstructorRestParameterNotFirst); + } + } else { + ErrorHandler::error0(ErrorCode::MethodHasRestParameter); + } + } + + pParam = new AstParameter( + static_cast< Direction >($2), $7, pType, $8->getName(), + pScope); + + if ( !$8->checkType($5) ) + { + // WARNING + } + + pScope->addDeclaration(pParam); + } + } + } + | error + simple_type_spec + { + idlc()->setParseState(PS_NoState); + yyerrok; + } + ; + +direction : + IDL_IN + { + $$ = DIR_IN; + } + | IDL_OUT + { + $$ = DIR_OUT; + } + | IDL_INOUT + { + $$ = DIR_INOUT; + } + ; + +opt_rest: + IDL_ELLIPSIS + { + $$ = true; + } + | /* empty */ + { + $$ = false; + } + ; + +opt_raises: + raises + | /* empty */ + { + $$ = nullptr; + } + ; + +raises: + IDL_RAISES + { + idlc()->setParseState(PS_RaiseSeen); + } + '(' + { + idlc()->setParseState(PS_RaiseSqSeen); + } + exception_list + ')' + { + idlc()->setParseState(PS_RaiseQsSeen); + $$ = $5; + } + ; + +exception_list: + exception_name + { + $$ = new DeclList; + $$->push_back($1); + } + | exception_list ',' exception_name + { + $1->push_back($3); + $$ = $1; + } + ; + +exception_name: + scoped_name + { + // The topmost scope is either an AstOperation (for interface methods + // and service constructors) or an AstAttribute (for interface + // attributes), so look up exception names in the next-to-topmost scope: + AstDeclaration * decl = idlc()->scopes()->nextToTop()->lookupByName( + *$1); + if (decl == nullptr) { + ErrorHandler::lookupError(*$1); + } else if (!ErrorHandler::checkPublished(decl)) { + decl = nullptr; + } else if (decl->getNodeType() != NT_exception) { + ErrorHandler::error1(ErrorCode::IllegalRaises, decl); + decl = nullptr; + } + delete $1; + $$ = decl; + } + ; + +interface_inheritance_decl: + optional_inherited_interface + IDL_INTERFACE + { + idlc()->setParseState(PS_ServiceIFHeadSeen); + } + scoped_name + { + AstInterface * ifc = static_cast< AstInterface * >( + idlc()->scopes()->top()); + if (ifc->usesSingleInheritance()) { + ErrorHandler::error0(ErrorCode::MixedInheritance); + } else { + addInheritedInterface( + ifc, *$4, $1, + OStringToOUString( + idlc()->getDocumentation(), RTL_TEXTENCODING_UTF8)); + } + delete $4; + } + ; + +optional_inherited_interface: + '[' IDL_OPTIONAL ']' { $$ = true; } + | /* EMPTY */ { $$ = false; } + ; + +constants_exports : + constants_export constants_exports + | /* EMPTY */ + ; + +constants_export : + IDL_CONST + { + idlc()->setParseState(PS_ConstSeen); + } + const_type + { + idlc()->setParseState(PS_ConstTypeSeen); + } + identifier + { + idlc()->setParseState(PS_ConstIDSeen); + checkIdentifier($5); + } + '=' + { + idlc()->setParseState(PS_ConstAssignSeen); + } + expression + { + idlc()->setParseState(PS_ConstExprSeen); + + AstScope* pScope = idlc()->scopes()->topNonNull(); + AstConstant* pConstant = nullptr; + + if ( $9 && pScope ) + { + if ( !$9->coerce($3) ) + { + ErrorHandler::coercionError($9, $3); + } else + { + pConstant = new AstConstant($3, $9, *$5, pScope); + pScope->addDeclaration(pConstant); + } + } + delete $5; + + idlc()->setParseState(PS_ConstantDeclSeen); + } + ';' {}; + ; + +constants_dcl : + IDL_CONSTANTS + { + idlc()->setParseState(PS_ConstantsSeen); + } + identifier + { + idlc()->setParseState(PS_ConstantsIDSeen); + checkIdentifier($3); + } + '{' + { + idlc()->setParseState(PS_ConstantsSqSeen); + + AstScope* pScope = idlc()->scopes()->topNonNull(); + AstConstants* pConstants = nullptr; + + if ( pScope ) + { + pConstants = new AstConstants(*$3, pScope); + if( AstDeclaration* pExists = pScope->lookupForAdd(pConstants) ) + { + pExists->setInMainfile(idlc()->isInMainFile()); + delete(pConstants); + pConstants = static_cast<AstConstants*>(pExists); + } else + { + pScope->addDeclaration(pConstants); + } + idlc()->scopes()->push(pConstants); + } + delete $3; + } + constants_exports + { + idlc()->setParseState(PS_ConstantsBodySeen); + } + '}' + { + idlc()->setParseState(PS_ConstantsQsSeen); + /* + * Finished with this constants - pop it from the scope stack + */ + idlc()->scopes()->pop(); + } + ; + +expression : const_expr ; + +const_expr : or_expr ; + +or_expr : + xor_expr + | or_expr '|' xor_expr + { + $$ = new AstExpression(ExprComb::Or, $1, $3); + } + ; + +xor_expr : + and_expr + | xor_expr '^' and_expr + { + $$ = new AstExpression(ExprComb::Xor, $1, $3); + } + ; + +and_expr : + shift_expr + | and_expr '&' shift_expr + { + $$ = new AstExpression(ExprComb::And, $1, $3); + } + ; + +shift_expr : + add_expr + | shift_expr IDL_LEFTSHIFT add_expr + { + $$ = new AstExpression(ExprComb::Left, $1, $3); + } + | shift_expr IDL_RIGHTSHIFT add_expr + { + $$ = new AstExpression(ExprComb::Right, $1, $3); + } + ; + +add_expr : + mult_expr + | add_expr '+' mult_expr + { + $$ = new AstExpression(ExprComb::Add, $1, $3); + } + | add_expr '-' mult_expr + { + $$ = new AstExpression(ExprComb::Minus, $1, $3); + } + ; + +mult_expr : + unary_expr + | mult_expr '*' unary_expr + { + $$ = new AstExpression(ExprComb::Mul, $1, $3); + } + | mult_expr '/' unary_expr + { + $$ = new AstExpression(ExprComb::Div, $1, $3); + } + | mult_expr '%' unary_expr + { + $$ = new AstExpression(ExprComb::Mod, $1, $3); + } + ; + +unary_expr : + primary_expr + | '+' primary_expr + { + $$ = new AstExpression(ExprComb::UPlus, $2, nullptr); + } + | '-' primary_expr + { + $$ = new AstExpression(ExprComb::UMinus, $2, nullptr); + } + | '~' primary_expr + { + } + ; + +primary_expr : + scoped_name + { + /* + * An expression which is a scoped name is not resolved now, + * but only when it is evaluated (such as when it is assigned + * as a constant value) + */ + $$ = new AstExpression($1); + } + | literal + | '(' const_expr ')' + { + $$ = $2; + } + ; + +literal : + IDL_INTEGER_LITERAL + { + $$ = new AstExpression($1); + } + | IDL_INTEGER_ULITERAL + { + $$ = new AstExpression($1); + } + | IDL_FLOATING_PT_LITERAL + { + $$ = new AstExpression($1); + } + | IDL_TRUE + { + $$ = new AstExpression(sal_Int32(1), ET_boolean); + } + | IDL_FALSE + { + $$ = new AstExpression(sal_Int32(0), ET_boolean); + } + ; + +const_type : + integer_type + | byte_type + | boolean_type + | floating_pt_type + | scoped_name + { + AstScope* pScope = idlc()->scopes()->topNonNull(); + AstDeclaration const * type = nullptr; + + /* + * If the constant's type is a scoped name, it must resolve + * to a scalar constant type + */ + if ( pScope ) { + type = pScope->lookupByName(*$1); + if (type) { + if (!ErrorHandler::checkPublished(type)) + { + type = nullptr; + $$ = ET_none; + } + else + { + type = resolveTypedefs(type); + if (type->getNodeType() == NT_predefined) + { + $$ = static_cast< AstBaseType const * >(type)-> + getExprType(); + } else + $$ = ET_any; + } + } else + $$ = ET_any; + } else + $$ = ET_any; + } + ; + +exception_header : + IDL_EXCEPTION + { + idlc()->setParseState(PS_ExceptSeen); + } + identifier + { + idlc()->setParseState(PS_ExceptIDSeen); + checkIdentifier($3); + } + inheritance_spec + { + idlc()->setParseState(PS_InheritSpecSeen); + + $$ = new FeInheritanceHeader(NT_exception, $3, $5, nullptr); + delete $5; + } + ; + +exception_dcl : + exception_header + { + idlc()->setParseState(PS_ExceptHeaderSeen); + + AstScope* pScope = idlc()->scopes()->topNonNull(); + AstException* pExcept = nullptr; + + if ( pScope ) + { + AstException* pBase = static_cast< AstException* >( + $1->getInherits()); + pExcept = new AstException(*$1->getName(), pBase, pScope); + pScope->addDeclaration(pExcept); + } + /* + * Push the scope of the exception on the scopes stack + */ + idlc()->scopes()->push(pExcept); + delete $1; + } + '{' + { + idlc()->setParseState(PS_ExceptSqSeen); + } + members + { + idlc()->setParseState(PS_ExceptBodySeen); + } + '}' + { + idlc()->setParseState(PS_ExceptQsSeen); + /* this exception is finished, pop its scope from the stack */ + idlc()->scopes()->pop(); + } + ; + +property : + flag_header + simple_type_spec + { + idlc()->setParseState(PS_PropertyTypeSeen); + } + at_least_one_declarator + { + idlc()->setParseState(PS_PropertyCompleted); + + AstScope* pScope = idlc()->scopes()->topNonNull(); + AstAttribute* pAttr = nullptr; + FeDeclList* pList = $4; + FeDeclarator* pDecl = nullptr; + AstType const * pType = nullptr; + + if ( pScope->getScopeNodeType() == NT_singleton ) + { + ErrorHandler::error0(ErrorCode::IllegalAdd); + } else + { + if ( ($1 & AF_ATTRIBUTE) == AF_ATTRIBUTE ) + ErrorHandler::flagError(ErrorCode::WrongAttributeKeyword, AF_ATTRIBUTE); + + if ( ($1 & AF_PROPERTY) != AF_PROPERTY ) + ErrorHandler::flagError(ErrorCode::MissingAttributeKeyword, AF_PROPERTY); + + /* + * Create nodes representing attributes and add them to the + * enclosing scope + */ + if ( pScope && $2 && pList ) + { + FeDeclList::iterator iter = pList->begin(); + FeDeclList::iterator end = pList->end(); + + while (iter != end) + { + pDecl = (*iter); + if ( !pDecl ) + { + ++iter; + continue; + } + + pType = FeDeclarator::compose($2); + + if ( !pType ) + { + ++iter; + continue; + } + + pAttr = new AstAttribute(NT_property, $1, pType, pDecl->getName(), pScope); + + pScope->addDeclaration(pAttr); + ++iter; + delete pDecl; + } + } + } + + if ( pList ) + delete pList; + } + | error ';' + { + yyerror("property"); + yyerrok; + } + ; + +service_exports : + service_exports service_export + | /* EMPTY */ + ; + +service_export : + service_interface_header + at_least_one_scoped_name + ';' + { + idlc()->setParseState(PS_ServiceMemberSeen); + + AstScope* pScope = idlc()->scopes()->topNonNull(); + AstDeclaration* pDecl = nullptr; + AstInterfaceMember* pIMember = nullptr; + + if ( pScope->getScopeNodeType() == NT_singleton ) + { + ErrorHandler::error0(ErrorCode::IllegalAdd); + } else + { + /* + * Create a node representing a class member. + * Store it in the enclosing scope + */ + if ( pScope && $2 ) + { + for (auto const& elem : *($2)) + { + pDecl = pScope->lookupByName(elem); + if ( pDecl && (pDecl->getNodeType() == NT_interface) ) + { + /* we relax the strict published check and allow to add new + * interfaces if they are optional + */ + bool bOptional = (($1 & AF_OPTIONAL) == AF_OPTIONAL); + if ( ErrorHandler::checkPublished(pDecl, bOptional) ) + { + pIMember = new AstInterfaceMember( + $1, static_cast<AstInterface*>(pDecl), elem, pScope); + pScope->addDeclaration(pIMember); + } + } else + { + ErrorHandler::lookupError(ErrorCode::InterfaceMemberLookup, elem, scopeAsDecl(pScope)); + } + } + } + } + delete $2; + } + | service_service_header + at_least_one_scoped_name + ';' + { + idlc()->setParseState(PS_ServiceMemberSeen); + + AstScope* pScope = idlc()->scopes()->topNonNull(); + AstDeclaration* pDecl = nullptr; + AstServiceMember* pSMember = nullptr; + + /* + * Create a node representing a class member. + * Store it in the enclosing scope + */ + if ( pScope && $2 ) + { + for (auto const& elem : *($2)) + { + pDecl = pScope->lookupByName(elem); + if ( pDecl && (pDecl->getNodeType() == NT_service) ) + { + if ( static_cast< AstService * >(pDecl)->isSingleInterfaceBasedService() || (pScope->getScopeNodeType() == NT_singleton && pScope->nMembers() > 0) ) + ErrorHandler::error0(ErrorCode::IllegalAdd); + else if ( ErrorHandler::checkPublished(pDecl) ) + { + pSMember = new AstServiceMember( + $1, static_cast<AstService*>(pDecl), elem, pScope); + pScope->addDeclaration(pSMember); + } + } else + { + ErrorHandler::lookupError(ErrorCode::ServiceMemberLookup, elem, scopeAsDecl(pScope)); + } + } + } + delete $2; + } + | IDL_OBSERVES + at_least_one_scoped_name + ';' + { + idlc()->setParseState(PS_ServiceMemberSeen); + + AstScope* pScope = idlc()->scopes()->topNonNull(); + AstDeclaration* pDecl = nullptr; + AstObserves* pObserves = nullptr; + + if ( pScope->getScopeNodeType() == NT_singleton ) + { + ErrorHandler::error0(ErrorCode::IllegalAdd); + } else + { + /* + * Create a node representing a class member. + * Store it in the enclosing scope + */ + if ( pScope && $2 ) + { + for (auto const& elem : *($2)) + { + pDecl = pScope->lookupByName(elem); + if ( pDecl && (pDecl->getNodeType() == NT_interface) ) + { + pObserves = new AstObserves(static_cast<AstInterface*>(pDecl), elem, pScope); + pScope->addDeclaration(pObserves); + } else + { + ErrorHandler::lookupError(ErrorCode::InterfaceMemberLookup, elem, scopeAsDecl(pScope)); + } + } + } + } + delete $2; + } + | IDL_NEEDS + at_least_one_scoped_name + ';' + { + idlc()->setParseState(PS_ServiceMemberSeen); + + AstScope* pScope = idlc()->scopes()->topNonNull(); + AstDeclaration* pDecl = nullptr; + AstNeeds* pNeeds = nullptr; + + if ( pScope->getScopeNodeType() == NT_singleton ) + { + ErrorHandler::error0(ErrorCode::IllegalAdd); + } else + { + /* + * Create a node representing a class member. + * Store it in the enclosing scope + */ + if ( pScope && $2 ) + { + for (auto const& elem : *($2)) + { + pDecl = pScope->lookupByName(elem); + if ( pDecl && (pDecl->getNodeType() == NT_service) ) + { + pNeeds = new AstNeeds(static_cast<AstService*>(pDecl), elem, pScope); + pScope->addDeclaration(pNeeds); + } else + { + ErrorHandler::lookupError(ErrorCode::ServiceMemberLookup, elem, scopeAsDecl(pScope)); + } + } + } + } + delete $2; + } + | property + ';' + { + idlc()->setParseState(PS_PropertyDeclSeen); + } + ; + +service_interface_header : + IDL_INTERFACE + { + idlc()->setParseState(PS_ServiceIFHeadSeen); + $$ = AF_INVALID; + } + | flag_header + IDL_INTERFACE + { + idlc()->setParseState(PS_ServiceIFHeadSeen); + if ( (AF_OPTIONAL != $1) && ( AF_INVALID != $1) ) + ErrorHandler::flagError(ErrorCode::ExpectedOptional, $1); + $$ = $1; + } + ; + +service_service_header : + IDL_SERVICE + { + idlc()->setParseState(PS_ServiceSHeadSeen); + $$ = AF_INVALID; + } + | flag_header + IDL_SERVICE + { + idlc()->setParseState(PS_ServiceSHeadSeen); + if ( (AF_OPTIONAL != $1) && ( AF_INVALID != $1) ) + ErrorHandler::flagError(ErrorCode::ExpectedOptional, $1); + $$ = $1; + } + ; + +service_dcl : + IDL_SERVICE + { + idlc()->setParseState(PS_ServiceSeen); + } + identifier + { + idlc()->setParseState(PS_ServiceIDSeen); + checkIdentifier($3); + + AstScope* pScope = idlc()->scopes()->topNonNull(); + AstService* pService = nullptr; + + /* + * Make a new service and add it to the enclosing scope + */ + if (pScope != nullptr) + { + pService = new AstService(*$3, pScope); + pScope->addDeclaration(pService); + } + delete $3; + /* + * Push it on the stack + */ + idlc()->scopes()->push(pService); + } + service_dfn + { + /* this service is finished, pop its scope from the stack */ + idlc()->scopes()->pop(); + } + ; + +service_dfn: + service_interface_dfn + | service_obsolete_dfn + ; + +service_interface_dfn: + ':' scoped_name + { + AstScope * scope = idlc()->scopes()->nextToTop(); + // skip the scope pushed by service_dcl + AstDeclaration * decl = scope->lookupByName(*$2); + if (decl != nullptr + && resolveTypedefs(decl)->getNodeType() == NT_interface) + { + if (ErrorHandler::checkPublished(decl)) { + idlc()->scopes()->top()->addDeclaration(decl); + } + } else { + ErrorHandler::lookupError( + ErrorCode::InterfaceMemberLookup, *$2, scopeAsDecl(scope)); + } + delete $2; + } + opt_service_body + { + AstService * s = static_cast< AstService * >(idlc()->scopes()->top()); + if (s != nullptr) { + s->setSingleInterfaceBasedService(); + s->setDefaultConstructor(!$4); + } + } + ; + +opt_service_body: + service_body { $$ = true; } + | /* empty */ { $$ = false; } + ; + +service_body: + '{' + constructors + '}' + ; + +constructors: + constructors constructor + | /* empty */ + ; + +constructor: + identifier + { + checkIdentifier($1); + AstScope * scope = idlc()->scopes()->top(); + AstOperation * ctor = new AstOperation(nullptr, *$1, scope); + delete $1; + scope->addDeclaration(ctor); + idlc()->scopes()->push(ctor); + } + '(' + parameters + ')' + opt_raises + { + static_cast< AstOperation * >(idlc()->scopes()->top())->setExceptions( + $6); + delete $6; + idlc()->scopes()->pop(); + if (static_cast< AstService * >(idlc()->scopes()->top())-> + checkLastConstructor()) + { + ErrorHandler::error0(ErrorCode::SimilarConstructors); + } + } + ';' + ; + +singleton_dcl : + IDL_SINGLETON + { + idlc()->setParseState(PS_SingletonSeen); + } + identifier + { + idlc()->setParseState(PS_SingletonIDSeen); + checkIdentifier($3); + + AstScope* pScope = idlc()->scopes()->topNonNull(); + AstService* pService = nullptr; + + /* + * Make a new service and add it to the enclosing scope + */ + if (pScope != nullptr) + { + pService = new AstService(NT_singleton, *$3, pScope); + pScope->addDeclaration(pService); + } + delete $3; + /* + * Push it on the stack + */ + idlc()->scopes()->push(pService); + } + singleton_dfn + { + /* this singleton is finished, pop its scope from the stack */ + idlc()->scopes()->pop(); + } + ; + +singleton_dfn: + singleton_interface_dfn + | service_obsolete_dfn + ; + +singleton_interface_dfn: + ':' scoped_name + { + AstScope * scope = idlc()->scopes()->nextToTop(); + // skip the scope (needlessly) pushed by singleton_dcl + AstDeclaration * decl = scope->lookupByName(*$2); + if (decl != nullptr + && resolveTypedefs(decl)->getNodeType() == NT_interface) + { + if (ErrorHandler::checkPublished(decl)) { + idlc()->scopes()->top()->addDeclaration(decl); + } + } else { + ErrorHandler::lookupError( + ErrorCode::InterfaceMemberLookup, *$2, scopeAsDecl(scope)); + } + delete $2; + } + ; + +service_obsolete_dfn: + '{' + { + idlc()->setParseState( + idlc()->scopes()->top()->getScopeNodeType() == NT_service + ? PS_ServiceSqSeen : PS_SingletonSqSeen); + } + service_exports + { + idlc()->setParseState( + idlc()->scopes()->top()->getScopeNodeType() == NT_service + ? PS_ServiceBodySeen : PS_SingletonBodySeen); + } + '}' + { + idlc()->setParseState( + idlc()->scopes()->top()->getScopeNodeType() == NT_service + ? PS_ServiceQsSeen : PS_SingletonQsSeen); + } + ; + +type_dcl : + IDL_TYPEDEF + { + idlc()->setParseState(PS_TypedefSeen); + } + type_declarator {} + | struct_type {} + | enum_type {} + ; + +type_declarator : + type_spec + { + idlc()->setParseState(PS_TypeSpecSeen); + if ($1 != nullptr && $1->getNodeType() == NT_instantiated_struct) { + ErrorHandler::error0(ErrorCode::InstantiatedStructTypeTypedef); + } + } + at_least_one_declarator + { + idlc()->setParseState(PS_DeclaratorsSeen); + + AstScope* pScope = idlc()->scopes()->topNonNull(); + AstTypeDef* pTypeDef = nullptr; + FeDeclList* pList = $3; + FeDeclarator* pDecl = nullptr; + AstType const * pType = nullptr; + + /* + * Create nodes representing typedefs and add them to the + * enclosing scope + */ + if ( pScope && $1 && pList ) + { + FeDeclList::iterator iter = pList->begin(); + FeDeclList::iterator end = pList->end(); + + while (iter != end) + { + pDecl = (*iter); + if ( !pDecl ) + { + ++iter; + continue; + } + + pType = FeDeclarator::compose($1); + + if ( !pType ) + { + ++iter; + continue; + } + + pTypeDef = new AstTypeDef(pType, pDecl->getName(), pScope); + + pScope->addDeclaration(pTypeDef); + ++iter; + delete pDecl; + } + delete pList; + } + } + ; + +at_least_one_declarator : + declarator declarators + { + if ( $2 ) + { + $2->push_back($1); + $$ = $2; + } else + { + FeDeclList* pList = new FeDeclList; + pList->push_back($1); + $$ = pList; + } + } + ; + +declarators : + declarators + ',' + { + idlc()->setParseState(PS_DeclsCommaSeen); + } + declarator + { + idlc()->setParseState(PS_DeclsDeclSeen); + if ( $1 ) + { + $1->push_back($4); + $$ = $1; + } else + { + FeDeclList* pList = new FeDeclList; + pList->push_back($4); + $$ = pList; + } + } + | /* EMPTY */ + { + $$ = nullptr; + } + ; + +declarator : + identifier + { + // For historic reasons, the struct com.sun.star.uno.Uik contains + // members with illegal names (of the form "m_DataN"); avoid useless + // warnings about them: + AstScope * scope = idlc()->scopes()->top(); + if (scope == nullptr || scope->getScopeNodeType() != NT_struct + || (scopeAsDecl(scope)->getScopedName() + != "com::sun::star::uno::Uik")) + { + checkIdentifier($1); + } + + $$ = new FeDeclarator(*$1); + delete $1; + } + ; + +at_least_one_scoped_name : + scoped_name scoped_names + { + if ($2) + { + $2->push_front(*$1); + $$ = $2; + } else + { + std::list< OString >* pScopedNames = new std::list< OString >; + // coverity[copy_paste_error : FALSE] - this is not a cut and paste + pScopedNames->push_back(*$1); + $$ = pScopedNames; + } + delete $1; + } + ; + +scoped_names : + scoped_names + ',' + { + idlc()->setParseState(PS_SNListCommaSeen); + } + scoped_name + { + idlc()->setParseState(PS_ScopedNameSeen); + if ($1) + { + $1->push_back(*$4); + $$ = $1; + } else + { + std::list< OString >* pNames = new std::list< OString >; + pNames->push_back(*$4); + $$ = pNames; + } + delete $4; + } + | /* EMPTY */ + { + $$ = nullptr; + } + ; + +scoped_name : + identifier + { + idlc()->setParseState(PS_SN_IDSeen); + checkIdentifier($1); + $$ = $1; + } + | IDL_SCOPESEPARATOR + { + idlc()->setParseState(PS_ScopeDelimSeen); + } + identifier + { + checkIdentifier($3); + OString* pName = new OString("::"); + *pName += *$3; + delete $3; + $$ = pName; + } + | scoped_name + IDL_SCOPESEPARATOR + { + } + identifier + { + checkIdentifier($4); + *$1 += "::"; + *$1 += *$4; + delete $4; + $$ = $1; + } + ; + +type_spec : + simple_type_spec + | constructed_type_spec + ; + +simple_type_spec : + fundamental_type + | scoped_name opt_type_args + { + $$ = createNamedType($1, $2); + } + ; + +fundamental_type: + base_type_spec + { + $$ = idlc()->scopes()->bottom()->lookupPrimitiveType($1); + } + | sequence_type_spec + ; + +opt_type_args: + '<' type_args '>' { $$ = $2; } + | /* empty */ { $$ = nullptr; } + ; + +type_args: + type_arg + { + $$ = new DeclList; + $$->push_back(const_cast< AstDeclaration * >($1)); //TODO: const_cast + } + | type_args ',' type_arg + { + $1->push_back(const_cast< AstDeclaration * >($3)); //TODO: const_cast + $$ = $1; + } + ; + +type_arg: + simple_type_spec + { + if ($1 != nullptr && static_cast< AstType const * >($1)->isUnsigned()) { + ErrorHandler::error0(ErrorCode::UnsignedTypeArgument); + } + $$ = $1; + } + ; + +base_type_spec : + integer_type + | floating_pt_type + | char_type + | boolean_type + | byte_type + | any_type + | type_type + | string_type + ; + +integer_type : + signed_int + | unsigned_int + ; + +signed_int : + IDL_LONG + { + $$ = ET_long; + } + | IDL_HYPER + { + $$ = ET_hyper; + } + | IDL_SHORT + { + $$ = ET_short; + } + ; + +unsigned_int : + IDL_UNSIGNED IDL_LONG + { + $$ = ET_ulong; + } + | IDL_UNSIGNED IDL_HYPER + { + $$ = ET_uhyper; + } + | IDL_UNSIGNED IDL_SHORT + { + $$ = ET_ushort; + } + ; + +floating_pt_type : + IDL_DOUBLE + { + $$ = ET_double; + } + | IDL_FLOAT + { + $$ = ET_float; + } + ; + +char_type : + IDL_CHAR + { + $$ = ET_char; + } + ; + +byte_type : + IDL_BYTE + { + $$ = ET_byte; + } + ; + +boolean_type : + IDL_BOOLEAN + { + $$ = ET_boolean; + } + ; + +any_type : + IDL_ANY + { + $$ = ET_any; + } + ; + +type_type : + IDL_TYPE + { + $$ = ET_type; + } + ; + +string_type : + IDL_STRING + { + $$ = ET_string; + } + ; + +constructed_type_spec : + struct_type + | enum_type + ; + +sequence_type_spec : + IDL_SEQUENCE + { + idlc()->setParseState(PS_SequenceSeen); + /* + * Push a sequence marker on scopes stack + */ + idlc()->scopes()->push(nullptr); + } + '<' + { + idlc()->setParseState(PS_SequenceSqSeen); + } + simple_type_spec + { + idlc()->setParseState(PS_SequenceTypeSeen); + } + '>' + { + idlc()->setParseState(PS_SequenceQsSeen); + /* + * Remove sequence marker from scopes stack + */ + if (idlc()->scopes()->top() == nullptr) + idlc()->scopes()->pop(); + /* + * Create a node representing a sequence + */ + AstScope* pScope = idlc()->scopes()->bottom(); + AstDeclaration* pDecl = nullptr; + AstDeclaration* pSeq = nullptr; + + if ( $5 ) + { + AstType const *pType = static_cast<AstType const *>($5); + if ( pType ) + { + pSeq = new AstSequence(pType, pScope); + /* + * Add this AstSequence to the types defined in the global scope + */ + pDecl = pScope->addDeclaration(pSeq); + if ( pSeq != pDecl ) + { + // if sequence type already defined then use it + delete pSeq; + pSeq = pDecl; + } + } + } + $$ = pSeq; + } + | error '>' + { + yyerror("sequence declaration"); + yyerrok; + $$ = nullptr; + } + ; + +struct_type : + structure_header + { + idlc()->setParseState(PS_StructHeaderSeen); + + AstScope* pScope = idlc()->scopes()->topNonNull(); + AstStruct* pStruct = nullptr; + + if ( pScope ) + { + AstStruct const* pBase= static_cast< AstStruct const* >(resolveTypedefs($1->getInherits())); + pStruct = new AstStruct( + *$1->getName(), $1->getTypeParameters(), pBase, pScope); + pScope->addDeclaration(pStruct); + } + /* + * Push the scope of the struct on the scopes stack + */ + idlc()->scopes()->push(pStruct); + delete $1; + } + '{' + { + idlc()->setParseState(PS_StructSqSeen); + } + at_least_one_member + { + idlc()->setParseState(PS_StructBodySeen); + } + '}' + { + idlc()->setParseState(PS_StructQsSeen); + /* this exception is finished, pop its scope from the stack */ + idlc()->scopes()->pop(); + } + ; + +structure_header : + IDL_STRUCT + { + idlc()->setParseState(PS_StructSeen); + } + identifier + { + idlc()->setParseState(PS_StructIDSeen); + checkIdentifier($3); + } + opt_type_params + inheritance_spec + { + idlc()->setParseState(PS_InheritSpecSeen); + + // Polymorphic struct type templates with base types would cause various + // problems in language bindings, so forbid them here. For example, + // GCC prior to version 3.4 fails with code like + // + // struct Base { ... }; + // template< typename typeparam_T > struct Derived: public Base { + // int member1 CPPU_GCC3_ALIGN(Base); + // ... }; + // + // (Note that plain struct types with instantiated polymorphic struct + // type bases, which might also cause problems in language bindings, are + // already rejected on a syntactic level.) + if ($5 != nullptr && $6 != nullptr) { + ErrorHandler::error0(ErrorCode::StructTypeTemplateWithBase); + } + + $$ = new FeInheritanceHeader(NT_struct, $3, $6, $5); + delete $5; + delete $6; + } + ; + +opt_type_params: + '<' type_params '>' { $$ = $2; } + | /* empty */ { $$ = nullptr; } + ; + +type_params: + identifier + { + $$ = new std::vector< OString >; + $$->push_back(*$1); + delete $1; + } + | type_params ',' identifier + { + if (std::find($1->begin(), $1->end(), *$3) != $1->end()) { + ErrorHandler::error0(ErrorCode::IdenticalTypeParameters); + } + $1->push_back(*$3); + delete $3; + $$ = $1; + } + ; + +at_least_one_member : member members ; + +members : + members member + | /* EMPTY */ + ; + +member : + type_or_parameter + { + idlc()->setParseState(PS_MemberTypeSeen); + } + at_least_one_declarator + { + idlc()->setParseState(PS_MemberDeclsSeen); + } + ';' + { + idlc()->setParseState(PS_MemberDeclsCompleted); + + AstScope* pScope = idlc()->scopes()->topNonNull(); + AstMember* pMember = nullptr; + FeDeclList* pList = $3; + FeDeclarator* pDecl = nullptr; + AstType const * pType = nullptr; + + // !!! check recursive type + + if ( pScope && pList && $1 ) + { + FeDeclList::iterator iter = pList->begin(); + FeDeclList::iterator end = pList->end(); + while (iter != end) + { + pDecl = (*iter); + if ( !pDecl ) + { + ++iter; + continue; + } + + pType = FeDeclarator::compose($1); + + if ( !pType ) + { + ++iter; + continue; + } + + pMember = new AstMember(pType, pDecl->getName(), pScope); + + if ( !pDecl->checkType($1) ) + { + // WARNING + } + + pScope->addDeclaration(pMember); + ++iter; + delete pDecl; + } + delete pList; + } + } + | error ';' + { + yyerror("member definition"); + yyerrok; + } + ; + +type_or_parameter: + fundamental_type + | scoped_name opt_type_args + { + AstDeclaration const * decl = nullptr; + AstStruct * scope = static_cast< AstStruct * >(idlc()->scopes()->top()); + if (scope != nullptr && $2 == nullptr) { + decl = scope->findTypeParameter(*$1); + } + if (decl != nullptr) { + delete $1; + delete $2; + } else { + decl = createNamedType($1, $2); + if (scope != nullptr && includes(decl, scopeAsDecl(scope))) { + ErrorHandler::error1( + ErrorCode::RecursiveType, scopeAsDecl(scope)); + decl = nullptr; + } + } + $$ = decl; + } + ; + +enum_type : + IDL_ENUM + { + idlc()->setParseState(PS_EnumSeen); + } + identifier + { + idlc()->setParseState(PS_EnumIDSeen); + checkIdentifier($3); + + AstScope* pScope = idlc()->scopes()->topNonNull(); + AstEnum* pEnum = nullptr; + + /* + * Create a node representing an enum and add it to its + * enclosing scope + */ + if (pScope != nullptr) + { + pEnum = new AstEnum(*$3, pScope); + /* + * Add it to its defining scope + */ + pScope->addDeclaration(pEnum); + } + delete $3; + /* + * Push the enum scope on the scopes stack + */ + idlc()->scopes()->push(pEnum); + + } + '{' + { + idlc()->setParseState(PS_EnumSqSeen); + } + at_least_one_enumerator + { + idlc()->setParseState(PS_EnumBodySeen); + } + '}' + { + idlc()->setParseState(PS_EnumQsSeen); + /* + * Done with this enum. Pop its scope from the scopes stack + */ + if (idlc()->scopes()->top() == nullptr) + $$ = nullptr; + else + { + $$ = static_cast<AstEnum*>(idlc()->scopes()->topNonNull()); + idlc()->scopes()->pop(); + } + } + ; + +at_least_one_enumerator : enumerator enumerators ; + +enumerators : + enumerators + ',' + { + idlc()->setParseState(PS_EnumCommaSeen); + } + enumerator + | /* EMPTY */ + | error ',' + { + yyerror("enumerator definition"); + yyerrok; + } + ; + +enumerator : + identifier + { + checkIdentifier($1); + + AstScope* pScope = idlc()->scopes()->topNonNull(); + AstEnum* pEnum = nullptr; + AstConstant* pEnumVal = nullptr; + + if ( pScope && pScope->getScopeNodeType() == NT_enum) + { + pEnum = static_cast<AstEnum*>(pScope); + if (pEnum && $1) + { + AstExpression* pExpr = new AstExpression(pEnum->getEnumValueCount()); + pEnumVal = new AstConstant(ET_long , NT_enum_val, + pExpr, *$1, pScope); + } + if ( pEnum->checkValue(pEnumVal->getConstValue()) ) + ErrorHandler::error1(ErrorCode::Eval, pEnum); + + pScope->addDeclaration(pEnumVal); + } + delete $1; + } + | identifier + '=' + const_expr + { + checkIdentifier($1); + + AstScope* pScope = idlc()->scopes()->topNonNull(); + AstEnum* pEnum = nullptr; + AstConstant* pEnumVal = nullptr; + + if ( $3 && pScope && pScope->getScopeNodeType() == NT_enum) + { + $3->evaluate(); + if ( $3->coerce(ET_long) ) + { + pEnum = static_cast<AstEnum*>(pScope); + if (pEnum) + { + pEnumVal = new AstConstant(ET_long , NT_enum_val, + $3, *$1, pScope); + } + if ( pEnum->checkValue(pEnumVal->getConstValue()) ) + ErrorHandler::error1(ErrorCode::Eval, pEnum); + + pScope->addDeclaration(pEnumVal); + } else + { + ErrorHandler::coercionError($3, ET_long); + delete $3; + } + } + delete $1; + } + ; + +identifier: + IDL_IDENTIFIER + | IDL_GET { $$ = new OString("get"); } + | IDL_SET { $$ = new OString("set"); } + | IDL_PUBLISHED { $$ = new OString("published"); } + ; + +%% + +/* + * Report an error situation discovered in a production + */ +void yyerror(char const *errmsg) +{ + ErrorHandler::syntaxError(idlc()->getParseState(), idlc()->getLineNumber(), errmsg); + idlc()->setParseState(PS_NoState); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/source/scanner.l b/idlc/source/scanner.l new file mode 100644 index 000000000..aaf74a564 --- /dev/null +++ b/idlc/source/scanner.l @@ -0,0 +1,526 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * 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 . + */ + +%option yylineno + +%{ +/* + * scanner.ll - Lexical scanner for IDLC 1.0 + */ + +#include <sal/config.h> + +#include <stdlib.h> +#include <string.h> + +#include <o3tl/safeint.hxx> +#include <o3tl/string_view.hxx> +#include <rtl/character.hxx> + +#if defined _MSC_VER +#pragma warning ( push ) +// Silence warnings about redefinition of INT8_MIN etc in stdint.h +// The flex-generated workdir/LexTarget/idlc/source/scanner.cxx defines them prior to these includes +#pragma warning ( disable : 4005 ) +#endif +#include <idlc.hxx> +#if defined _MSC_VER +#pragma warning ( pop ) +#endif +#include <errorhandler.hxx> +#include <fehelper.hxx> + +#include "attributeexceptions.hxx" + + +class AstExpression; +class AstMember; + +#include <parser.hxx> + +/* handle locations */ +static int yycolumn = 1; + +#define YY_USER_ACTION idlc()->setOffset(yycolumn, yycolumn+yyleng-1); \ + yycolumn += yyleng; + +static sal_Int32 beginLine = 0; +static OString docu; + +static int asciiToInteger(char const * s, sal_Int64 * sval, sal_uInt64 * uval) { + bool neg = false; + if (*s == '-') { + neg = true; + ++s; + } + unsigned int base = 10; + if (*s == '0') { + base = 8; + ++s; + if (*s == 'X' || *s == 'x') { + base = 16; + ++s; + } + } + sal_uInt64 val = 0; + for (; *s != 0; ++s) { + unsigned int n; + if (*s >= '0' && *s <= '9') { + n = *s - '0'; + } else { + switch (*s) { + case 'A': + case 'a': + n = 10; + break; + case 'B': + case 'b': + n = 11; + break; + case 'C': + case 'c': + n = 12; + break; + case 'D': + case 'd': + n = 13; + break; + case 'E': + case 'e': + n = 14; + break; + case 'F': + case 'f': + n = 15; + break; + default: + goto done; + } + } + // The following guarantees the invariant val <= SAL_MAX_UINT64 (because + // base and n are sufficiently small), *if* + // std::numeric_limits<sal_uInt64>::max() == SAL_MAX_UINT64: + sal_uInt64 nval = val * base + n; + if (nval < val) { + ErrorHandler::syntaxError( + PS_NoState, idlc()->getLineNumber(), + "integral constant too large"); + val = 0; + break; + } + val = nval; + } + done: + if (neg) { + if (val < SAL_CONST_UINT64(0x8000000000000000)) { + *sval = -static_cast< sal_Int64 >(val); + } else if (val == SAL_CONST_UINT64(0x8000000000000000)) { + *sval = SAL_MIN_INT64; + } else { + ErrorHandler::syntaxError( + PS_NoState, idlc()->getLineNumber(), + "negative integral constant too large"); + *sval = 0; + } + return IDL_INTEGER_LITERAL; + } else if (val <= o3tl::make_unsigned(SAL_MAX_INT64)) { + *sval = static_cast< sal_Int64 >(val); + return IDL_INTEGER_LITERAL; + } else { + *uval = val; + return IDL_INTEGER_ULITERAL; + } +} + +static double asciiToFloat(const char *s) +{ + double d = 0.0; + double e, k; + sal_Int32 neg = 0; + + if (*s == '-') + { + neg = 1; + s++; + } + while (*s >= '0' && *s <= '9') + { + d = (d * 10) + *s - '0'; + s++; + } + if (*s == '.') + { + s++; + e = 10; + while (*s >= '0' && *s <= '9') + { + d += (*s - '0') / (e * 1.0); + e *= 10; + s++; + } + } + if (*s == 'e' || *s == 'E') + { + s++; + if (*s == '-') + { + s++; + } else + { + if (*s == '+') + s++; + e = 0; + while (*s >= '0' && *s <= '9') + { + e = (e * 10) + *s - '0'; + s++; + } + if (e > 0) + { + for (k = 1; e > 0; k *= 10, e--) + ; + d /= k; + } + } + } + if (neg) d *= -1.0; + return d; +} + +static void idlParsePragma(char* pPragma) +{ + OString pragma(pPragma); + sal_Int32 index = pragma.indexOf("include"); + char* begin = pPragma + index + 8; + char* offset = begin; + while (*offset != ',') offset++; + //OString include = pragma.copy(index + 8, offset - begin); + //unused// idlc()->insertInclude(pragma.copy(index + 8, (sal_Int32)(offset - begin))); +} + +static void parseLineAndFile(char* pBuf) +{ + char *r = pBuf; + char *h; + bool bIsInMain = false; + + /* Skip initial '#' */ + if (*r != '#') + return; + + /* Find line number */ + for (r++; *r == ' ' || *r == '\t' || rtl::isAsciiAlpha(static_cast<unsigned char>(*r)); r++) ; + h = r; + for (; *r != '\0' && *r != ' ' && *r != '\t'; r++) ; + *r++ = 0; + idlc()->setLineNumber(sal_uInt32(atol(h))); + yylineno = atol(h); + + /* Find file name, if present */ + for (; *r != '"'; r++) + { + if (*r == '\n' || *r == '\0') + return; + } + h = ++r; + for (; *r != '"'; r++) ; + *r = 0; + if (*h == '\0') + idlc()->setFileName("standard input"); + else + idlc()->setFileName(OString(h)); + + bIsInMain = idlc()->getFileName() == idlc()->getRealFileName(); + idlc()->setInMainfile(bIsInMain); +} + +// Suppress any warnings from generated code: +#ifdef __GNUC__ +#pragma GCC diagnostic ignored "-Wunused-function" +#pragma GCC diagnostic ignored "-Wunused-label" +#elif defined _MSC_VER +/**/ +#ifdef yywrap +#undef yywrap +#define yywrap() 1 +#endif +/**/ +#endif +#define YY_NO_UNISTD_H +%} + +%option noyywrap +%option never-interactive + +%x DOCU +%x COMMENT + +DIGIT [0-9] +OCT_DIGIT [0-7] +HEX_DIGIT [a-fA-F0-9] +CAPITAL [A-Z] +ALPHA [a-zA-Z] +INT_LITERAL [1-9][0-9]* +OCT_LITERAL 0{OCT_DIGIT}* +HEX_LITERAL (0x|0X){HEX_DIGIT}* + +IDENTIFIER_NEW ({ALPHA}({ALPHA}|{DIGIT})*)|({CAPITAL}("_"?({ALPHA}|{DIGIT})+)*) +IDENTIFIER ("_"?({ALPHA}|{DIGIT})+)* + +%% + +[ \t\r]+ ; /* eat up whitespace */ +[\n] { + idlc()->incLineNumber(); + yycolumn = 1; + yylineno++; +} + +attribute return IDL_ATTRIBUTE; +bound return IDL_BOUND; +const return IDL_CONST; +constants return IDL_CONSTANTS; +constrained return IDL_CONSTRAINED; +enum return IDL_ENUM; +exception return IDL_EXCEPTION; +interface return IDL_INTERFACE; +maybeambiguous return IDL_MAYBEAMBIGUOUS; +maybedefault return IDL_MAYBEDEFAULT; +maybevoid return IDL_MAYBEVOID; +module return IDL_MODULE; +needs return IDL_NEEDS; +observes return IDL_OBSERVES; +optional return IDL_OPTIONAL; +property return IDL_PROPERTY; +raises return IDL_RAISES; +readonly return IDL_READONLY; +removable return IDL_REMOVABLE; +service return IDL_SERVICE; +sequence return IDL_SEQUENCE; +singleton return IDL_SINGLETON; +struct return IDL_STRUCT; +transient return IDL_TRANSIENT; +typedef return IDL_TYPEDEF; + +any return IDL_ANY; +boolean return IDL_BOOLEAN; +byte return IDL_BYTE; +char return IDL_CHAR; +double return IDL_DOUBLE; +float return IDL_FLOAT; +hyper return IDL_HYPER; +long return IDL_LONG; +short return IDL_SHORT; +string return IDL_STRING; +type return IDL_TYPE; +unsigned return IDL_UNSIGNED; +void return IDL_VOID; + +TRUE return IDL_TRUE; +True return IDL_TRUE; +FALSE return IDL_FALSE; +False return IDL_FALSE; + +in return IDL_IN; +out return IDL_OUT; +inout return IDL_INOUT; + +get return IDL_GET; +set return IDL_SET; + +published return IDL_PUBLISHED; + +"..." return IDL_ELLIPSIS; + +("-")?{INT_LITERAL}+(l|L|u|U)? { + return asciiToInteger(yytext, &yylval.ival, &yylval.uval); + } + +("-")?{OCT_LITERAL}+(l|L|u|U)? { + return asciiToInteger(yytext, &yylval.ival, &yylval.uval); + } + +("-")?{HEX_LITERAL}+(l|L|u|U)? { + return asciiToInteger(yytext, &yylval.ival, &yylval.uval); + } + +("-")?{DIGIT}+(e|E)(("+"|"-")?{DIGIT}+)?(f|F)? | +("-")?{DIGIT}*"."{DIGIT}+((e|E)("+"|"-")?{DIGIT}+)?(f|F)? { + yylval.dval = asciiToFloat( yytext ); + return IDL_FLOATING_PT_LITERAL; + } + +{IDENTIFIER} { + yylval.sval = new OString(yytext); + return IDL_IDENTIFIER; + } + +\<\< { + yylval.strval = yytext; + return IDL_LEFTSHIFT; + } +\>\> { + yylval.strval = yytext; + return IDL_RIGHTSHIFT; + } +\:\: { + yylval.strval = yytext; + return IDL_SCOPESEPARATOR; + } + +"/*" { + BEGIN( COMMENT ); + docu = OString(); + beginLine = idlc()->getLineNumber(); + } + +"/***" { + BEGIN( COMMENT ); + docu = OString(); + beginLine = idlc()->getLineNumber(); + } + +<COMMENT>[^*]+ { + docu += yytext; + } + +<COMMENT>"*"[^*/]+ { + docu += yytext; + } + +<COMMENT>"**" { + docu += yytext; + } + +<COMMENT>[*]+"/" { + docu = docu.trim(); + sal_Int32 nIndex = 0; + int count = 0; + do { o3tl::getToken(docu, 0, '\n', nIndex ); count++; } while( nIndex != -1 ); + idlc()->setLineNumber( beginLine + count - 1); + BEGIN( INITIAL ); + } + +"/**" { + BEGIN( DOCU ); + docu = OString(); + beginLine = idlc()->getLineNumber(); + } + +<DOCU>[^*\n]+ { + docu += yytext; + } + +<DOCU>"\n"[ \t]*"*"{1} { + idlc()->setLineNumber( idlc()->getLineNumber() + 1); + docu += "\n"; + } + +<DOCU>"\n" { + idlc()->setLineNumber( idlc()->getLineNumber() + 1); + docu += yytext; + } + +<DOCU>"*"[^*^/\n]* { + docu += yytext; + } + +<DOCU>"\n"[ \t]*"*/" { + docu = docu.trim(); + sal_Int32 nIndex = 0; + int count = 0; + do { o3tl::getToken(docu, 0, '\n', nIndex ); count++; } while( nIndex != -1 ); + idlc()->setLineNumber( beginLine + count - 1); + if ( (nIndex = docu.indexOf("/*")) >= 0 || (nIndex = docu.indexOf("///")) >= 0 ) + { + if ( 0 != nIndex && + (docu[nIndex - 1] != '"' && docu[nIndex - 1] != ':') ) + ErrorHandler::syntaxError(PS_NoState, idlc()->getLineNumber(), + "nested documentation strings are not allowed!"); + } + idlc()->setDocumentation(docu); + BEGIN( INITIAL ); + } + +<DOCU>"*/" { + docu = docu.trim(); + sal_Int32 nIndex = 0; + int count = 0; + do { o3tl::getToken(docu, 0, '\n', nIndex ); count++; } while( nIndex != -1 ); + idlc()->setLineNumber( beginLine + count - 1); + if ( docu.indexOf("/*") >= 0 || docu.indexOf("//") >= 0 ) + { + if ( 0 != nIndex && + (docu[nIndex - 1] != '"' && docu[nIndex - 1] != ':') ) + ErrorHandler::syntaxError(PS_NoState, idlc()->getLineNumber(), + "nested documentation strings are not allowed!"); + } + idlc()->setDocumentation(docu); + BEGIN( INITIAL ); + } + +"//"[^/]{1}.*"\n" { + /* only a comment */ + OString docStr(yytext); + docStr = docStr.copy( 0, docStr.lastIndexOf('\n') ); + docStr = docStr.copy( docStr.lastIndexOf('/')+1 ); + docStr = docStr.trim(); + idlc()->incLineNumber(); + } + +"///".*"\n" { + OString docStr(yytext); + docStr = docStr.copy( 0, docStr.lastIndexOf('\n') ); + docStr = docStr.copy( docStr.lastIndexOf('/')+1 ); + docStr = docStr.trim(); + idlc()->incLineNumber(); + idlc()->setDocumentation(docStr); + } + +. return yytext[0]; + +^#[ \t]*line[ \t]*[0-9]*" ""\""[^\"]*"\""\n { + parseLineAndFile(yytext); +} + +^#[ \t]*[0-9]*" ""\""[^\"]*"\""" "[0-9]*\n { + parseLineAndFile(yytext); +} + +^#[ \t]*[0-9]*" ""\""[^\"]*"\""\n { + parseLineAndFile(yytext); +} + +^#[ \t]*[0-9]*\n { + parseLineAndFile(yytext); +} + +^#[ \t]*ident.*\n { + /* ignore cpp ident */ + idlc()->incLineNumber(); +} + +^#[ \t]*pragma[ \t].*\n { /* remember pragma */ + idlParsePragma(yytext); + idlc()->incLineNumber(); +} + +%% + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/idlc/test/const.idl b/idlc/test/const.idl new file mode 100644 index 000000000..aeb638e22 --- /dev/null +++ b/idlc/test/const.idl @@ -0,0 +1,71 @@ +/* -*- 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 . + */ + +module idlc +{ +module test +{ + const long l = 1; + const long add = 1 + 2; + const long sub = 3 - 2; + const hyper h = 123456789; + const float f7 = 3.4123; + const float f2 = 3.4123 + 10e-12; + const boolean bt = True; + const boolean bf = False; + const boolean and = bt & bf; + + /// SHORT_MAX + 1; + const short shortMax = -0x8000; + /// LONG_MAX + 1; + const unsigned long longMax = 0x80000000; + + +constants USER +{ + /// = 1 + const long FLAG1 = 0x00000001; + /// = 2 + const long FLAG2 = 0x00000002; + /// = 4 + const long FLAG3 = 0x00000004; + /// = 8 + const long FLAG4 = 0x00000008; + /// = 16 + const long FLAG5 = 0x00000010; + /// = 0 + const long FLAG6 = FLAG1 & FLAG2; + /// = 3 + const long FLAG7 = FLAG1 | FLAG2; + /// = 2 + const long FLAG8 = (FLAG1 | FLAG2) & FLAG2; + /// = 4 + const long FLAG9 = FLAG1 << 2; + /// = 32 + const long FLAG10 = (FLAG5 >> 1) << 2; + /// = 1 + const long FLAG11 = 33 % 4; + /// = 4 + const long FLAG12 = FLAG10 / 8; +}; + +}; +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/test/enum.idl b/idlc/test/enum.idl new file mode 100644 index 000000000..9ddbd6e76 --- /dev/null +++ b/idlc/test/enum.idl @@ -0,0 +1,45 @@ +/* -*- 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 . + */ + +module idlc +{ +module test +{ + +enum Error +{ + NONE, + FATAL, + SYSTEM, + RUNTIME +}; + +enum Warning +{ + NO, + USER = 2, + WRONGPASSWORD = 4, + IDFAILURE +}; + + +}; +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/test/exception.idl b/idlc/test/exception.idl new file mode 100644 index 000000000..cc15069f4 --- /dev/null +++ b/idlc/test/exception.idl @@ -0,0 +1,40 @@ +/* -*- 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 . + */ + +module idlc +{ +module test +{ + +exception BaseException +{ + string Description; +}; + +exception RuntimeException : BaseException +{ + long Id; + type Context; +}; + + +}; +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/test/identifiers.idl b/idlc/test/identifiers.idl new file mode 100644 index 000000000..d845b3729 --- /dev/null +++ b/idlc/test/identifiers.idl @@ -0,0 +1,43 @@ +/* -*- 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 . + */ + +struct Identifiers +{ + long onlysmallalphas; + long smallMixedAlphas; + long CapMixedAlphas; + long ONLYCAPS; + long CAPS_WITH_UNDERSCORE; + long CAPS_WITH_UNDERSCORE_11; + long CAPS_WITH_UNDERSCORE11_11TEST; + long CapMixed_Alphas_11; + long m_CapMixedAlphas_11; // should be not allowed with -cid + long small_get; //should be not allowed with -cid + long small_11; //should be not allowed with -cid + long small_11small; //should be not allowed with -cid + long mixedAlphas_11CAPS; // should be not allowed with -cid + long mixedAlphas_11mixedAlphas; // should be not allowed with -cid + long _mixedAlphas; // should be not allowed with -cid +// long _mixedAlphas_; // should be not allowed +// long CapsMixedAlphas_; // should be not allowed +// long _CapsMixedAlphas_; // should be not allowed + +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/test/interface.idl b/idlc/test/interface.idl new file mode 100644 index 000000000..5de90a07b --- /dev/null +++ b/idlc/test/interface.idl @@ -0,0 +1,71 @@ +/* -*- 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 <enum.idl> +#include <struct.idl> + +module idlc +{ + +module test +{ + +interface XBase +{ + [readonly, attribute] string description; + + string getDescription(); +}; + +interface XTestBaseTypes : XBase +{ + void voidFunc(); + + short shortFunc( [in] short inparam, [out] short outparam, [inout] short inoutparam); + unsigned short uShortFunc( [in] unsigned short inparam, [out] unsigned short outparam, [inout] unsigned short inoutparam); + + long longFunc( [in] long inparam, [out] long outparam, [inout] long inoutparam); + unsigned long ulongFunc( [in] unsigned long inparam, [out] unsigned long outparam, [inout] unsigned long inoutparam); + + hyper hyperFunc( [in] hyper inparam, [out] hyper outparam, [inout] hyper inoutparam); + unsigned hyper uHyperFunc( [in] unsigned hyper inparam, [out] unsigned hyper outparam, [inout] unsigned hyper inoutparam); + + float floatFunc( [in] float inparam, [out] float outparam, [inout] float inoutparam); + double doubleFunc( [in] double inparam, [out] double outparam, [inout] double inoutparam); + char charFunc( [in] char inparam, [out] char outparam, [inout] char inoutparam); + string stringFunc( [in] string inparam, [out] string outparam, [inout] string inoutparam); + byte byteFunc( [in] byte inparam, [out] byte outparam, [inout] byte inoutparam); + + type typeFunc( [in] type inparam, [out] type outparam, [inout] type inoutparam); + any anyFunc( [in] any inparam, [out] any outparam, [inout] any inoutparam); +}; + + +interface XTestComplexTypes : XBase +{ + Error enumFunc( [in] Error inparam, [out] Error outparam, [inout] Error inoutparam); + + BaseStruct structFunc( [in] ::idlc::test::BaseStruct inparam, [out] idlc::test::BaseStruct outparam, [inout] BaseStruct inoutparam); +}; + +}; + +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/test/parser/attribute.tests b/idlc/test/parser/attribute.tests new file mode 100644 index 000000000..dd0b85bde --- /dev/null +++ b/idlc/test/parser/attribute.tests @@ -0,0 +1,232 @@ +# +# 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 . +# + +EXPECT SUCCESS "attribute.tests 1": +interface I1 { + [attribute] long a; +}; + + +EXPECT SUCCESS "attribute.tests 2": +interface I1 { + [attribute] long a {}; +}; + + +EXPECT FAILURE "attribute.tests 3": +interface I1 { + [attribute] long a { + get raises (); + }; +}; + + +EXPECT FAILURE "attribute.tests 3a": +interface I1 { + [attribute] long a { + set raises (); + }; +}; + + +EXPECT SUCCESS "attribute.tests 4": +exception E1 {}; +interface I1 { + [attribute] long a { + get raises (E1); + }; +}; + + +EXPECT SUCCESS "attribute.tests 5": +exception E1 {}; +interface I1 { + [attribute] long a { + set raises (E1); + }; +}; + + +EXPECT SUCCESS "attribute.tests 6": +exception E1 {}; +interface I1 { + [attribute] long a { + get raises (E1); + set raises (E1); + }; +}; + + +EXPECT SUCCESS "attribute.tests 7": +exception E1 {}; +interface I1 { + [attribute] long a { + set raises (E1); + get raises (E1); + }; +}; + + +EXPECT FAILURE "attribute.tests 8": +exception E1 {}; +interface I1 { + [attribute] long a { + get raises (E1); + get raises (E1); + }; +}; + + +EXPECT OLD-FAILURE "attribute.tests 9": +exception E1 {}; +interface I1 { + void E1(); + [attribute] long a { + get raises (E1); + }; +}; + + +EXPECT OLD-FAILURE "attribute.tests 10": +exception E1 {}; +interface I1 { + [attribute] long E1 { + get raises (E1); + }; +}; + + +EXPECT NEW-FAILURE "attribute.tests 11": +exception E1 {}; +interface I1 { + [attribute] long a { + get raises (E1,E1); + }; +}; + + +EXPECT SUCCESS "attribute.tests 12": +exception E1 {}; +interface I1 { + [attribute, readonly] long a { + get raises (E1); + }; +}; + + +EXPECT FAILURE "attribute.tests 13": +exception E1 {}; +interface I1 { + [attribute, readonly] long a { + set raises (E1); + }; +}; + + +EXPECT FAILURE "attribute.tests 14": +interface I1 { + [] long a; +}; + + +EXPECT SUCCESS "attribute.tests 15": +interface I1 { + [attribute] long a; +}; + + +EXPECT FAILURE "attribute.tests 16": +interface I1 { + [attribute, property] long a; +}; + + +EXPECT FAILURE "attribute.tests 17": +interface I1 { + [attribute, optional] long a; +}; + + +EXPECT FAILURE "attribute.tests 18": +interface I1 { + [attribute, maybevoid] long a; +}; + + +EXPECT FAILURE "attribute.tests 19": +interface I1 { + [attribute, constrained] long a; +}; + + +EXPECT FAILURE "attribute.tests 20": +interface I1 { + [attribute, transient] long a; +}; + + +EXPECT FAILURE "attribute.tests 21": +interface I1 { + [attribute, maybeambiguous] long a; +}; + + +EXPECT FAILURE "attribute.tests 22": +interface I1 { + [attribute, maybedefault] long a; +}; + + +EXPECT FAILURE "attribute.tests 23": +interface I1 { + [attribute, removable] long a; +}; + + +EXPECT SUCCESS "attribute.tests 24": +interface I1 { + [attribute, bound] long a; +}; + + +EXPECT SUCCESS "attribute.tests 25": +interface I1 { + [bound, attribute] long a; +}; + + +EXPECT SUCCESS "attribute.tests 26": +interface I1 { + [attribute, readonly] long a; +}; + + +EXPECT SUCCESS "attribute.tests 27": +interface I1 { + [attribute, bound, readonly] long a; +}; + + +EXPECT SUCCESS "attribute.tests 28": +exception E1 {}; +interface I1 { + [attribute, bound] long a { + get raises (E1); + set raises (E1); + }; +}; diff --git a/idlc/test/parser/constant.tests b/idlc/test/parser/constant.tests new file mode 100644 index 000000000..49183d4d1 --- /dev/null +++ b/idlc/test/parser/constant.tests @@ -0,0 +1,294 @@ +# +# 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 . +# + +EXPECT SUCCESS "constant.tests 1": +constants C { + const boolean C1 = FALSE; + const byte C2 = 0; + const short C3 = 0; + const unsigned short C4 = 0; + const long C5 = 0; + const unsigned long C6 = 0; + const hyper C7 = 0; + const unsigned hyper C8 = 0; + const float C9 = 0.0; + const double C10 = 0.0; +}; + + +EXPECT FAILURE "constant.tests 2": +module m { + const boolean C1 = FALSE; + const byte C2 = 0; + const short C3 = 0; + const unsigned short C4 = 0; + const long C5 = 0; + const unsigned long C6 = 0; + const hyper C7 = 0; + const unsigned hyper C8 = 0; + const float C9 = 0.0; + const double C10 = 0.0; +}; + + +EXPECT FAILURE "constant.tests 3": +constants C { + const char C1 = 'A'; +}; + + +EXPECT FAILURE "constant.tests 4": +module m { + const char C1 = 'A'; +}; + + +EXPECT FAILURE "constant.tests 5": +constants C { + const string C1 = ""; +}; + + +EXPECT FAILURE "constant.tests 6": +module m { + const string C1 = ""; +}; + + +EXPECT SUCCESS "constant.tests 7": +constants C {}; + + +EXPECT SUCCESS "constant.tests 8": +constants C { + const byte C1 = -128; + const byte C2 = -0200; + const byte C3 = -0x80; + const byte C4 = 127; + const byte C5 = 0177; + const byte C6 = 0x7F; + const short C7 = -32768; + const short C8 = -0100000; + const short C9 = -0x8000; + const short C10 = 32767; + const short C11 = 077777; + const short C12 = 0x7FFF; + const unsigned short C13 = 0; + const unsigned short C14 = 0x0; + const unsigned short C15 = 65535; + const unsigned short C16 = 0177777; + const unsigned short C17 = 0xFFFF; + const long C18 = -2147483648; + const long C19 = -020000000000; + const long C20 = -0x80000000; + const long C21 = 2147483647; + const long C22 = 017777777777; + const long C23 = 0x7FFFFFFF; + const unsigned long C24 = 0; + const unsigned long C25 = 0x0; + const unsigned long C26 = 4294967295; + const unsigned long C27 = 037777777777; + const unsigned long C28 = 0xFFFFFFFF; + const hyper C29 = -9223372036854775808; + const hyper C30 = -01000000000000000000000; + const hyper C31 = -0x8000000000000000; + const hyper C32 = 9223372036854775807; + const hyper C33 = 0777777777777777777777; + const hyper C34 = 0x7FFFFFFFFFFFFFFF; + const unsigned hyper C35 = 0; + const unsigned hyper C36 = 0x0; + const unsigned hyper C37 = 18446744073709551615; + const unsigned hyper C38 = 01777777777777777777777; + const unsigned hyper C39 = 0xFFFFFFFFFFFFFFFF; +}; + + +EXPECT NEW-FAILURE "constant.tests 8a": +constants C { + const byte C4 = 255; + const byte C5 = 0377; + const byte C6 = 0xFF; +}; + + +EXPECT FAILURE "constant.tests 9": +constants C { const byte C1 = -129; }; + + +EXPECT FAILURE "constant.tests 10": +constants C { const byte C1 = -0201; }; + + +EXPECT FAILURE "constant.tests 11": +constants C { const byte C1 = -0x81; }; + + +EXPECT FAILURE "constant.tests 12": +constants C { const byte C1 = 256; }; + + +EXPECT FAILURE "constant.tests 13": +constants C { const byte C1 = 0400; }; + + +EXPECT FAILURE "constant.tests 14": +constants C { const byte C1 = 0x100; }; + + +EXPECT FAILURE "constant.tests 15": +constants C { const short C1 = -32769; }; + + +EXPECT FAILURE "constant.tests 16": +constants C { const short C1 = -0100001; }; + + +EXPECT FAILURE "constant.tests 17": +constants C { const short C1 = -0x8001; }; + + +EXPECT FAILURE "constant.tests 18": +constants C { const short C1 = 32768; }; + + +EXPECT FAILURE "constant.tests 19": +constants C { const short C1 = 0100000; }; + + +EXPECT FAILURE "constant.tests 20": +constants C { const short C1 = 0x8000; }; + + +EXPECT FAILURE "constant.tests 21": +constants C { const unsigned short C1 = -1; }; + + +EXPECT FAILURE "constant.tests 22": +constants C { const unsigned short C1 = -01; }; + + +EXPECT FAILURE "constant.tests 23": +constants C { const unsigned short C1 = -0x1; }; + + +EXPECT FAILURE "constant.tests 24": +constants C { const unsigned short C1 = 65536; }; + + +EXPECT FAILURE "constant.tests 25": +constants C { const unsigned short C1 = 0200000; }; + + +EXPECT FAILURE "constant.tests 26": +constants C { const unsigned short C1 = 0x10000; }; + + +EXPECT FAILURE "constant.tests 27": +constants C { const long C1 = -2147483649; }; + + +EXPECT FAILURE "constant.tests 28": +constants C { const long C1 = -020000000001; }; + + +EXPECT FAILURE "constant.tests 29": +constants C { const long C1 = -0x80000001; }; + + +EXPECT FAILURE "constant.tests 30": +constants C { const long C1 = 2147483648; }; + + +EXPECT FAILURE "constant.tests 31": +constants C { const long C1 = 020000000000; }; + + +EXPECT FAILURE "constant.tests 32": +constants C { const long C1 = 0x80000000; }; + + +EXPECT FAILURE "constant.tests 33": +constants C { const unsigned long C1 = -1; }; + + +EXPECT FAILURE "constant.tests 34": +constants C { const unsigned long C1 = -01; }; + + +EXPECT FAILURE "constant.tests 35": +constants C { const unsigned long C1 = -0x1; }; + + +EXPECT FAILURE "constant.tests 36": +constants C { const unsigned long C1 = 4294967296; }; + + +EXPECT FAILURE "constant.tests 37": +constants C { const unsigned long C1 = 040000000000; }; + + +EXPECT FAILURE "constant.tests 38": +constants C { const unsigned long C1 = 0x100000000; }; + + +EXPECT FAILURE "constant.tests 39": +constants C { const hyper C1 = -9223372036854775809; }; + + +EXPECT FAILURE "constant.tests 40": +constants C { const hyper C1 = -01000000000000000000001; }; + + +EXPECT FAILURE "constant.tests 41": +constants C { const hyper C1 = -0x8000000000000001; }; + + +EXPECT FAILURE "constant.tests 42": +constants C { const hyper C1 = 9223372036854775808; }; + + +EXPECT FAILURE "constant.tests 43": +constants C { const hyper C1 = 01000000000000000000000; }; + + +EXPECT FAILURE "constant.tests 44": +constants C { const hyper C1 = 0x8000000000000000; }; + + +EXPECT FAILURE "constant.tests 45": +constants C { const unsigned hyper C1 = -1; }; + + +EXPECT FAILURE "constant.tests 46": +constants C { const unsigned hyper C1 = -01; }; + + +EXPECT FAILURE "constant.tests 47": +constants C { const unsigned hyper C1 = -0x1; }; + + +EXPECT FAILURE "constant.tests 48": +constants C { const unsigned hyper C1 = 18446744073709551616; }; + + +EXPECT FAILURE "constant.tests 49": +constants C { const unsigned hyper C1 = 02000000000000000000000; }; + + +EXPECT FAILURE "constant.tests 50": +constants C { const unsigned hyper C1 = 0x10000000000000000; }; diff --git a/idlc/test/parser/constructor.tests b/idlc/test/parser/constructor.tests new file mode 100644 index 000000000..ce2438b98 --- /dev/null +++ b/idlc/test/parser/constructor.tests @@ -0,0 +1,190 @@ +# +# 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 . +# + +EXPECT SUCCESS "constructor.tests 1": +interface X {}; +service S: X; + + +EXPECT SUCCESS "constructor.tests 2": +interface X {}; +service S: X {}; + + +EXPECT SUCCESS "constructor.tests 3": +interface X {}; +service S: X { + f(); +}; + + +EXPECT FAILURE "constructor.tests 4": +interface X {}; +service S: X { + f(); + f(); +}; + + +EXPECT FAILURE "constructor.tests 5": +interface X { + void f([in] any... p); +}; + + +EXPECT FAILURE "constructor.tests 6": +interface X { + void f([out] any... p); +}; + + +EXPECT SUCCESS "constructor.tests 7": +interface X {}; +service S: X { + f([in] any... p); +}; + + +EXPECT SUCCESS "constructor.tests 8": +interface X {}; +typedef any some; +service S: X { + f([in] some... p); +}; + + +EXPECT FAILURE "constructor.tests 9": +interface X {}; +service S: X { + f([in] long p1, [in] any... p2); +}; + + +EXPECT FAILURE "constructor.tests 10": +interface X {}; +service S: X { + f([in] any... p2, [in] long p1); +}; + + +EXPECT FAILURE "constructor.tests 11": +interface X {}; +service S: X { + f([in] long p1, [in] long... p2); +}; + + +EXPECT FAILURE "constructor.tests 12": +interface X {}; +service S: X { + f([out] long p); +}; + + +EXPECT FAILURE "constructor.tests 13": +interface X {}; +service S: X { + f([out] any... p); +}; + + +EXPECT FAILURE "constructor.tests 14": +interface X {}; +singleton S: X { + f(); +}; + + +EXPECT FAILURE "constructor.tests 15": +module com { module sun { module star { module test { + interface X {}; +service S: com::sun::star::test::X { + c1([in] long a, [in] com::sun::star::test::X b); + c2([in] long c, [in] X d); +}; +}; }; }; }; + + +EXPECT FAILURE "constructor.tests 16": +module com { module sun { module star { module test { + interface X {}; +}; }; }; }; +typedef long T; +service S: com::sun::star::test::X { + c1([in] sequence<long> a); + c2([in] sequence<T> b); +}; + + +EXPECT FAILURE "constructor.tests 17": +module com { module sun { module star { module test { + interface X {}; +}; }; }; }; +service S: com::sun::star::test::X { + c1([in] any... a); + c2([in] any... b); +}; + + +EXPECT SUCCESS "constructor.tests 18": +module com { module sun { module star { module test { + interface X {}; +}; }; }; }; +service S: com::sun::star::test::X { + c1([in] any... a); + c2([in] sequence<any> b); +}; + + +EXPECT SUCCESS "constructor.tests 19": +module com { module sun { module star { module test { + interface X { void m(); }; +}; }; }; }; +service S: com::sun::star::test::X { + c([in] any... a); +}; + + +EXPECT SUCCESS "constructor.tests 20": +module com { module sun { module star { module uno { + interface XInterface { void m(); }; +}; }; }; }; +service S: com::sun::star::uno::XInterface { + c1([in] long a, [in] long b); + c2([in] long a); +}; + + +EXPECT SUCCESS "constructor.tests 21": +module com { module sun { module star { module uno { + interface XInterface { void m(); }; +}; }; }; }; +service S: com::sun::star::uno::XInterface { + c1([in] long a); + c2([in] long a, [in] long b); +}; + + +EXPECT SUCCESS "constructor.tests 22": +module com { module sun { module star { module uno { + interface XInterface { void m(); }; +}; }; }; }; +service S: com::sun::star::uno::XInterface { + c1([in] long a, [in] short b); + c2([in] long a, [in] long b); +}; diff --git a/idlc/test/parser/conversion.tests b/idlc/test/parser/conversion.tests new file mode 100644 index 000000000..4f1d6bc7d --- /dev/null +++ b/idlc/test/parser/conversion.tests @@ -0,0 +1,79 @@ +# +# 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/. +# + +EXPECT SUCCESS "conversion.tests 1": +constants C { + const byte C1 = -128.0; + const byte C2 = -127.9; + const byte C3 = 254.9; + const byte C4 = 255.0; + const short C5 = -32768.0; + const short C6 = -32767.9; + const short C7 = 32766.9; + const short C8 = 32767.0; + const unsigned short C9 = 0.0; + const unsigned short C10 = 0.1; + const unsigned short C11 = 65534.9; + const unsigned short C12 = 65535.0; + const long C13 = -2147483648.0; + const long C14 = -2147483647.9; + const long C15 = 2147483646.9; + const long C16 = 2147483647.0; + const unsigned long C17 = 0.0; + const unsigned long C18 = 0.1; + const unsigned long C19 = 4294967294.9; + const unsigned long C20 = 4294967295.0; + const hyper C21 = -9223372036854774784.0; // -0x7FFFFFFFFFFFFC00 = -0x1.FFFFFFFFFFFFFp62 + const hyper C22 = 9223372036854774784.0; // 0x7FFFFFFFFFFFFC00 = 0x1.FFFFFFFFFFFFFp62 + const unsigned hyper C23 = 0.0; + const unsigned hyper C24 = 0.1; + const unsigned hyper C25 = 18446744073709549568.0; // 0xFFFFFFFFFFFFF800 = 0x1.FFFFFFFFFFFFFp63 +}; + +EXPECT FAILURE "conversion.tests 2": +constants C { const byte C1 = -128.1; }; + +EXPECT FAILURE "conversion.tests 3": +constants C { const byte C1 = 255.1; }; + +EXPECT FAILURE "conversion.tests 4": +constants C { const short C1 = -32768.1; }; + +EXPECT FAILURE "conversion.tests 5": +constants C { const short C1 = 32767.1; }; + +EXPECT FAILURE "conversion.tests 6": +constants C { const unsigned short C1 = -0.1; }; + +EXPECT FAILURE "conversion.tests 7": +constants C { const unsigned short C1 = 65535.1; }; + +EXPECT FAILURE "conversion.tests 8": +constants C { const long C1 = -2147483648.1; }; + +EXPECT FAILURE "conversion.tests 9": +constants C { const long C1 = 2147483647.1; }; + +EXPECT FAILURE "conversion.tests 10": +constants C { const unsigned long C1 = -0.1; }; + +EXPECT FAILURE "conversion.tests 11": +constants C { const unsigned long C1 = 4294967295.1; }; + +EXPECT FAILURE "conversion.tests 12": +constants C { const hyper C1 = -9223372036854775808.0; }; // -0x8000000000000000 = -0x1p63 + +EXPECT FAILURE "conversion.tests 13": +constants C { const hyper C1 = 9223372036854775807.0; }; // 0x7FFFFFFFFFFFFFFF rounds up to 0x1p63 + +EXPECT FAILURE "conversion.tests 14": +constants C { const unsigned hyper C1 = -0.1; }; + +EXPECT FAILURE "conversion.tests 15": +constants C { const unsigned hyper C1 = 18446744073709551615.0; }; + // 0xFFFFFFFFFFFFFFFF rounds up to 0x1p64 diff --git a/idlc/test/parser/interfaceinheritance.tests b/idlc/test/parser/interfaceinheritance.tests new file mode 100644 index 000000000..f9cac4ca2 --- /dev/null +++ b/idlc/test/parser/interfaceinheritance.tests @@ -0,0 +1,279 @@ +# +# 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 . +# + +EXPECT FAILURE "interfaceinheritance.tests 1": +interface Base {}; +interface Derived { + interface Base; + interface Base; +}; + + +EXPECT FAILURE "interfaceinheritance.tests 2": +interface Base {}; +interface Derived { + interface Base; + [optional] interface Base; +}; + + +EXPECT FAILURE "interfaceinheritance.tests 3": +interface Base {}; +interface Derived { + [optional] interface Base; + interface Base; +}; + + +EXPECT FAILURE "interfaceinheritance.tests 4": +interface Base {}; +interface Derived { + [optional] interface Base; + [optional] interface Base; +}; + + +EXPECT FAILURE "interfaceinheritance.tests 5": +interface Base1 {}; +interface Base2: Base1 {}; +interface Derived { + interface Base1; + interface Base2; +}; + + +EXPECT FAILURE "interfaceinheritance.tests 6": +interface Base1 {}; +interface Base2: Base1 {}; +interface Derived { + interface Base2; + interface Base1; +}; + + +EXPECT FAILURE "interfaceinheritance.tests 7": +interface Base1 {}; +interface Base2: Base1 {}; +interface Derived { + [optional] interface Base1; + interface Base2; +}; + + +EXPECT FAILURE "interfaceinheritance.tests 8": +interface Base1 {}; +interface Base2: Base1 {}; +interface Derived { + interface Base2; + [optional] interface Base1; +}; + + +EXPECT SUCCESS "interfaceinheritance.tests 9": +interface Base1 {}; +interface Base2: Base1 {}; +interface Derived { + interface Base1; + [optional] interface Base2; +}; + + +EXPECT SUCCESS "interfaceinheritance.tests 10": +interface Base1 {}; +interface Base2: Base1 {}; +interface Derived { + [optional] interface Base2; + interface Base1; +}; + + +EXPECT SUCCESS "interfaceinheritance.tests 11": +interface Base1 {}; +interface Base2: Base1 {}; +interface Derived { + [optional] interface Base1; + [optional] interface Base2; +}; + + +EXPECT SUCCESS "interfaceinheritance.tests 12": +interface Base1 {}; +interface Base2: Base1 {}; +interface Derived { + [optional] interface Base2; + [optional] interface Base1; +}; + + +EXPECT SUCCESS "interfaceinheritance.tests 13": +interface Base1 {}; +interface Base2 { [optional] interface Base1; }; +interface Derived { + interface Base1; + interface Base2; +}; + + +EXPECT SUCCESS "interfaceinheritance.tests 14": +interface Base1 {}; +interface Base2 { [optional] interface Base1; }; +interface Derived { + interface Base2; + interface Base1; +}; + + +EXPECT FAILURE "interfaceinheritance.tests 15": +interface Base1 {}; +interface Base2 { [optional] interface Base1; }; +interface Derived { + [optional] interface Base1; + interface Base2; +}; + + +EXPECT FAILURE "interfaceinheritance.tests 16": +interface Base1 {}; +interface Base2 { [optional] interface Base1; }; +interface Derived { + interface Base2; + [optional] interface Base1; +}; + + +EXPECT SUCCESS "interfaceinheritance.tests 17": +interface Base1 {}; +interface Base2 { [optional] interface Base1; }; +interface Derived { + interface Base1; + [optional] interface Base2; +}; + + +EXPECT SUCCESS "interfaceinheritance.tests 18": +interface Base1 {}; +interface Base2 { [optional] interface Base1; }; +interface Derived { + [optional] interface Base2; + interface Base1; +}; + + +EXPECT SUCCESS "interfaceinheritance.tests 19": +interface Base1 {}; +interface Base2 { [optional] interface Base1; }; +interface Derived { + [optional] interface Base1; + [optional] interface Base2; +}; + + +EXPECT SUCCESS "interfaceinheritance.tests 20": +interface Base1 {}; +interface Base2 { [optional] interface Base1; }; +interface Derived { + [optional] interface Base2; + [optional] interface Base1; +}; + + +EXPECT SUCCESS "interfaceinheritance.tests 21": +interface Base1 {}; +interface Base2: Base1 {}; +interface Base3: Base1 {}; +interface Derived { + interface Base2; + interface Base3; +}; + + +EXPECT SUCCESS "interfaceinheritance.tests 22": +interface Base1 {}; +interface Base2: Base1 {}; +interface Base3: Base1 {}; +interface Derived { + [optional] interface Base2; + interface Base3; +}; + + +EXPECT SUCCESS "interfaceinheritance.tests 23": +interface Base1 {}; +interface Base2: Base1 {}; +interface Base3: Base1 {}; +interface Derived { + interface Base2; + [optional] interface Base3; +}; + + +EXPECT SUCCESS "interfaceinheritance.tests 24": +interface Base1 {}; +interface Base2: Base1 {}; +interface Base3: Base1 {}; +interface Derived { + [optional] interface Base2; + [optional] interface Base3; +}; + + +EXPECT SUCCESS "interfaceinheritance.tests 25": +interface Base {}; +interface Derived { + [optional] interface Base; +}; + + +EXPECT FAILURE "interfaceinheritance.tests 26": +interface Base; +interface Derived { + interface Base; +}; + + +EXPECT FAILURE "interfaceinheritance.tests 27": +interface Base; +interface Derived { + [optional] interface Base; +}; + + +EXPECT FAILURE "interfaceinheritance.tests 28": +interface Base {}; +typedef Base Hidden; +interface Derived { + interface Base; + interface Hidden; +}; + + +EXPECT FAILURE "interfaceinheritance.tests 29": +interface Base {}; +typedef Base Hidden; +interface Derived { + interface Hidden; + interface Base; +}; + + +EXPECT FAILURE "interfaceinheritance.tests 30": +interface Base {}; +interface Derived { + interface Base; + [optional] interface com::sun::star::uno::XInterface; +}; diff --git a/idlc/test/parser/methodoverload.tests b/idlc/test/parser/methodoverload.tests new file mode 100644 index 000000000..9a07a4b2c --- /dev/null +++ b/idlc/test/parser/methodoverload.tests @@ -0,0 +1,177 @@ +# +# 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 . +# + +EXPECT FAILURE "methodoverload.tests 1": +interface Derived { + void f(); + void f(); +}; + + +EXPECT FAILURE "methodoverload.tests 2": +interface Base { + void f(); +}; +interface Derived { + interface Base; + void f(); +}; + + +EXPECT FAILURE "methodoverload.tests 3": +interface Base { + void f(); +}; +interface Derived { + void f(); + interface Base; +}; + + +EXPECT FAILURE "methodoverload.tests 4": +interface Base { + void f(); +}; +interface Derived { + [optional] interface Base; + void f(); +}; + + +EXPECT FAILURE "methodoverload.tests 5": +interface Base { + void f(); +}; +interface Derived { + void f(); + [optional] interface Base; +}; + + +EXPECT FAILURE "methodoverload.tests 6": +interface Base1 { + void f(); +}; +interface Base2 { + void f(); +}; +interface Derived { + interface Base1; + interface Base2; +}; + + +EXPECT FAILURE "methodoverload.tests 7": +interface Base1 { + void f(); +}; +interface Base2 { + void f(); +}; +interface Derived { + [optional] interface Base1; + interface Base2; +}; + + +EXPECT FAILURE "methodoverload.tests 8": +interface Base1 { + void f(); +}; +interface Base2 { + void f(); +}; +interface Derived { + interface Base1; + [optional] interface Base2; +}; + + +EXPECT SUCCESS "methodoverload.tests 9": +interface Base1 { + void f(); +}; +interface Base2 { + void f(); +}; +interface Derived { + [optional] interface Base1; + [optional] interface Base2; +}; + + +EXPECT FAILURE "methodoverload.tests 10": +interface I { + [attribute] long a; + [attribute] short a; +}; + + +EXPECT FAILURE "methodoverload.tests 11": +interface I1 { + [attribute] long a; +}; +interface I2 { + [attribute] short a; + interface I1; +}; + + +EXPECT FAILURE "methodoverload.tests 12": +interface I { + [attribute] long a; + void a(); +}; + + +EXPECT FAILURE "methodoverload.tests 13": +interface I1 { + [attribute] long a; +} +interface I2 { + void a(); + interface I1; +}; + + +EXPECT FAILURE "methodoverload.tests 14": +interface I1 { + void a(); +} +interface I2 { + [attribute] long a; + interface I1; +}; + + +EXPECT SUCCESS "methodoverload.tests 15": +interface I { + [attribute] long a; + void geta(); + void seta(); +}; + + +EXPECT SUCCESS "methodoverload.tests 16": +interface I1 { + [attribute] long a; +}; +interface I2: I1 { + void geta(); + void seta(); +}; diff --git a/idlc/test/parser/oldstyle.tests b/idlc/test/parser/oldstyle.tests new file mode 100644 index 000000000..c6692b977 --- /dev/null +++ b/idlc/test/parser/oldstyle.tests @@ -0,0 +1,28 @@ +# +# 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/. +# + +EXPECT SUCCESS "oldstyle.tests 1": +service S1 {}; +service S2 { service S1; }; + + +EXPECT FAILURE "oldstyle.tests 2": +interface X {}; +service S1: X; +service S2 { service S1; }; + + +EXPECT SUCCESS "oldstyle.tests 3": +service S1 {}; +singleton S2 { service S1; }; + + +EXPECT FAILURE "oldstyle.tests 4": +interface X {}; +service S1: X; +singleton S2 { service S1; }; diff --git a/idlc/test/parser/polystruct.tests b/idlc/test/parser/polystruct.tests new file mode 100644 index 000000000..89b0817c9 --- /dev/null +++ b/idlc/test/parser/polystruct.tests @@ -0,0 +1,251 @@ +# +# 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 . +# + +EXPECT SUCCESS "polystruct.tests 1": +struct Struct<T> { T member; }; + + +EXPECT FAILURE "polystruct.tests 2": +struct Struct<T,U,T,V> { long member; }; + + +EXPECT FAILURE "polystruct.tests 3": +struct Struct<T> { long member; }; +typedef Struct Typedef; + + +EXPECT FAILURE "polystruct.tests 4": +struct Struct<T> { long member; }; +typedef Struct<long> Typedef; + + +EXPECT SUCCESS "polystruct.tests 5": +struct Struct<T> { long member; }; + + +EXPECT SUCCESS "polystruct.tests 6": +struct Struct1<T> { T member; }; +struct Struct2 { Struct1<long> member; }; + + +EXPECT SUCCESS "polystruct.tests 7": +struct Struct1<T> { T member; }; +struct Struct2 { Struct1<Struct1<string> > member; }; + + +EXPECT FAILURE "polystruct.tests 8": +struct Struct1<T> { T member; }; +struct Struct2 { Struct1<int> member; }; + + +EXPECT FAILURE "polystruct.tests 9": +struct Struct1<T> { T member; }; +struct Struct2 { Struct1<long,long> member; }; + + +EXPECT FAILURE "polystruct.tests 10": +struct Struct2 { Struct1<long> member; }; + + +EXPECT FAILURE "polystruct.tests 11": +struct Struct1<T> { T member; }; +struct Struct2 { Struct1<> member; }; + + +EXPECT FAILURE "polystruct.tests 12": +struct Struct1<T> { T member; }; +struct Struct2 { Struct1<void> member; }; + + +EXPECT FAILURE "polystruct.tests 13": +exception Exception {}; +struct Struct1<T> { T member; }; +struct Struct2 { Struct1<Exception> member; }; + + +EXPECT SUCCESS "polystruct.tests 14": +struct Struct<T> { T T; }; + + +EXPECT SUCCESS "polystruct.tests 15": +struct Struct<Struct> { Struct member; }; + + +EXPECT FAILURE "polystruct.tests 16": +struct Struct<Struct> { Struct<long> member; }; + + +EXPECT FAILURE "polystruct.tests 17": +struct Struct<Struct> { ::Struct member; }; + + +EXPECT FAILURE "polystruct.tests 18": +struct Struct<Struct> { ::Struct<long> member; }; + + +EXPECT SUCCESS "polystruct.tests 19": +struct Struct1<T> { T member; }; +struct Struct2<Struct1> { Struct1 member; }; + + +EXPECT SUCCESS "polystruct.tests 20": +struct Struct1<T> { T member; }; +struct Struct2<Struct1> { Struct1<long> member; }; + + +EXPECT SUCCESS "polystruct.tests 21": +struct Struct1<T> { T member; }; +struct Struct2<Struct1> { ::Struct1<long> member; }; + + +EXPECT FAILURE "polystruct.tests 22": +struct Struct1 { long member1; }; +struct Struct2<T>: Struct1 { long member2; }; + + +EXPECT FAILURE "polystruct.tests 23": +struct Struct1<T> { long member1; }; +struct Struct2: Struct1<long> { long member2; }; + + +EXPECT FAILURE "polystruct.tests 24": +struct Struct1<T> { long member1; }; +struct Struct2<T>: Struct1<long> { long member2; }; + + +EXPECT FAILURE "polystruct.tests 25": +struct Struct1<T> { long member; }; +struct Struct2 { Struct1<Struct2> member; }; + + +EXPECT SUCCESS "polystruct.tests 25a": +struct Struct<T> { long member; }; +interface X { [attribute] Struct<X> member; }; + + +EXPECT FAILURE "polystruct.tests 26": +struct Struct1<T> { long member; }; +struct Struct2<T> { long member; }; +struct Struct3 { Struct1<Struct2<Struct3> > member; }; + + +EXPECT SUCCESS "polystruct.tests 27": +struct Struct1<T> { long member; }; +struct Struct2 { Struct1<sequence<Struct2> > member; }; + + +EXPECT SUCCESS "polystruct.tests 28": +struct Struct1<T> { long member; }; +struct Struct2 { Struct1<sequence<sequence<Struct2> > > member; }; + + +EXPECT SUCCESS "polystruct.tests 29": +struct Struct1<T> { long member; }; +struct Struct2 { sequence<Struct1<Struct2> > member; }; + + +EXPECT SUCCESS "polystruct.tests 30": +struct Struct1<T> { long member; }; +struct Struct2 { sequence<Struct1<sequence<Struct2> > > member; }; + + +EXPECT SUCCESS "polystruct.tests 31": +struct Struct1<T> { long member; }; +struct Struct2 { sequence<sequence<Struct1<Struct2> > > member; }; + + +EXPECT FAILURE "polystruct.tests 32": +struct Struct<T> { Struct member; }; + + +EXPECT FAILURE "polystruct.tests 33": +struct Struct<T> { Struct<long> member; }; + + +EXPECT FAILURE "polystruct.tests 34": +struct Struct<T> { Struct<Struct> member; }; + + +EXPECT FAILURE "polystruct.tests 35": +struct Struct<T> { Struct<Struct<long> > member; }; + + +EXPECT FAILURE "polystruct.tests 36": +struct Struct1<T> { long member; }; +struct Struct2<T> { Struct1<Struct2> member; }; + + +EXPECT FAILURE "polystruct.tests 37": +struct Struct1<T> { long member; }; +struct Struct2<T> { long member; }; +struct Struct3<T> { Struct1<Struct2<Struct3> > member; }; + + +EXPECT FAILURE "polystruct.tests 38": +struct Struct1<T> { long member; }; +struct Struct2<T> { Struct1<Struct2<long> > member; }; + + +EXPECT FAILURE "polystruct.tests 39": +struct Struct1<T> { long member; }; +struct Struct2<T> { long member; }; +struct Struct3<T> { Struct1<Struct2<Struct3<long> > > member; }; + + +EXPECT FAILURE "polystruct.tests 40": +struct Struct1<T> { long member; }; +struct Struct2 { Struct1<unsigned short> member; }; + + +EXPECT FAILURE "polystruct.tests 41": +struct Struct1<T, U> { long member; }; +struct Struct2<T> { long member; }; +struct Struct3 { Struct2<Struct1<long, unsigned long> > member; }; + + +EXPECT FAILURE "polystruct.tests 42": +struct Struct<T> { long member; }; +interface X { void f([in] Struct<unsigned hyper> p); }; + + +EXPECT FAILURE "polystruct.tests 43": +struct Struct1<T> { long member; }; +struct Struct2 { Struct1<sequence<unsigned short> > member; }; + + +EXPECT SUCCESS "polystruct.tests 44": +struct Struct1<T> { long member; }; +struct Struct2 { Struct1<sequence<char> > member; }; + + +EXPECT FAILURE "polystruct.tests 45": +struct Struct1<T> { long member; }; +typedef unsigned short td; +struct Struct2 { Struct1<td> member; }; + + +EXPECT FAILURE "polystruct.tests 46": +struct Struct1<T> { long member; }; +typedef sequence<unsigned short> td; +struct Struct2 { Struct1<td> member; }; + + +EXPECT FAILURE "polystruct.tests 47": +struct Struct1<T> { long member; }; +typedef unsigned short td; +struct Struct2 { Struct1<sequence<td> > member; }; diff --git a/idlc/test/parser/published.tests b/idlc/test/parser/published.tests new file mode 100644 index 000000000..f81ef6b41 --- /dev/null +++ b/idlc/test/parser/published.tests @@ -0,0 +1,681 @@ +# +# 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 . +# + +EXPECT SUCCESS "published.tests 1": +published enum Enum { VALUE }; +published struct Struct1 { long member; }; +published struct Struct2<T> { T member; }; +published exception E1 {}; +published interface I1 {}; +published typedef long Typedef; +published constants Constants { const long Constant = 1; }; +published service Service1: I1 {}; +published service Service2 { interface I1; }; +published singleton Singleton1: I1; +published singleton Singleton2 { service Service2; }; + + +EXPECT FAILURE "published.tests 2": +constants Constants { published const long C = 1; }; + + +EXPECT FAILURE "published.tests 3": +published constants Constants { published const long C = 1; }; + + +EXPECT FAILURE "published.tests 4": +published module m {}; + + +EXPECT SUCCESS "published.tests 5": +interface I1; +interface I1 {}; + + +EXPECT SUCCESS "published.tests 6": +interface I1; +published interface I1 {}; + + +EXPECT FAILURE "published.tests 7": +published interface I1; +interface I1 {}; + + +EXPECT SUCCESS "published.tests 8": +published interface I1; +published interface I1 {}; + + +EXPECT SUCCESS "published.tests 9": +struct S1 { long m1; }; +struct S2: S1 { long m2; }; + + +EXPECT FAILURE "published.tests 10": +struct S1 { long m1; }; +published struct S2: S1 { long m2; }; + + +EXPECT SUCCESS "published.tests 11": +published struct S1 { long m1; }; +struct S2: S1 { long m2; }; + + +EXPECT SUCCESS "published.tests 12": +published struct S1 { long m1; }; +published struct S2: S1 { long m2; }; + + +EXPECT SUCCESS "published.tests 13": +enum E { V }; +struct S1<T> { T m1; }; +struct S2 { S1<E> m2; }; + + +EXPECT FAILURE "published.tests 14": +enum E { V }; +struct S1<T> { T m1; }; +published struct S2 { S1<E> m2; }; + + +EXPECT SUCCESS "published.tests 15": +enum E { V }; +published struct S1<T> { T m1; }; +struct S2 { S1<E> m2; }; + + +EXPECT FAILURE "published.tests 16": +enum E { V }; +published struct S1<T> { T m1; }; +published struct S2 { S1<E> m2; }; + + +EXPECT SUCCESS "published.tests 17": +published enum E { V }; +struct S1<T> { T m1; }; +struct S2 { S1<E> m2; }; + + +EXPECT FAILURE "published.tests 18": +published enum E { V }; +struct S1<T> { T m1; }; +published struct S2 { S1<E> m2; }; + + +EXPECT SUCCESS "published.tests 19": +published enum E { V }; +published struct S1<T> { T m1; }; +struct S2 { S1<E> m2; }; + + +EXPECT SUCCESS "published.tests 20": +published enum E { V }; +published struct S1<T> { T m1; }; +published struct S2 { S1<E> m2; }; + + +EXPECT SUCCESS "published.tests 21": +module com { module sun { module star { module uno { +exception Exception {}; +exception E2: Exception {}; +}; }; }; }; + + +EXPECT FAILURE "published.tests 22": +module com { module sun { module star { module uno { +exception Exception {}; +published exception E2: Exception {}; +}; }; }; }; + + +EXPECT SUCCESS "published.tests 23": +module com { module sun { module star { module uno { +published exception Exception {}; +exception E2: Exception {}; +}; }; }; }; + + +EXPECT SUCCESS "published.tests 24": +module com { module sun { module star { module uno { +published exception Exception {}; +published exception E2: Exception {}; +}; }; }; }; + + +EXPECT SUCCESS "published.tests 25": +enum E { V }; +module com { module sun { module star { module uno { +exception Exception { E m; }; +}; }; }; }; + + +EXPECT FAILURE "published.tests 26": +enum E { V }; +module com { module sun { module star { module uno { +published exception Exception { E m; }; +}; }; }; }; + + +EXPECT SUCCESS "published.tests 27": +published enum E { V }; +module com { module sun { module star { module uno { +exception Exception { E m; }; +}; }; }; }; + + +EXPECT SUCCESS "published.tests 28": +published enum E { V }; +module com { module sun { module star { module uno { +published exception Exception { E m; }; +}; }; }; }; + + +EXPECT SUCCESS "published.tests 29": +interface I1 {}; +interface I2: I1 {}; + + +EXPECT FAILURE "published.tests 30": +interface I1 {}; +published interface I2: I1 {}; + + +EXPECT SUCCESS "published.tests 31": +published interface I1 {}; +interface I2: I1 {}; + + +EXPECT SUCCESS "published.tests 32": +published interface I1 {}; +published interface I2: I1 {}; + + +EXPECT SUCCESS "published.tests 33": +enum E { V }; +interface I1 { [attribute] E m; }; + + +EXPECT FAILURE "published.tests 34": +enum E { V }; +published interface I1 { [attribute] E m; }; + + +EXPECT SUCCESS "published.tests 35": +published enum E { V }; +interface I1 { [attribute] E m; }; + + +EXPECT SUCCESS "published.tests 36": +published enum E { V }; +published interface I1 { [attribute] E m; }; + + +EXPECT SUCCESS "published.tests 36a.1": +module com { module sun { module star { module uno { +exception Exception {}; +interface I1 { [attribute] long m { get raises (Exception); }; }; +}; }; }; }; + + +EXPECT FAILURE "published.tests 36a.2": +module com { module sun { module star { module uno { +exception Exception {}; +published interface I1 { + [attribute] long m { get raises (Exception); }; }; +}; }; }; }; + + +EXPECT SUCCESS "published.tests 36a.3": +module com { module sun { module star { module uno { +published exception Exception {}; +interface I1 { [attribute] long m { get raises (Exception); }; }; +}; }; }; }; + + +EXPECT SUCCESS "published.tests 36a.4": +module com { module sun { module star { module uno { +published exception Exception {}; +published interface I1 { + [attribute] long m { get raises (Exception); }; }; +}; }; }; }; + + +EXPECT SUCCESS "published.tests 37": +enum E { V }; +interface I1 { E f(); }; + + +EXPECT FAILURE "published.tests 38": +enum E { V }; +published interface I1 { E f(); }; + + +EXPECT SUCCESS "published.tests 39": +published enum E { V }; +interface I1 { E f(); }; + + +EXPECT SUCCESS "published.tests 40": +published enum E { V }; +published interface I1 { E f(); }; + + +EXPECT SUCCESS "published.tests 41": +enum E { V }; +interface I1 { void f([in] E p); }; + + +EXPECT FAILURE "published.tests 42": +enum E { V }; +published interface I1 { void f([in] E p); }; + + +EXPECT SUCCESS "published.tests 43": +published enum E { V }; +interface I1 { void f([in] E p); }; + + +EXPECT SUCCESS "published.tests 44": +published enum E { V }; +published interface I1 { void f([in] E p); }; + + +EXPECT SUCCESS "published.tests 45": +module com { module sun { module star { module uno { +exception Exception {}; +interface I1 { void f() raises (Exception); }; +}; }; }; }; + + +EXPECT FAILURE "published.tests 46": +module com { module sun { module star { module uno { +exception Exception {}; +published interface I1 { void f() raises (Exception); }; +}; }; }; }; + + +EXPECT SUCCESS "published.tests 47": +module com { module sun { module star { module uno { +published exception Exception {}; +interface I1 { void f() raises (Exception); }; +}; }; }; }; + + +EXPECT SUCCESS "published.tests 48": +module com { module sun { module star { module uno { +published exception Exception {}; +published interface I1 { void f() raises (Exception); }; +}; }; }; }; + + +EXPECT SUCCESS "published.tests 49": +interface I1 {}; +interface I2 { interface I1; }; + + +EXPECT FAILURE "published.tests 50": +interface I1 {}; +published interface I2 { interface I1; }; + + +EXPECT SUCCESS "published.tests 51": +published interface I1 {}; +interface I2 { interface I1; }; + + +EXPECT SUCCESS "published.tests 52": +published interface I1 {}; +published interface I2 { interface I1; }; + + +EXPECT SUCCESS "published.tests 57": +enum E { V }; +typedef E T; + + +EXPECT FAILURE "published.tests 58": +enum E { V }; +published typedef E T; + + +EXPECT SUCCESS "published.tests 59": +published enum E { V }; +typedef E T; + + +EXPECT SUCCESS "published.tests 60": +published enum E { V }; +published typedef E T; + + +EXPECT SUCCESS "published.tests 61": +enum E { V }; +typedef E T; +struct S { T m; }; + + +EXPECT FAILURE "published.tests 62": +enum E { V }; +typedef E T; +published struct S { T m; }; + + +EXPECT FAILURE "published.tests 63": +enum E { V }; +published typedef E T; +struct S { T m; }; + + +EXPECT FAILURE "published.tests 64": +enum E { V }; +published typedef E T; +published struct S { T m; }; + + +EXPECT SUCCESS "published.tests 65": +published enum E { V }; +typedef E T; +struct S { T m; }; + + +EXPECT FAILURE "published.tests 66": +published enum E { V }; +typedef E T; +published struct S { T m; }; + + +EXPECT SUCCESS "published.tests 67": +published enum E { V }; +published typedef E T; +struct S { T m; }; + + +EXPECT SUCCESS "published.tests 68": +published enum E { V }; +published typedef E T; +published struct S { T m; }; + + +EXPECT SUCCESS "published.tests 73": +constants Cs { + const long C1 = 1; + const long C2 = C1 + 1; +}; + + +EXPECT SUCCESS "published.tests 74": +published constants Cs { + const long C1 = 1; + const long C2 = C1 + 1; +}; + + +EXPECT SUCCESS "published.tests 83": +constants Cs1 { const long C1 = 1; }; +constants Cs2 { const long C2 = Cs1::C1 + 1; }; + + +EXPECT FAILURE "published.tests 84": +constants Cs1 { const long C1 = 1; }; +published constants Cs2 { const long C2 = Cs1::C1 + 1; }; + + +EXPECT SUCCESS "published.tests 85": +published constants Cs1 { const long C1 = 1; }; +constants Cs2 { const long C2 = Cs1::C1 + 1; }; + + +EXPECT SUCCESS "published.tests 86": +published constants Cs1 { const long C1 = 1; }; +published constants Cs2 { const long C2 = Cs1::C1 + 1; }; + + +EXPECT SUCCESS "published.tests 87": +typedef long T; +constants Cs { const T C = 1; }; + + +EXPECT FAILURE "published.tests 88": +typedef long T; +published constants Cs { const T C = 1; }; + + +EXPECT SUCCESS "published.tests 89": +published typedef long T; +constants Cs { const T C = 1; }; + + +EXPECT SUCCESS "published.tests 90": +published typedef long T; +published constants Cs { const T C = 1; }; + + +EXPECT SUCCESS "published.tests 91": +service S1 {}; +service S2 { service S1; }; + + +EXPECT FAILURE "published.tests 92": +service S1 {}; +published service S2 { service S1; }; + + +EXPECT SUCCESS "published.tests 93": +published service S1 {}; +service S2 { service S1; }; + + +EXPECT SUCCESS "published.tests 94": +published service S1 {}; +published service S2 { service S1; }; + + +EXPECT SUCCESS "published.tests 95": +interface I1 {}; +service S { interface I1; }; + + +EXPECT FAILURE "published.tests 96": +interface I1 {}; +published service S { interface I1; }; + + +EXPECT SUCCESS "published.tests 97": +published interface I1 {}; +service S { interface I1; }; + + +EXPECT SUCCESS "published.tests 98": +published interface I1 {}; +published service S { interface I1; }; + + +EXPECT SUCCESS "published.tests 99": +interface I1 {}; +service S: I1; + + +EXPECT FAILURE "published.tests 100": +interface I1 {}; +published service S: I1; + + +EXPECT SUCCESS "published.tests 101": +published interface I1 {}; +service S: I1; + + +EXPECT SUCCESS "published.tests 102": +published interface I1 {}; +published service S: I1; + + +EXPECT SUCCESS "published.tests 103": +enum E { V }; +interface I1 {}; +service S: I1 { + f([in] E p); +}; + + +EXPECT FAILURE "published.tests 104": +enum E { V }; +published interface I1 {}; +published service S: I1 { + f([in] E p); +}; + + +EXPECT SUCCESS "published.tests 105": +published enum E { V }; +interface I1 {}; +service S: I1 { + f([in] E p); +}; + + +EXPECT SUCCESS "published.tests 106": +published enum E { V }; +published interface I1 {}; +published service S: I1 { + f([in] E p); +}; + + +EXPECT SUCCESS "published.tests 107": +module com { module sun { module star { module uno { +exception Exception {}; +interface I1 {}; +service S: I1 { + f() raises (Exception); +}; +}; }; }; }; + + +EXPECT FAILURE "published.tests 108": +module com { module sun { module star { module uno { +exception Exception {}; +published interface I1 {}; +published service S: I1 { + f() raises (Exception); +}; +}; }; }; }; + + +EXPECT SUCCESS "published.tests 109": +module com { module sun { module star { module uno { +published exception Exception {}; +interface I1 {}; +service S: I1 { + f() raises (Exception); +}; +}; }; }; }; + + +EXPECT SUCCESS "published.tests 110": +module com { module sun { module star { module uno { +published exception Exception {}; +published interface I1 {}; +published service S: I1 { + f() raises (Exception); +}; +}; }; }; }; + + +EXPECT SUCCESS "published.tests 111": +service S1 {}; +singleton S2 { service S1; }; + + +EXPECT FAILURE "published.tests 112": +service S1 {}; +published singleton S2 { service S1; }; + + +EXPECT SUCCESS "published.tests 113": +published service S1 {}; +singleton S2 { service S1; }; + + +EXPECT SUCCESS "published.tests 114": +published service S1 {}; +published singleton S2 { service S1; }; + + +EXPECT SUCCESS "published.tests 115": +interface I1 {}; +singleton S: I1; + + +EXPECT FAILURE "published.tests 116": +interface I1 {}; +published singleton S: I1; + + +EXPECT SUCCESS "published.tests 117": +published interface I1 {}; +singleton S: I1; + + +EXPECT SUCCESS "published.tests 118": +published interface I1 {}; +published singleton S: I1; + + +EXPECT FAILURE "published.tests 119": +interface I1 {}; +published interface I2 { [optional] interface I1; }; + + +EXPECT FAILURE "published.tests 120": +service S1 {}; +published service S2 { [optional] service S1; }; + + +EXPECT SUCCESS "published.tests 121": +interface I {}; +published service S { [optional] interface I; }; + + +EXPECT FAILURE "published.tests 122": +interface I {}; +published service S { [optional, property] I p; }; + + +EXPECT FAILURE "published.tests 123": +interface I {}; +published service S { [optional, property] sequence<I> p; }; + + +EXPECT FAILURE "published.tests 124": +struct P<T> { T m; }; +interface I {}; +published service S { [optional, property] P<I> p; }; + + +EXPECT FAILURE "published.tests 125": +published struct P<T> { T m; }; +interface I {}; +published service S { [optional, property] P<I> p; }; + + +EXPECT FAILURE "published.tests 126": +struct P<T> { T m; }; +published interface I {}; +published service S { [optional, property] P<I> p; }; diff --git a/idlc/test/parser/struct.tests b/idlc/test/parser/struct.tests new file mode 100644 index 000000000..77d500e89 --- /dev/null +++ b/idlc/test/parser/struct.tests @@ -0,0 +1,46 @@ +# +# 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 . +# + +EXPECT FAILURE "struct.tests 1": +struct S { void m; }; + + +EXPECT FAILURE "struct.tests 2": +struct S { sequence<void> m; }; + + +EXPECT FAILURE "struct.tests 3": +exception E {}; +struct S { E m; }; + + +EXPECT FAILURE "struct.tests 4": +exception E {}; +struct S { sequence<E> m; }; + + +EXPECT FAILURE "struct.tests 5": +struct S { S m; }; + + +EXPECT SUCCESS "struct.tests 6": +struct S { sequence<S> m; }; + + +EXPECT SUCCESS "struct.tests 7": +struct S { sequence<sequence<S> > m; }; diff --git a/idlc/test/parser/typedef.tests b/idlc/test/parser/typedef.tests new file mode 100644 index 000000000..0eaf5d634 --- /dev/null +++ b/idlc/test/parser/typedef.tests @@ -0,0 +1,63 @@ +# +# 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 . +# + +EXPECT SUCCESS "typedef.tests 1": +struct Struct1 { long member1; }; +typedef Struct1 T1; +typedef T1 T2; +struct Struct2: T2 { long member2; }; + + +EXPECT FAILURE "typedef.tests 2": +typedef long T1; +typedef T1 T2; +struct Struct: T2 { long member2; }; + + +EXPECT SUCCESS "typedef.tests 3": +interface Interface1 {}; +typedef Interface1 T1; +typedef T1 T2; +interface Interface2: T2 {}; + + +EXPECT FAILURE "typedef.tests 4": +interface Interface1; +typedef Interface1 T1; +typedef T1 T2; +interface Interface2: T2 {}; + + +EXPECT FAILURE "typedef.tests 5": +typedef long T1; +typedef T1 T2; +interface Interface: T2 {}; + + +EXPECT FAILURE "typedef.tests 6": +typedef void T; + + +EXPECT FAILURE "typedef.tests 7": +exception E {}; +typedef E T; + + +EXPECT FAILURE "typdef.tests 8": +constants C {}; +typedef C T; diff --git a/idlc/test/service.idl b/idlc/test/service.idl new file mode 100644 index 000000000..79107f933 --- /dev/null +++ b/idlc/test/service.idl @@ -0,0 +1,64 @@ +/* -*- 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 <interface.idl> + +module idlc +{ +module test +{ + +exception bla +{ +}; + +service IdlTest +{ +// [property] bla p0; + [property] short p1; + [optional, property] unsigned short p2; + + [maybevoid, property] long p3; + [bound, property] unsigned long p4; + + [constrained, property] hyper p5; + [transient, property] unsigned hyper p6; + + [maybeambiguous, property] string p7; + [maybedefault, property] type p8; + [removable, property] any p9; + + [readonly, optional, removable, property] ::idlc::test::BaseStruct p10; + + interface XTestBaseTypes; + [optional] interface ::idlc::test::XTestComplexTypes; +}; + +service BetterIdlTest +{ + service IdlTest; + + interface XTestBaseTypes; + [optional] interface ::idlc::test::XTestComplexTypes; +}; + +}; +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/test/singleton.idl b/idlc/test/singleton.idl new file mode 100644 index 000000000..e69e2900f --- /dev/null +++ b/idlc/test/singleton.idl @@ -0,0 +1,61 @@ +/* -*- 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 <interface.idl> + +module idlc +{ +module test +{ + +exception bla +{ +}; + +service IdlTest +{ +// [property] bla p0; + [property] short p1; + [optional, property] unsigned short p2; + + [maybevoid, property] long p3; + [bound, property] unsigned long p4; + + [constrained, property] hyper p5; + [transient, property] unsigned hyper p6; + + [maybeambiguous, property] string p7; + [maybedefault, property] type p8; + [removable, property] any p9; + + [readonly, optional, removable, property] ::idlc::test::BaseStruct p10; + + interface XTestBaseTypes; + [optional] interface ::idlc::test::XTestComplexTypes; +}; + +singleton SingletonTest +{ + service IdlTest; +}; + +}; +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/test/struct.idl b/idlc/test/struct.idl new file mode 100644 index 000000000..133471d2e --- /dev/null +++ b/idlc/test/struct.idl @@ -0,0 +1,121 @@ +/* -*- 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 . + */ + +/* In this file the idl struct will be tested. + bla + */ + +/// idlc defines a test module +module idlc +{ + +/// test defines a test module +module test +{ + +typedef sequence< long > Id; +//struct Bla +//{ +// long bla; +//}; + +/** bla + BaseStruct defines an * initial struct + */ +struct BaseStruct +{ + Id Id; + + /// a short member + short m1; + + /// an unsigned short member + unsigned short m2; + + /// a long member + long m3; + + /// an unsigned long member + unsigned long m4; + + /// a hyper member + hyper m5; + + /// an unsigned hyper member + unsigned hyper m6; + + /// a string member + string m7; + + /// a byte member + byte m8; + + /// a type member + type m9; + + /// a float member + float m10; + + /// a double member + double m11; + + /// a char member + char m12; + + /// a boolean member + boolean m13; + + /// an any member + any m14; +}; + +interface XTestBaseTypes; + +typedef sequence< long > LongSeq; + +typedef sequence< LongSeq > LongSeqSeq; + +/** TestStruct deinfes a struct which inherits + from the base strcut type BaseStruct. +*/ +struct TestStruct : BaseStruct +{ + /// a sequence< long > member + sequence< long > ms1; + + /// a sequence< sequence< long > > member + sequence< sequence< long > > ms2; + + /// an interface member + XTestBaseTypes ms5; + + /// a typedef member + LongSeq ms6; + + /// a further typedef member + LongSeqSeq ms7; + + /// a sequence typedef member + sequence<LongSeq> ms8; + +}; + +}; }; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/test/typelookup.idl b/idlc/test/typelookup.idl new file mode 100644 index 000000000..a9b5612ef --- /dev/null +++ b/idlc/test/typelookup.idl @@ -0,0 +1,80 @@ +/* -*- 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 . + */ + +/* In this file the idl struct will be tested. + bla + */ + +#include <enum.idl> + +typedef short Error; + +/// idlc defines a test module +module idlc +{ + +typedef long Error; + +/// test defines a test module +module test +{ + +/** bla + BaseStruct defines an * initial struct + */ +struct BaseStruct +{ + /// a long member + long m1; + /// a string member + string m2; + /// a byte member + byte m3; + /// a type member + type m4; + /// an enum member, Error in module idlc::test + Error m5; + /// a typedef member, global Error (typedef short) + ::Error m6; + /// a typedef member, Error in module idlc (typedef long) + ::idlc::Error m7; + /// a typedef member, Error in module idlc (typedef long) + idlc::Error m8; + /// an enum member, Error in module idlc::test + test::Error m9; +}; + +/** TestStruct deinfes a struct which inherits + from the base strcut type BaseStruct. +*/ +struct TestStruct : BaseStruct +{ + /// a short member + short ms1; + /// a hyper member + hyper ms2; + /// a sequence<long> member + sequence< long > ms3; +}; + +}; // test + +}; // idlc + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |