summaryrefslogtreecommitdiffstats
path: root/idl
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:06:44 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:06:44 +0000
commited5640d8b587fbcfed7dd7967f3de04b37a76f26 (patch)
tree7a5f7c6c9d02226d7471cb3cc8fbbf631b415303 /idl
parentInitial commit. (diff)
downloadlibreoffice-upstream.tar.xz
libreoffice-upstream.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 '')
-rw-r--r--idl/Executable_svidl.mk60
-rw-r--r--idl/IwyuFilter_idl.yaml2
-rw-r--r--idl/Makefile14
-rw-r--r--idl/Module_idl.mk26
-rw-r--r--idl/README.md9
-rw-r--r--idl/inc/basobj.hxx128
-rw-r--r--idl/inc/bastype.hxx76
-rw-r--r--idl/inc/command.hxx47
-rw-r--r--idl/inc/database.hxx141
-rw-r--r--idl/inc/globals.hxx128
-rw-r--r--idl/inc/hash.hxx61
-rw-r--r--idl/inc/lex.hxx217
-rw-r--r--idl/inc/module.hxx37
-rw-r--r--idl/inc/object.hxx90
-rw-r--r--idl/inc/parser.hxx72
-rw-r--r--idl/inc/slot.hxx134
-rw-r--r--idl/inc/types.hxx118
-rw-r--r--idl/source/cmptools/hash.cxx65
-rw-r--r--idl/source/cmptools/lex.cxx336
-rw-r--r--idl/source/objects/basobj.cxx141
-rw-r--r--idl/source/objects/bastype.cxx120
-rw-r--r--idl/source/objects/module.cxx34
-rw-r--r--idl/source/objects/object.cxx347
-rw-r--r--idl/source/objects/slot.cxx620
-rw-r--r--idl/source/objects/types.cxx320
-rw-r--r--idl/source/prj/command.cxx296
-rw-r--r--idl/source/prj/database.cxx553
-rw-r--r--idl/source/prj/globals.cxx84
-rw-r--r--idl/source/prj/parser.cxx590
-rw-r--r--idl/source/prj/svidl.cxx213
-rw-r--r--idlc/CustomTarget_parser_test.mk91
-rw-r--r--idlc/Executable_idlc.mk81
-rw-r--r--idlc/Makefile14
-rw-r--r--idlc/Module_idlc.mk25
-rw-r--r--idlc/README.md7
-rw-r--r--idlc/inc/astattribute.hxx107
-rw-r--r--idlc/inc/astbasetype.hxx50
-rw-r--r--idlc/inc/astconstant.hxx50
-rw-r--r--idlc/inc/astconstants.hxx35
-rw-r--r--idlc/inc/astdeclaration.hxx136
-rw-r--r--idlc/inc/astenum.hxx45
-rw-r--r--idlc/inc/astexception.hxx35
-rw-r--r--idlc/inc/astexpression.hxx139
-rw-r--r--idlc/inc/astinterface.hxx129
-rw-r--r--idlc/inc/astinterfacemember.hxx45
-rw-r--r--idlc/inc/astmember.hxx48
-rw-r--r--idlc/inc/astmodule.hxx44
-rw-r--r--idlc/inc/astneeds.hxx41
-rw-r--r--idlc/inc/astobserves.hxx41
-rw-r--r--idlc/inc/astoperation.hxx54
-rw-r--r--idlc/inc/astparameter.hxx46
-rw-r--r--idlc/inc/astscope.hxx73
-rw-r--r--idlc/inc/astsequence.hxx49
-rw-r--r--idlc/inc/astservice.hxx61
-rw-r--r--idlc/inc/astservicemember.hxx45
-rw-r--r--idlc/inc/aststack.hxx46
-rw-r--r--idlc/inc/aststruct.hxx62
-rw-r--r--idlc/inc/aststructinstance.hxx49
-rw-r--r--idlc/inc/asttype.hxx37
-rw-r--r--idlc/inc/asttypedef.hxx44
-rw-r--r--idlc/inc/errorhandler.hxx118
-rw-r--r--idlc/inc/fehelper.hxx70
-rw-r--r--idlc/inc/idlc.hxx164
-rw-r--r--idlc/inc/idlctypes.hxx189
-rw-r--r--idlc/inc/inheritedinterface.hxx56
-rw-r--r--idlc/inc/options.hxx76
-rw-r--r--idlc/source/astconstant.cxx123
-rw-r--r--idlc/source/astdeclaration.cxx164
-rw-r--r--idlc/source/astdump.cxx420
-rw-r--r--idlc/source/astenum.cxx105
-rw-r--r--idlc/source/astexpression.cxx1327
-rw-r--r--idlc/source/astinterface.cxx399
-rw-r--r--idlc/source/astoperation.cxx115
-rw-r--r--idlc/source/astscope.cxx314
-rw-r--r--idlc/source/astservice.cxx54
-rw-r--r--idlc/source/aststack.cxx79
-rw-r--r--idlc/source/aststruct.cxx167
-rw-r--r--idlc/source/aststructinstance.cxx63
-rw-r--r--idlc/source/attributeexceptions.hxx38
-rw-r--r--idlc/source/errorhandler.cxx583
-rw-r--r--idlc/source/fehelper.cxx102
-rw-r--r--idlc/source/idlc.cxx400
-rw-r--r--idlc/source/idlccompile.cxx394
-rw-r--r--idlc/source/idlcmain.cxx164
-rw-r--r--idlc/source/idlcproduce.cxx242
-rw-r--r--idlc/source/options.cxx424
-rw-r--r--idlc/source/parser.y2737
-rw-r--r--idlc/source/scanner.l526
-rw-r--r--idlc/test/const.idl71
-rw-r--r--idlc/test/enum.idl45
-rw-r--r--idlc/test/exception.idl40
-rw-r--r--idlc/test/identifiers.idl43
-rw-r--r--idlc/test/interface.idl71
-rw-r--r--idlc/test/parser/attribute.tests232
-rw-r--r--idlc/test/parser/constant.tests294
-rw-r--r--idlc/test/parser/constructor.tests190
-rw-r--r--idlc/test/parser/conversion.tests79
-rw-r--r--idlc/test/parser/interfaceinheritance.tests279
-rw-r--r--idlc/test/parser/methodoverload.tests177
-rw-r--r--idlc/test/parser/oldstyle.tests28
-rw-r--r--idlc/test/parser/polystruct.tests251
-rw-r--r--idlc/test/parser/published.tests681
-rw-r--r--idlc/test/parser/struct.tests46
-rw-r--r--idlc/test/parser/typedef.tests63
-rw-r--r--idlc/test/service.idl64
-rw-r--r--idlc/test/singleton.idl61
-rw-r--r--idlc/test/struct.idl121
-rw-r--r--idlc/test/typelookup.idl80
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: */