summaryrefslogtreecommitdiffstats
path: root/codemaker/source
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 /codemaker/source
parentInitial commit. (diff)
downloadlibreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.tar.xz
libreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.zip
Adding upstream version 4:7.4.7.upstream/4%7.4.7upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'codemaker/source')
-rw-r--r--codemaker/source/codemaker/codemaker.cxx46
-rw-r--r--codemaker/source/codemaker/exceptiontree.cxx93
-rw-r--r--codemaker/source/codemaker/global.cxx367
-rw-r--r--codemaker/source/codemaker/options.cxx41
-rw-r--r--codemaker/source/codemaker/typemanager.cxx258
-rw-r--r--codemaker/source/codemaker/unotype.cxx70
-rw-r--r--codemaker/source/commoncpp/commoncpp.cxx299
-rw-r--r--codemaker/source/commonjava/commonjava.cxx135
-rw-r--r--codemaker/source/cppumaker/cppumaker.cxx110
-rw-r--r--codemaker/source/cppumaker/cppuoptions.cxx325
-rw-r--r--codemaker/source/cppumaker/cppuoptions.hxx41
-rw-r--r--codemaker/source/cppumaker/cpputype.cxx4105
-rw-r--r--codemaker/source/cppumaker/cpputype.hxx35
-rw-r--r--codemaker/source/cppumaker/dependencies.cxx296
-rw-r--r--codemaker/source/cppumaker/dependencies.hxx126
-rw-r--r--codemaker/source/cppumaker/dumputils.cxx79
-rw-r--r--codemaker/source/cppumaker/dumputils.hxx40
-rw-r--r--codemaker/source/cppumaker/includes.cxx273
-rw-r--r--codemaker/source/cppumaker/includes.hxx100
-rw-r--r--codemaker/source/javamaker/classfile.cxx828
-rw-r--r--codemaker/source/javamaker/classfile.hxx239
-rw-r--r--codemaker/source/javamaker/javamaker.cxx98
-rw-r--r--codemaker/source/javamaker/javaoptions.cxx249
-rw-r--r--codemaker/source/javamaker/javaoptions.hxx41
-rw-r--r--codemaker/source/javamaker/javatype.cxx2539
-rw-r--r--codemaker/source/javamaker/javatype.hxx35
26 files changed, 10868 insertions, 0 deletions
diff --git a/codemaker/source/codemaker/codemaker.cxx b/codemaker/source/codemaker/codemaker.cxx
new file mode 100644
index 000000000..cb797533e
--- /dev/null
+++ b/codemaker/source/codemaker/codemaker.cxx
@@ -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 .
+ */
+
+#include <sal/config.h>
+
+#include <codemaker/codemaker.hxx>
+#include <codemaker/global.hxx>
+#include <rtl/string.hxx>
+#include <rtl/textcvt.h>
+#include <rtl/textenc.h>
+#include <rtl/ustring.hxx>
+
+namespace codemaker {
+
+OString convertString(OUString const & string) {
+ OString s;
+ if (!string.convertToString(
+ &s, RTL_TEXTENCODING_UTF8,
+ (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR
+ | RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR)))
+ {
+ throw CannotDumpException(
+ "Failure converting string from UTF-16 to UTF-8");
+ }
+ return s;
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/codemaker/source/codemaker/exceptiontree.cxx b/codemaker/source/codemaker/exceptiontree.cxx
new file mode 100644
index 000000000..148f017b6
--- /dev/null
+++ b/codemaker/source/codemaker/exceptiontree.cxx
@@ -0,0 +1,93 @@
+/* -*- 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 <codemaker/exceptiontree.hxx>
+#include <codemaker/typemanager.hxx>
+
+#include <rtl/ref.hxx>
+#include <rtl/string.hxx>
+#include <rtl/textenc.h>
+#include <rtl/ustring.hxx>
+#include <unoidl/unoidl.hxx>
+
+#include <memory>
+#include <vector>
+
+using codemaker::ExceptionTree;
+using codemaker::ExceptionTreeNode;
+
+ExceptionTreeNode * ExceptionTreeNode::add(OString const & theName) {
+ std::unique_ptr< ExceptionTreeNode > node(new ExceptionTreeNode(theName));
+ children.push_back(std::move(node));
+ return children.back().get();
+}
+
+void ExceptionTreeNode::clearChildren() {
+ children.clear();
+}
+
+void ExceptionTree::add(
+ OString const & name, rtl::Reference< TypeManager > const & manager)
+{
+ std::vector< OString > list;
+ bool bRuntimeException = false;
+ for (OString n(name); n != "com.sun.star.uno.Exception";) {
+ if (n == "com.sun.star.uno.RuntimeException") {
+ bRuntimeException = true;
+ break;
+ }
+ list.push_back(n);
+ rtl::Reference< unoidl::Entity > ent;
+ codemaker::UnoType::Sort s = manager->getSort(b2u(n), &ent);
+ (void) s; // WaE: unused variable
+ assert(s == codemaker::UnoType::Sort::Exception);
+ n = u2b(
+ static_cast< unoidl::ExceptionTypeEntity * >(ent.get())->
+ getDirectBase());
+ assert(!n.isEmpty());
+ }
+ if (bRuntimeException)
+ return;
+
+ ExceptionTreeNode * node = &m_root;
+ for (std::vector< OString >::reverse_iterator i(list.rbegin());
+ !node->present; ++i)
+ {
+ if (i == list.rend()) {
+ node->setPresent();
+ break;
+ }
+ for (ExceptionTreeNode::Children::iterator j(
+ node->children.begin());;
+ ++j)
+ {
+ if (j == node->children.end()) {
+ node = node->add(*i);
+ break;
+ }
+ if ((*j)->name == *i) {
+ node = j->get();
+ break;
+ }
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/codemaker/source/codemaker/global.cxx b/codemaker/source/codemaker/global.cxx
new file mode 100644
index 000000000..1310a0b05
--- /dev/null
+++ b/codemaker/source/codemaker/global.cxx
@@ -0,0 +1,367 @@
+/* -*- 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/process.h>
+#include <rtl/strbuf.hxx>
+#include <rtl/ustring.hxx>
+#include <osl/thread.h>
+#include <osl/file.hxx>
+#include <o3tl/string_view.hxx>
+
+#include <string.h>
+#include <string_view>
+#include <errno.h>
+
+#if defined(_WIN32)
+# include <io.h>
+# include <direct.h>
+#endif
+
+#ifdef UNX
+# include <sys/stat.h>
+# include <unistd.h>
+#endif
+
+#include <codemaker/global.hxx>
+
+#ifdef SAL_UNX
+#define SEPARATOR '/'
+#else
+#define SEPARATOR '\\'
+#endif
+
+using namespace ::osl;
+
+
+OString getTempDir(const OString& sFileName)
+{
+ sal_Int32 index = 0;
+#ifdef SAL_UNX
+ if ((index=sFileName.lastIndexOf('/')) > 0)
+ return sFileName.copy(0, index);
+#else
+ if ((index=sFileName.lastIndexOf('\\')) > 0)
+ return sFileName.copy(0, index);
+#endif
+ return ".";
+}
+
+OString createFileNameFromType( const OString& destination,
+ const OString& typeName,
+ const OString& postfix )
+{
+ OString type(typeName.replace('.', '/'));
+
+ sal_Int32 length = destination.getLength();
+
+ bool bWithPoint = false;
+ if (length == 0)
+ {
+ length++;
+ bWithPoint = true;
+ }
+
+ length += type.getLength() + postfix.getLength();
+
+ bool bWithSeparator = false;
+ if (!(destination.endsWith("\\") || destination.endsWith("/"))
+ && !(type.startsWith("\\") || type.startsWith("/")))
+ {
+ length++;
+ bWithSeparator = true;
+ }
+
+ OStringBuffer fileNameBuf(length);
+
+ if (bWithPoint)
+ fileNameBuf.append('.');
+ else
+ fileNameBuf.append(destination);
+
+ if (bWithSeparator)
+ fileNameBuf.append("/");
+
+ fileNameBuf.append(type);
+ fileNameBuf.append(postfix);
+
+ OString fileName(fileNameBuf.makeStringAndClear());
+
+ char token;
+#ifdef SAL_UNX
+ fileName = fileName.replace('\\', '/');
+ token = '/';
+#else
+ fileName = fileName.replace('/', '\\');
+ token = '\\';
+#endif
+
+ OStringBuffer buffer(length);
+
+ sal_Int32 nIndex = 0;
+ do
+ {
+ buffer.append(o3tl::getToken(fileName, 0, token, nIndex));
+ if( nIndex == -1 )
+ break;
+
+ if (buffer.isEmpty() || std::string_view(".") == buffer)
+ {
+ buffer.append(token);
+ continue;
+ }
+
+#if defined(SAL_UNX)
+ if (mkdir(buffer.getStr(), 0777) == -1)
+#else
+ if (mkdir(buffer.getStr()) == -1)
+#endif
+ {
+ if ( errno == ENOENT )
+ return OString();
+ }
+
+ buffer.append(token);
+ } while(true);
+
+ OUString uSysFileName;
+ OSL_VERIFY( FileBase::getSystemPathFromFileURL(
+ convertToFileUrl(fileName), uSysFileName) == FileBase::E_None );
+ return OUStringToOString(uSysFileName, osl_getThreadTextEncoding());
+}
+
+bool fileExists(const OString& fileName)
+{
+ FILE *f= fopen(fileName.getStr(), "r");
+
+ if (f != nullptr)
+ {
+ fclose(f);
+ return true;
+ }
+
+ return false;
+}
+
+static bool checkFileContent(const OString& targetFileName, const OString& tmpFileName)
+{
+ FILE *target = fopen(targetFileName.getStr(), "r");
+ FILE *tmp = fopen(tmpFileName.getStr(), "r");
+ bool bFindChanges = false;
+
+ if (target != nullptr && tmp != nullptr)
+ {
+ char buffer1[1024+1];
+ char buffer2[1024+1];
+ sal_Int32 n1 = 0;
+ sal_Int32 n2 = 0;
+
+ while ( !bFindChanges && !feof(target) && !feof(tmp))
+ {
+ n1 = fread(buffer1, sizeof(char), 1024, target);
+ n2 = fread(buffer2, sizeof(char), 1024, tmp);
+
+ if ( n1 != n2 )
+ bFindChanges = true;
+ else
+ if ( memcmp(buffer1, buffer2, n2) != 0 )
+ bFindChanges = true;
+ }
+ }
+
+ if (target) fclose(target);
+ if (tmp) fclose(tmp);
+
+ return bFindChanges;
+}
+
+bool makeValidTypeFile(const OString& targetFileName, const OString& tmpFileName,
+ bool bFileCheck)
+{
+ if (bFileCheck) {
+ if (checkFileContent(targetFileName, tmpFileName)) {
+ if ( !unlink(targetFileName.getStr()) )
+ if ( !rename(tmpFileName.getStr(), targetFileName.getStr()) )
+ return true;
+ } else
+ return removeTypeFile(tmpFileName);
+ } else {
+ if (fileExists(targetFileName))
+ if (!removeTypeFile(targetFileName))
+ return false;
+
+ if ( rename(tmpFileName.getStr(), targetFileName.getStr()) ) {
+ if (errno == EEXIST)
+ return true;
+ } else
+ return true;
+ }
+ return false;
+}
+
+bool removeTypeFile(const OString& fileName)
+{
+ return unlink(fileName.getStr()) == 0;
+}
+
+OUString convertToFileUrl(const OString& fileName)
+{
+ if ( fileName.startsWith("file://") )
+ {
+ return OStringToOUString(fileName, osl_getThreadTextEncoding());
+ }
+
+ OUString uUrlFileName;
+ OUString uFileName(fileName.getStr(), fileName.getLength(), osl_getThreadTextEncoding());
+ if ( fileName.startsWith(".") || fileName.indexOf(SEPARATOR) < 0 )
+ {
+ OUString uWorkingDir;
+ if (osl_getProcessWorkingDir(&uWorkingDir.pData) != osl_Process_E_None)
+ {
+ OSL_ASSERT(false);
+ }
+ if (FileBase::getAbsoluteFileURL(uWorkingDir, uFileName, uUrlFileName)
+ != FileBase::E_None)
+ {
+ OSL_ASSERT(false);
+ }
+ } else
+ {
+ if (FileBase::getFileURLFromSystemPath(uFileName, uUrlFileName)
+ != FileBase::E_None)
+ {
+ OSL_ASSERT(false);
+ }
+ }
+
+ return uUrlFileName;
+}
+
+
+// FileStream
+
+FileStream::FileStream()
+ : m_file(nullptr)
+{
+}
+
+FileStream::~FileStream()
+{
+ if ( isValid() )
+ osl_closeFile(m_file);
+}
+
+bool FileStream::isValid() const
+{
+ return m_file != nullptr;
+}
+
+void FileStream::createTempFile(const OString& sPath)
+{
+ OString sTmp(".");
+ OUString sTmpPath;
+ OUString sTmpName;
+
+ if (!sPath.isEmpty())
+ sTmp = sPath;
+
+ sTmpPath = convertToFileUrl(sTmp);
+
+ if (osl_createTempFile(sTmpPath.pData, &m_file, &sTmpName.pData) == osl_File_E_None) {
+#ifdef SAL_UNX
+ sal_uInt64 const uAttr = osl_File_Attribute_OwnWrite |
+ osl_File_Attribute_OwnRead |
+ osl_File_Attribute_GrpWrite |
+ osl_File_Attribute_GrpRead |
+ osl_File_Attribute_OthRead;
+ if (osl_setFileAttributes(sTmpName.pData, uAttr) != osl_File_E_None) {
+ m_file = nullptr;
+ return;
+ }
+#endif
+ OUString sSysTmpName;
+ FileBase::getSystemPathFromFileURL(sTmpName, sSysTmpName);
+ m_name = OUStringToOString(sSysTmpName, osl_getThreadTextEncoding());
+ } else
+ m_file = nullptr;
+}
+
+void FileStream::close()
+{
+ if ( isValid() )
+ {
+ osl_closeFile(m_file);
+ m_file = nullptr;
+ m_name.clear();
+ }
+}
+
+bool FileStream::write(void const * buffer, sal_uInt64 size) {
+ while (size > 0) {
+ sal_uInt64 written;
+ if (osl_writeFile(m_file, buffer, size, &written) != osl_File_E_None) {
+ return false;
+ }
+ OSL_ASSERT(written <= size);
+ size -= written;
+ buffer = static_cast< char const * >(buffer) + written;
+ }
+ return true;
+}
+
+FileStream &operator<<(FileStream& o, sal_uInt32 i) {
+ sal_uInt64 writtenBytes;
+ OString s = OString::number(static_cast<sal_Int32>(i));
+ osl_writeFile(o.m_file, s.getStr(), s.getLength() * sizeof(char), &writtenBytes);
+ return o;
+}
+FileStream &operator<<(FileStream& o, char const * s) {
+ sal_uInt64 writtenBytes;
+ osl_writeFile(o.m_file, s, strlen(s), &writtenBytes);
+ return o;
+}
+FileStream &operator<<(FileStream& o, OString const * s) {
+ sal_uInt64 writtenBytes;
+ osl_writeFile(o.m_file, s->getStr(), s->getLength() * sizeof(char), &writtenBytes);
+ return o;
+}
+FileStream &operator<<(FileStream& o, const OString& s) {
+ sal_uInt64 writtenBytes;
+ osl_writeFile(o.m_file, s.getStr(), s.getLength() * sizeof(char), &writtenBytes);
+ return o;
+
+}
+FileStream &operator<<(FileStream& o, OStringBuffer const * s) {
+ sal_uInt64 writtenBytes;
+ osl_writeFile(o.m_file, s->getStr(), s->getLength() * sizeof(char), &writtenBytes);
+ return o;
+}
+FileStream &operator<<(FileStream& o, const OStringBuffer& s) {
+ sal_uInt64 writtenBytes;
+ osl_writeFile(
+ o.m_file, s.getStr(), s.getLength() * sizeof(char), &writtenBytes);
+ return o;
+}
+
+FileStream & operator <<(FileStream & out, std::u16string_view s) {
+ return out << OUStringToOString(s, RTL_TEXTENCODING_UTF8);
+}
+
+CannotDumpException::~CannotDumpException() noexcept {}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/codemaker/source/codemaker/options.cxx b/codemaker/source/codemaker/options.cxx
new file mode 100644
index 000000000..2d85b35a9
--- /dev/null
+++ b/codemaker/source/codemaker/options.cxx
@@ -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 .
+ */
+
+#include <codemaker/options.hxx>
+
+Options::Options() {}
+
+Options::~Options() {}
+
+bool Options::isValid(const OString& option) const
+{
+ return m_options.find(option) != m_options.end();
+}
+
+const OString& Options::getOption(const OString& option) const
+{
+ OptionMap::const_iterator i(m_options.find(option));
+ if (i == m_options.end())
+ {
+ throw IllegalArgument("Option is not valid or currently not set.");
+ }
+ return i->second;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/codemaker/source/codemaker/typemanager.cxx b/codemaker/source/codemaker/typemanager.cxx
new file mode 100644
index 000000000..194840ca9
--- /dev/null
+++ b/codemaker/source/codemaker/typemanager.cxx
@@ -0,0 +1,258 @@
+/* -*- 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 <cstdlib>
+#include <cstring>
+#include <vector>
+
+#include <codemaker/global.hxx>
+#include <codemaker/typemanager.hxx>
+#include <rtl/ref.hxx>
+#include <rtl/ustring.hxx>
+#include <unoidl/unoidl.hxx>
+
+TypeManager::TypeManager(): manager_(new unoidl::Manager) {}
+
+TypeManager::~TypeManager() {}
+
+void TypeManager::loadProvider(OUString const & uri, bool primary) {
+ rtl::Reference< unoidl::Provider > prov(manager_->addProvider(uri));
+ if (primary) {
+ primaryProviders_.push_back(prov);
+ }
+}
+
+bool TypeManager::foundAtPrimaryProvider(OUString const & name) const {
+ if (name.isEmpty()) {
+ return !primaryProviders_.empty();
+ }
+ for (const rtl::Reference< unoidl::Provider >& xProvider : primaryProviders_)
+ {
+ if (xProvider->findEntity(name).is()) {
+ return true;
+ }
+ }
+ if (!manager_->findEntity(name).is()) {
+ throw CannotDumpException("Unknown entity '" + name + "'");
+ }
+ return false;
+}
+
+codemaker::UnoType::Sort TypeManager::getSort(
+ OUString const & name, rtl::Reference< unoidl::Entity > * entity,
+ rtl::Reference< unoidl::MapCursor > * cursor) const
+{
+ if (name.isEmpty()) {
+ if (cursor != nullptr) {
+ *cursor = manager_->createCursor("");
+ }
+ return codemaker::UnoType::Sort::Module;
+ }
+ if (name == "void") {
+ return codemaker::UnoType::Sort::Void;
+ }
+ if (name == "boolean") {
+ return codemaker::UnoType::Sort::Boolean;
+ }
+ if (name == "byte") {
+ return codemaker::UnoType::Sort::Byte;
+ }
+ if (name == "short") {
+ return codemaker::UnoType::Sort::Short;
+ }
+ if (name == "unsigned short") {
+ return codemaker::UnoType::Sort::UnsignedShort;
+ }
+ if (name == "long") {
+ return codemaker::UnoType::Sort::Long;
+ }
+ if (name == "unsigned long") {
+ return codemaker::UnoType::Sort::UnsignedLong;
+ }
+ if (name == "hyper") {
+ return codemaker::UnoType::Sort::Hyper;
+ }
+ if (name == "unsigned hyper") {
+ return codemaker::UnoType::Sort::UnsignedHyper;
+ }
+ if (name == "float") {
+ return codemaker::UnoType::Sort::Float;
+ }
+ if (name == "double") {
+ return codemaker::UnoType::Sort::Double;
+ }
+ if (name == "char") {
+ return codemaker::UnoType::Sort::Char;
+ }
+ if (name == "string") {
+ return codemaker::UnoType::Sort::String;
+ }
+ if (name == "type") {
+ return codemaker::UnoType::Sort::Type;
+ }
+ if (name == "any") {
+ return codemaker::UnoType::Sort::Any;
+ }
+ if (name.startsWith("[")) {
+ return codemaker::UnoType::Sort::Sequence;
+ }
+ if (name.indexOf('<') != -1) {
+ return codemaker::UnoType::Sort::InstantiatedPolymorphicStruct;
+ }
+ rtl::Reference< unoidl::Entity > ent(manager_->findEntity(name));
+ if (!ent.is()) {
+ throw CannotDumpException("Unknown entity '" + name + "'");
+ }
+ if (entity != nullptr) {
+ *entity = ent;
+ }
+ switch (ent->getSort()) {
+ case unoidl::Entity::SORT_MODULE:
+ if (cursor != nullptr) {
+ *cursor = manager_->createCursor(name);
+ }
+ return codemaker::UnoType::Sort::Module;
+ case unoidl::Entity::SORT_ENUM_TYPE:
+ return codemaker::UnoType::Sort::Enum;
+ case unoidl::Entity::SORT_PLAIN_STRUCT_TYPE:
+ return codemaker::UnoType::Sort::PlainStruct;
+ case unoidl::Entity::SORT_POLYMORPHIC_STRUCT_TYPE_TEMPLATE:
+ return codemaker::UnoType::Sort::PolymorphicStructTemplate;
+ case unoidl::Entity::SORT_EXCEPTION_TYPE:
+ return codemaker::UnoType::Sort::Exception;
+ case unoidl::Entity::SORT_INTERFACE_TYPE:
+ return codemaker::UnoType::Sort::Interface;
+ case unoidl::Entity::SORT_TYPEDEF:
+ return codemaker::UnoType::Sort::Typedef;
+ case unoidl::Entity::SORT_CONSTANT_GROUP:
+ return codemaker::UnoType::Sort::ConstantGroup;
+ case unoidl::Entity::SORT_SINGLE_INTERFACE_BASED_SERVICE:
+ return codemaker::UnoType::Sort::SingleInterfaceBasedService;
+ case unoidl::Entity::SORT_ACCUMULATION_BASED_SERVICE:
+ return codemaker::UnoType::Sort::AccumulationBasedService;
+ case unoidl::Entity::SORT_INTERFACE_BASED_SINGLETON:
+ return codemaker::UnoType::Sort::InterfaceBasedSingleton;
+ case unoidl::Entity::SORT_SERVICE_BASED_SINGLETON:
+ return codemaker::UnoType::Sort::ServiceBasedSingleton;
+ default:
+ for (;;) { std::abort(); } // this cannot happen
+ }
+}
+
+codemaker::UnoType::Sort TypeManager::decompose(
+ std::u16string_view name, bool resolveTypedefs, OUString * nucleus,
+ sal_Int32 * rank, std::vector< OUString > * arguments,
+ rtl::Reference< unoidl::Entity > * entity) const
+{
+ sal_Int32 k;
+ std::vector< OString > args;
+ OUString n = b2u(codemaker::UnoType::decompose(u2b(name), &k, &args));
+ for (;;) {
+ rtl::Reference< unoidl::Entity > ent;
+ codemaker::UnoType::Sort s = getSort(n, &ent);
+ if (args.empty()
+ != (s != codemaker::UnoType::Sort::PolymorphicStructTemplate))
+ {
+ throw CannotDumpException(
+ "template arguments mismatch for \"" + n
+ + "\" resolved from \"" + name + "\"");
+ }
+ switch (s) {
+ case codemaker::UnoType::Sort::Typedef:
+ if (resolveTypedefs) {
+ n = dynamic_cast<unoidl::TypedefEntity&>(*ent).getType();
+ while (n.startsWith("[]")) {
+ ++k; //TODO: overflow
+ n = n.copy(std::strlen("[]"));
+ }
+ break;
+ }
+ [[fallthrough]];
+ case codemaker::UnoType::Sort::Void:
+ case codemaker::UnoType::Sort::Boolean:
+ case codemaker::UnoType::Sort::Byte:
+ case codemaker::UnoType::Sort::Short:
+ case codemaker::UnoType::Sort::UnsignedShort:
+ case codemaker::UnoType::Sort::Long:
+ case codemaker::UnoType::Sort::UnsignedLong:
+ case codemaker::UnoType::Sort::Hyper:
+ case codemaker::UnoType::Sort::UnsignedHyper:
+ case codemaker::UnoType::Sort::Float:
+ case codemaker::UnoType::Sort::Double:
+ case codemaker::UnoType::Sort::Char:
+ case codemaker::UnoType::Sort::String:
+ case codemaker::UnoType::Sort::Type:
+ case codemaker::UnoType::Sort::Any:
+ case codemaker::UnoType::Sort::Enum:
+ case codemaker::UnoType::Sort::PlainStruct:
+ case codemaker::UnoType::Sort::Exception:
+ case codemaker::UnoType::Sort::Interface:
+ if (nucleus != nullptr) {
+ *nucleus = n;
+ }
+ if (rank != nullptr) {
+ *rank = k;
+ }
+ if (arguments != nullptr) {
+ arguments->clear();
+ }
+ if (entity != nullptr) {
+ *entity = ent;
+ }
+ return s;
+ case codemaker::UnoType::Sort::PolymorphicStructTemplate:
+ if (args.size()
+ != (dynamic_cast<unoidl::PolymorphicStructTypeTemplateEntity&>(*ent).
+ getTypeParameters().size()))
+ {
+ throw CannotDumpException(
+ "bad number of template arguments for \"" + n
+ + "\" resolved from \"" + name + "\"");
+ }
+ if (nucleus != nullptr) {
+ *nucleus = n;
+ }
+ if (rank != nullptr) {
+ *rank = k;
+ }
+ if (arguments != nullptr) {
+ arguments->clear();
+ for (const OString& rArg : args)
+ {
+ arguments->push_back(b2u(rArg));
+ }
+ }
+ if (entity != nullptr) {
+ *entity = ent;
+ }
+ return
+ codemaker::UnoType::Sort::InstantiatedPolymorphicStruct;
+ case codemaker::UnoType::Sort::Sequence:
+ for (;;) std::abort(); // this cannot happen
+ default:
+ throw CannotDumpException(
+ "unexpected \"" + n + "\" resolved from \"" + name
+ + "\"in call to TypeManager::decompose");
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/codemaker/source/codemaker/unotype.cxx b/codemaker/source/codemaker/unotype.cxx
new file mode 100644
index 000000000..8c25ac8ae
--- /dev/null
+++ b/codemaker/source/codemaker/unotype.cxx
@@ -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 .
+ */
+
+
+#include <codemaker/unotype.hxx>
+
+#include <osl/diagnose.h>
+#include <rtl/string.hxx>
+#include <sal/types.h>
+
+
+OString codemaker::UnoType::decompose(
+ OString const & type, sal_Int32 * rank,
+ std::vector< OString > * arguments)
+{
+ sal_Int32 len = type.getLength();
+ sal_Int32 i = 0;
+ while (len - i > 1 && type[i + 1] == ']') {
+ i += 2;
+ }
+ if (rank != nullptr) {
+ *rank = i / 2;
+ }
+ sal_Int32 j = arguments == nullptr ? -1 : type.indexOf('<', i);
+ if (j < 0) {
+ return type.copy(i);
+ }
+ sal_Int32 k = j;
+ do {
+ ++k; // skip '<' or ','
+ sal_Int32 l = k;
+ for (sal_Int32 level = 0; l != len; ++l) {
+ char c = type[l];
+ if (c == ',') {
+ if (level == 0) {
+ break;
+ }
+ } else if (c == '<') {
+ ++level;
+ } else if (c == '>') {
+ if (level == 0) {
+ break;
+ }
+ --level;
+ }
+ }
+ arguments->push_back(type.copy(k, l - k));
+ k = l;
+ } while (k != len && type[k] != '>');
+ OSL_ASSERT(k == len - 1 && type[k] == '>');
+ return type.copy(i, j - i);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/codemaker/source/commoncpp/commoncpp.cxx b/codemaker/source/commoncpp/commoncpp.cxx
new file mode 100644
index 000000000..117afaca2
--- /dev/null
+++ b/codemaker/source/commoncpp/commoncpp.cxx
@@ -0,0 +1,299 @@
+/* -*- 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 <codemaker/commoncpp.hxx>
+
+#include <codemaker/options.hxx>
+#include <codemaker/typemanager.hxx>
+#include <codemaker/unotype.hxx>
+
+#include <rtl/strbuf.hxx>
+#include <rtl/string.hxx>
+#include <rtl/ustring.hxx>
+#include <sal/types.h>
+#include <o3tl/string_view.hxx>
+
+#include <vector>
+
+namespace codemaker::cpp {
+
+OString scopedCppName(OString const & type, bool ns_alias)
+{
+ char c('/');
+ sal_Int32 nPos = type.lastIndexOf( c );
+ if (nPos == -1) {
+ nPos = type.lastIndexOf( '.' );
+ if (nPos == -1)
+ return type;
+
+ c = '.';
+ }
+
+ OStringBuffer tmpBuf(type.getLength()*2);
+ nPos = 0;
+ do
+ {
+ tmpBuf.append(OString::Concat("::") + o3tl::getToken(type, 0, c, nPos));
+ } while( nPos != -1 );
+
+ OString s(tmpBuf.makeStringAndClear());
+ if (ns_alias && s.startsWith("::com::sun::star::", &s))
+ {
+ s = "::css::" + s; // nicer shorthand
+ }
+
+ return s;
+}
+
+OString translateUnoToCppType(
+ codemaker::UnoType::Sort sort, std::u16string_view nucleus)
+{
+ OStringBuffer buf;
+ if (sort <= codemaker::UnoType::Sort::Any) {
+ static char const * const cppTypes[static_cast<int>(codemaker::UnoType::Sort::Any) + 1] = {
+ "void", "::sal_Bool", "::sal_Int8", "::sal_Int16", "::sal_uInt16",
+ "::sal_Int32", "::sal_uInt32", "::sal_Int64", "::sal_uInt64",
+ "float", "double", "::sal_Unicode", "rtl::OUString",
+ "::css::uno::Type", "::css::uno::Any" };
+ buf.append(cppTypes[static_cast<int>(sort)]);
+ } else {
+ if (sort == codemaker::UnoType::Sort::Interface
+ && nucleus == u"com.sun.star.uno.XInterface")
+ {
+ buf.append("::css::uno::XInterface");
+ } else {
+ //TODO: check that nucleus is a valid (UTF-8) identifier
+ buf.append(u2b(nucleus));
+ }
+ }
+ return buf.makeStringAndClear();
+}
+
+OString translateUnoToCppIdentifier(
+ OString const & unoIdentifier, std::string_view prefix,
+ IdentifierTranslationMode transmode, OString const * forbidden)
+{
+ if (// Keywords:
+ unoIdentifier == "asm"
+ || unoIdentifier == "auto"
+ || unoIdentifier == "bool"
+ || unoIdentifier == "break"
+ || unoIdentifier == "case"
+ || unoIdentifier == "catch"
+ || unoIdentifier == "char"
+ || unoIdentifier == "class"
+ || unoIdentifier == "const"
+ /* unoIdentifier == "const_cast" */
+ || unoIdentifier == "continue"
+ || unoIdentifier == "default"
+ || unoIdentifier == "delete"
+ || unoIdentifier == "do"
+ || unoIdentifier == "double"
+ /* unoIdentifier == "dynamic_cast" */
+ || unoIdentifier == "else"
+ || unoIdentifier == "enum"
+ || unoIdentifier == "explicit"
+ || unoIdentifier == "export"
+ || unoIdentifier == "extern"
+ || unoIdentifier == "false"
+ || unoIdentifier == "float"
+ || unoIdentifier == "for"
+ || unoIdentifier == "friend"
+ || unoIdentifier == "goto"
+ || unoIdentifier == "if"
+ || unoIdentifier == "inline"
+ || unoIdentifier == "int"
+ || unoIdentifier == "long"
+ || unoIdentifier == "mutable"
+ || unoIdentifier == "namespace"
+ || unoIdentifier == "new"
+ || unoIdentifier == "operator"
+ || unoIdentifier == "private"
+ || unoIdentifier == "protected"
+ || unoIdentifier == "public"
+ || unoIdentifier == "register"
+ /* unoIdentifier == "reinterpret_cast" */
+ || unoIdentifier == "return"
+ || unoIdentifier == "short"
+ || unoIdentifier == "signed"
+ || unoIdentifier == "sizeof"
+ || unoIdentifier == "static"
+ /* unoIdentifier == "static_cast" */
+ || unoIdentifier == "struct"
+ || unoIdentifier == "switch"
+ || unoIdentifier == "template"
+ || unoIdentifier == "this"
+ || unoIdentifier == "throw"
+ || unoIdentifier == "true"
+ || unoIdentifier == "try"
+ || unoIdentifier == "typedef"
+ || unoIdentifier == "typeid"
+ || unoIdentifier == "typename"
+ || unoIdentifier == "union"
+ || unoIdentifier == "unsigned"
+ || unoIdentifier == "using"
+ || unoIdentifier == "virtual"
+ || unoIdentifier == "void"
+ || unoIdentifier == "volatile"
+ /* unoIdentifier == "wchar_t" */
+ || unoIdentifier == "while"
+ // Alternative representations:
+ || unoIdentifier == "and"
+ /* unoIdentifier == "and_eq" */
+ || unoIdentifier == "bitand"
+ || unoIdentifier == "bitor"
+ || unoIdentifier == "compl"
+ || unoIdentifier == "not"
+ /* unoIdentifier == "not_eq" */
+ || unoIdentifier == "or"
+ /* unoIdentifier == "or_eq" */
+ || unoIdentifier == "xor"
+ /* unoIdentifier == "xor_eq" */
+ // Standard macros:
+ || (unoIdentifier == "BUFSIZ"
+ || unoIdentifier == "CLOCKS_PER_SEC"
+ || unoIdentifier == "EDOM"
+ || unoIdentifier == "EOF"
+ || unoIdentifier == "ERANGE"
+ || unoIdentifier == "EXIT_FAILURE"
+ || unoIdentifier == "EXIT_SUCCESS"
+ || unoIdentifier == "FILENAME_MAX"
+ || unoIdentifier == "FOPEN_MAX"
+ || unoIdentifier == "HUGE_VAL"
+ || unoIdentifier == "LC_ALL"
+ || unoIdentifier == "LC_COLLATE"
+ || unoIdentifier == "LC_CTYPE"
+ || unoIdentifier == "LC_MONETARY"
+ || unoIdentifier == "LC_NUMERIC"
+ || unoIdentifier == "LC_TIME"
+ || unoIdentifier == "L_tmpnam"
+ || unoIdentifier == "MB_CUR_MAX"
+ || unoIdentifier == "NULL"
+ || unoIdentifier == "RAND_MAX"
+ || unoIdentifier == "SEEK_CUR"
+ || unoIdentifier == "SEEK_END"
+ || unoIdentifier == "SEEK_SET"
+ || unoIdentifier == "SIGABRT"
+ || unoIdentifier == "SIGFPE"
+ || unoIdentifier == "SIGILL"
+ || unoIdentifier == "SIGINT"
+ || unoIdentifier == "SIGSEGV"
+ || unoIdentifier == "SIGTERM"
+ || unoIdentifier == "SIG_DFL"
+ || unoIdentifier == "SIG_ERR"
+ || unoIdentifier == "SIG_IGN"
+ || unoIdentifier == "TMP_MAX"
+ || unoIdentifier == "WCHAR_MAX"
+ || unoIdentifier == "WCHAR_MIN"
+ || unoIdentifier == "WEOF"
+ /* unoIdentifier == "_IOFBF" */
+ /* unoIdentifier == "_IOLBF" */
+ /* unoIdentifier == "_IONBF" */
+ || unoIdentifier == "assert"
+ || unoIdentifier == "errno"
+ || unoIdentifier == "offsetof"
+ || unoIdentifier == "setjmp"
+ || unoIdentifier == "stderr"
+ || unoIdentifier == "stdin"
+ || unoIdentifier == "stdout"
+ /* unoIdentifier == "va_arg" */
+ /* unoIdentifier == "va_end" */
+ /* unoIdentifier == "va_start" */
+ // Standard values:
+ || unoIdentifier == "CHAR_BIT"
+ || unoIdentifier == "CHAR_MAX"
+ || unoIdentifier == "CHAR_MIN"
+ || unoIdentifier == "DBL_DIG"
+ || unoIdentifier == "DBL_EPSILON"
+ || unoIdentifier == "DBL_MANT_DIG"
+ || unoIdentifier == "DBL_MAX"
+ || unoIdentifier == "DBL_MAX_10_EXP"
+ || unoIdentifier == "DBL_MAX_EXP"
+ || unoIdentifier == "DBL_MIN"
+ || unoIdentifier == "DBL_MIN_10_EXP"
+ || unoIdentifier == "DBL_MIN_EXP"
+ || unoIdentifier == "FLT_DIG"
+ || unoIdentifier == "FLT_EPSILON"
+ || unoIdentifier == "FLT_MANT_DIG"
+ || unoIdentifier == "FLT_MAX"
+ || unoIdentifier == "FLT_MAX_10_EXP"
+ || unoIdentifier == "FLT_MAX_EXP"
+ || unoIdentifier == "FLT_MIN"
+ || unoIdentifier == "FLT_MIN_10_EXP"
+ || unoIdentifier == "FLT_MIN_EXP"
+ || unoIdentifier == "FLT_RADIX"
+ || unoIdentifier == "FLT_ROUNDS"
+ || unoIdentifier == "INT_MAX"
+ || unoIdentifier == "INT_MIN"
+ || unoIdentifier == "LDBL_DIG"
+ || unoIdentifier == "LDBL_EPSILON"
+ || unoIdentifier == "LDBL_MANT_DIG"
+ || unoIdentifier == "LDBL_MAX"
+ || unoIdentifier == "LDBL_MAX_10_EXP"
+ || unoIdentifier == "LDBL_MAX_EXP"
+ || unoIdentifier == "LDBL_MIN"
+ || unoIdentifier == "LDBL_MIN_10_EXP"
+ || unoIdentifier == "LDBL_MIN_EXP"
+ || unoIdentifier == "LONG_MAX"
+ || unoIdentifier == "LONG_MIN"
+ || unoIdentifier == "MB_LEN_MAX"
+ || unoIdentifier == "SCHAR_MAX"
+ || unoIdentifier == "SCHAR_MIN"
+ || unoIdentifier == "SHRT_MAX"
+ || unoIdentifier == "SHRT_MIN"
+ || unoIdentifier == "UCHAR_MAX"
+ || unoIdentifier == "UINT_MAX"
+ || unoIdentifier == "ULONG_MAX"
+ || unoIdentifier == "USHRT_MAX")
+ || (transmode == IdentifierTranslationMode::Global
+ && (// Standard types:
+ /* unoIdentifier == "clock_t" */
+ /* unoIdentifier == "div_t" */
+ unoIdentifier == "FILE"
+ /* unoIdentifier == "fpos_t" */
+ /* unoIdentifier == "jmp_buf" */
+ || unoIdentifier == "lconv"
+ /* unoIdentifier == "ldiv_t" */
+ /* unoIdentifier == "mbstate_t" */
+ /* unoIdentifier == "ptrdiff_t" */
+ /* unoIdentifier == "sig_atomic_t" */
+ /* unoIdentifier == "size_t" */
+ /* unoIdentifier == "time_t" */
+ || unoIdentifier == "tm"
+ /* unoIdentifier == "va_list" */
+ /* unoIdentifier == "wctrans_t" */
+ /* unoIdentifier == "wctype_t" */
+ /* unoIdentifier == "wint_t" */
+ // Standard namespaces:
+ || unoIdentifier == "std"))
+ // Others:
+ || unoIdentifier == "NDEBUG"
+ || (forbidden != nullptr && unoIdentifier == *forbidden) )
+ {
+ return OString::Concat(prefix) + "_" + unoIdentifier;
+ } else {
+ return unoIdentifier;
+ }
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/codemaker/source/commonjava/commonjava.cxx b/codemaker/source/commonjava/commonjava.cxx
new file mode 100644
index 000000000..6782789ae
--- /dev/null
+++ b/codemaker/source/commonjava/commonjava.cxx
@@ -0,0 +1,135 @@
+/* -*- 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 <codemaker/commonjava.hxx>
+
+#include <codemaker/options.hxx>
+#include <codemaker/typemanager.hxx>
+#include <codemaker/unotype.hxx>
+
+#include <rtl/strbuf.h>
+#include <rtl/string.h>
+#include <rtl/string.hxx>
+#include <rtl/ustring.hxx>
+#include <sal/types.h>
+
+#include <vector>
+
+namespace codemaker::java {
+
+OString translateUnoToJavaType(
+ codemaker::UnoType::Sort sort, std::string_view nucleus, bool referenceType)
+{
+ OStringBuffer buf(128);
+ if (sort <= codemaker::UnoType::Sort::Any) {
+ OString const javaTypes[static_cast<int>(codemaker::UnoType::Sort::Any) + 1][2] = {
+ { "void", "java/lang/Void" },
+ { "boolean", "java/lang/Boolean" },
+ { "byte", "java/lang/Byte" },
+ { "short", "java/lang/Short" },
+ { "short", "java/lang/Short" },
+ { "int", "java/lang/Integer" },
+ { "int", "java/lang/Integer" },
+ { "long", "java/lang/Long" },
+ { "long", "java/lang/Long" },
+ { "float", "java/lang/Float" },
+ { "double", "java/lang/Double" },
+ { "char", "java/lang/Character" },
+ { "java/lang/String", "java/lang/String" },
+ { "com/sun/star/uno/Type", "com/sun/star/uno/Type" },
+ { "java/lang/Object", "java/lang/Object" } };
+ buf.append(javaTypes[static_cast<int>(sort)][referenceType]);
+ } else {
+ if (nucleus == "com/sun/star/uno/XInterface") {
+ buf.append("java/lang/Object");
+ } else {
+ //TODO: check that nucleus is a valid (Java-modified UTF-8)
+ // identifier
+ buf.append(nucleus);
+ }
+ }
+ return buf.makeStringAndClear();
+}
+
+OString translateUnoToJavaIdentifier(
+ OString const & identifier, std::string_view prefix)
+{
+ if (identifier == "abstract"
+ || identifier == "assert" // since Java 1.4
+ || identifier == "boolean"
+ || identifier == "break"
+ || identifier == "byte"
+ || identifier == "case"
+ || identifier == "catch"
+ || identifier == "char"
+ || identifier == "class"
+ || identifier == "const"
+ || identifier == "continue"
+ || identifier == "default"
+ || identifier == "do"
+ || identifier == "double"
+ || identifier == "else"
+ || identifier == "enum" // probable addition in Java 1.5
+ || identifier == "extends"
+ || identifier == "final"
+ || identifier == "finally"
+ || identifier == "float"
+ || identifier == "for"
+ || identifier == "goto"
+ || identifier == "if"
+ || identifier == "implements"
+ || identifier == "import"
+ || identifier == "instanceof"
+ || identifier == "int"
+ || identifier == "interface"
+ || identifier == "long"
+ || identifier == "native"
+ || identifier == "new"
+ || identifier == "package"
+ || identifier == "private"
+ || identifier == "protected"
+ || identifier == "public"
+ || identifier == "return"
+ || identifier == "short"
+ || identifier == "static"
+ || identifier == "strictfp"
+ || identifier == "super"
+ || identifier == "switch"
+ || identifier == "synchronized"
+ || identifier == "this"
+ || identifier == "throw"
+ || identifier == "throws"
+ || identifier == "transient"
+ || identifier == "try"
+ || identifier == "void"
+ || identifier == "volatile"
+ || identifier == "while")
+ {
+ return OString::Concat(prefix) + "_" + identifier;
+ } else {
+ return identifier;
+ }
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/codemaker/source/cppumaker/cppumaker.cxx b/codemaker/source/cppumaker/cppumaker.cxx
new file mode 100644
index 000000000..b2556655b
--- /dev/null
+++ b/codemaker/source/cppumaker/cppumaker.cxx
@@ -0,0 +1,110 @@
+/* -*- 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 <cstdlib>
+#include <cstring>
+#include <iostream>
+#include <vector>
+
+#include <codemaker/generatedtypeset.hxx>
+#include <codemaker/typemanager.hxx>
+#include <rtl/ref.hxx>
+#include <rtl/string.hxx>
+#include <rtl/ustring.hxx>
+#include <sal/main.h>
+#include <sal/types.h>
+#include <unoidl/unoidl.hxx>
+#include <o3tl/string_view.hxx>
+
+#include "cppuoptions.hxx"
+#include "cpputype.hxx"
+
+// coverity[tainted_data] - this is a build time tool
+SAL_IMPLEMENT_MAIN_WITH_ARGS(argc, argv) {
+ CppuOptions options;
+ try {
+ if (!options.initOptions(argc, argv)) {
+ return EXIT_FAILURE;
+ }
+
+ rtl::Reference typeMgr(new TypeManager);
+ for (const OString& f :options.getExtraInputFiles())
+ {
+ typeMgr->loadProvider(convertToFileUrl(f), false);
+ }
+ for (const OString& f : options.getInputFiles())
+ {
+ typeMgr->loadProvider(convertToFileUrl(f), true);
+ }
+ codemaker::GeneratedTypeSet generated;
+ if (options.isValid("-T")) {
+ OUString names(b2u(options.getOption("-T")));
+ for (sal_Int32 i = 0; i != -1;) {
+ std::u16string_view name(o3tl::getToken(names, 0, ';', i));
+ if (!name.empty()) {
+ produce(
+ OUString(name == u"*"
+ ? u""
+ : o3tl::ends_with(name, u".*")
+ ? name.substr(0, name.size() - std::strlen(".*"))
+ : name),
+ typeMgr, generated, options);
+ }
+ }
+ } else {
+ produce("", typeMgr, generated, options);
+ }
+ if (!options.isValid("-nD")) {
+ // C++ header files generated for the following UNO types are
+ // included in header files in cppu/inc/com/sun/star/uno (Any.hxx,
+ // Reference.hxx, Type.h), so it seems best to always generate those
+ // C++ header files:
+ produce(
+ "com.sun.star.uno.RuntimeException", typeMgr, generated,
+ options);
+ produce(
+ "com.sun.star.uno.TypeClass", typeMgr, generated, options);
+ produce(
+ "com.sun.star.uno.XInterface", typeMgr, generated, options);
+ }
+ } catch (CannotDumpException & e) {
+ std::cerr << "ERROR: " << e.getMessage() << '\n';
+ return EXIT_FAILURE;
+ } catch (unoidl::NoSuchFileException & e) {
+ std::cerr << "ERROR: No such file <" << e.getUri() << ">\n";
+ return EXIT_FAILURE;
+ } catch (unoidl::FileFormatException & e) {
+ std::cerr
+ << "ERROR: Bad format of <" << e.getUri() << ">, \""
+ << e.getDetail() << "\"\n";
+ return EXIT_FAILURE;
+ } catch (IllegalArgument& e) {
+ std::cerr << "Illegal option " << e.m_message << '\n';
+ return EXIT_FAILURE;
+ } catch (std::exception& e) {
+ std::cerr << "Failure " << e.what() << '\n';
+ return EXIT_FAILURE;
+ }
+
+ return EXIT_SUCCESS;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/codemaker/source/cppumaker/cppuoptions.cxx b/codemaker/source/cppumaker/cppuoptions.cxx
new file mode 100644
index 000000000..0a2ad9623
--- /dev/null
+++ b/codemaker/source/cppumaker/cppuoptions.cxx
@@ -0,0 +1,325 @@
+/* -*- 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 <string.h>
+
+#include "cppuoptions.hxx"
+
+#ifdef SAL_UNX
+#define SEPARATOR '/'
+#else
+#define SEPARATOR '\\'
+#endif
+
+bool CppuOptions::initOptions(int ac, char* av[], bool bCmdFile)
+{
+ bool ret = true;
+ int i=0;
+
+ if (!bCmdFile)
+ {
+ bCmdFile = true;
+
+ OString name(av[0]);
+ sal_Int32 index = name.lastIndexOf(SEPARATOR);
+ m_program = name.copy(index > 0 ? index+1 : 0);
+
+ if (ac < 2)
+ {
+ fprintf(stderr, "%s", prepareHelp().getStr());
+ ret = false;
+ }
+
+ i = 1;
+ }
+ else
+ {
+ i = 0;
+ }
+
+ char *s=nullptr;
+ for( ; i < ac; i++)
+ {
+ if (av[i][0] == '-')
+ {
+ switch (av[i][1])
+ {
+ case 'O':
+ if (av[i][2] == '\0')
+ {
+ if (i < ac - 1 && av[i+1][0] != '-')
+ {
+ i++;
+ s = av[i];
+ }
+ else
+ {
+ OString tmp("'-O', please check");
+ if (i <= ac - 1)
+ {
+ tmp += OString::Concat(" your input '") + av[i+1] + "'";
+ }
+
+ throw IllegalArgument(tmp);
+ }
+ }
+ else
+ {
+ s = av[i] + 2;
+ }
+
+ m_options["-O"] = OString(s);
+ break;
+ case 'n':
+ if (av[i][2] != 'D' || av[i][3] != '\0')
+ {
+ OString tmp = OString::Concat("'-nD', please check your input '") + av[i] + "'";
+ throw IllegalArgument(tmp);
+ }
+
+ m_options["-nD"] = OString();
+ break;
+ case 'T':
+ if (av[i][2] == '\0')
+ {
+ if (i < ac - 1 && av[i+1][0] != '-')
+ {
+ i++;
+ s = av[i];
+ }
+ else
+ {
+ OString tmp("'-T', please check");
+ if (i <= ac - 1)
+ {
+ tmp += OString::Concat(" your input '") + av[i+1] + "'";
+ }
+
+ throw IllegalArgument(tmp);
+ }
+ }
+ else
+ {
+ s = av[i] + 2;
+ }
+
+ if (m_options.count("-T") > 0)
+ {
+ OString tmp = m_options["-T"] + ";" + s;
+ m_options["-T"] = tmp;
+ }
+ else
+ {
+ m_options["-T"] = OString(s);
+ }
+ break;
+ case 'L':
+ if (av[i][2] != '\0')
+ {
+ OString tmp("'-L', please check");
+ if (i <= ac - 1)
+ {
+ tmp += OString::Concat(" your input '") + av[i] + "'";
+ }
+
+ throw IllegalArgument(tmp);
+ }
+
+ if (isValid("-C") || isValid("-CS"))
+ {
+ throw IllegalArgument("'-L' could not be combined with '-C' or '-CS' option");
+ }
+ m_options["-L"] = OString();
+ break;
+ case 'C':
+ if (av[i][2] == 'S')
+ {
+ if (av[i][3] != '\0')
+ {
+ OString tmp("'-CS', please check");
+ if (i <= ac - 1)
+ {
+ tmp += OString::Concat(" your input '") + av[i] + "'";
+ }
+
+ throw IllegalArgument(tmp);
+ }
+
+ if (isValid("-L") || isValid("-C"))
+ {
+ throw IllegalArgument("'-CS' could not be combined with '-L' or '-C' option");
+ }
+ m_options["-CS"] = OString();
+ break;
+ }
+ else if (av[i][2] != '\0')
+ {
+ OString tmp("'-C', please check");
+ if (i <= ac - 1)
+ {
+ tmp += OString::Concat(" your input '") + av[i] + "'";
+ }
+
+ throw IllegalArgument(tmp);
+ }
+
+ if (isValid("-L") || isValid("-CS"))
+ {
+ throw IllegalArgument("'-C' could not be combined with '-L' or '-CS' option");
+ }
+ m_options["-C"] = OString();
+ break;
+ case 'G':
+ if (av[i][2] == 'c')
+ {
+ if (av[i][3] != '\0')
+ {
+ OString tmp("'-Gc', please check");
+ if (i <= ac - 1)
+ {
+ tmp += OString::Concat(" your input '") + av[i] + "'";
+ }
+
+ throw IllegalArgument(tmp);
+ }
+
+ m_options["-Gc"] = OString();
+ break;
+ }
+ else if (av[i][2] != '\0')
+ {
+ OString tmp("'-G', please check");
+ if (i <= ac - 1)
+ {
+ tmp += OString::Concat(" your input '") + av[i] + "'";
+ }
+
+ throw IllegalArgument(tmp);
+ }
+
+ m_options["-G"] = OString();
+ break;
+ case 'X': // support for eXtra type rdbs
+ {
+ if (av[i][2] == '\0')
+ {
+ if (i < ac - 1 && av[i+1][0] != '-')
+ {
+ i++;
+ s = av[i];
+ }
+ else
+ {
+ OString tmp("'-X', please check");
+ if (i <= ac - 1)
+ {
+ tmp += OString::Concat(" your input '") + av[i+1] + "'";
+ }
+
+ throw IllegalArgument(tmp);
+ }
+ }
+ else
+ {
+ s = av[i] + 2;
+ }
+
+ m_extra_input_files.emplace_back(s );
+ break;
+ }
+
+ default:
+ throw IllegalArgument(OString::Concat("the option is unknown") + av[i]);
+ }
+ } else
+ {
+ if (av[i][0] == '@')
+ {
+ FILE* cmdFile = fopen(av[i]+1, "r");
+ if( cmdFile == nullptr )
+ {
+ fprintf(stderr, "%s", prepareHelp().getStr());
+ ret = false;
+ }
+ else
+ {
+ int rargc=0;
+ char* rargv[512];
+ char buffer[512];
+
+ while (fscanf(cmdFile, "%511s", buffer) != EOF && rargc < 512)
+ {
+ rargv[rargc]= strdup(buffer);
+ rargc++;
+ }
+ fclose(cmdFile);
+
+ ret = initOptions(rargc, rargv, bCmdFile);
+
+ for (int j=0; j < rargc; j++)
+ {
+ free(rargv[j]);
+ }
+ }
+ }
+ else
+ {
+ m_inputFiles.emplace_back(av[i]);
+ }
+ }
+ }
+
+ return ret;
+}
+
+OString CppuOptions::prepareHelp()
+{
+ OString help = "\nusing: " +
+ m_program + " [-options] file_1 ... file_n\nOptions:\n"
+ " -O<path> = path describes the root directory for the generated output.\n"
+ " The output directory tree is generated under this directory.\n"
+ " -T<name> = name specifies a type or a list of types. The output for this\n"
+ " [t1;...] type is generated. If no '-T' option is specified,\n"
+ " then output for all types is generated.\n"
+ " Example: 'com.sun.star.uno.XInterface' is a valid type.\n"
+ " -L = UNO type functions are generated lightweight, that means only\n"
+ " the name and typeclass are given and everything else is retrieved\n"
+ " from the type library dynamically. The default is that UNO type\n"
+ " functions provides enough type information for bootstrapping C++.\n"
+ " '-L' should be the default for external components.\n"
+ " -C = UNO type functions are generated comprehensive that means all\n"
+ " necessary information is available for bridging the type in UNO.\n"
+ " -nD = no dependent types are generated.\n"
+ " -G = generate only target files which does not exists.\n"
+ " -Gc = generate only target files which content will be changed.\n"
+ " -X<file> = extra types which will not be taken into account for generation.\n\n" +
+ prepareVersion();
+
+ return help;
+}
+
+OString CppuOptions::prepareVersion() const
+{
+ OString version = m_program + " Version 2.0\n\n";
+ return version;
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/codemaker/source/cppumaker/cppuoptions.hxx b/codemaker/source/cppumaker/cppuoptions.hxx
new file mode 100644
index 000000000..f3d65e4fa
--- /dev/null
+++ b/codemaker/source/cppumaker/cppuoptions.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 .
+ */
+
+#pragma once
+
+#include <codemaker/options.hxx>
+
+class CppuOptions : public Options
+{
+public:
+ CppuOptions()
+ : Options()
+ {
+ }
+
+ bool initOptions(int ac, char* av[], bool bCmdFile = false) override;
+
+ OString prepareHelp() override;
+
+ OString prepareVersion() const;
+
+protected:
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/codemaker/source/cppumaker/cpputype.cxx b/codemaker/source/cppumaker/cpputype.cxx
new file mode 100644
index 000000000..03fcd033b
--- /dev/null
+++ b/codemaker/source/cppumaker/cpputype.cxx
@@ -0,0 +1,4105 @@
+/* -*- 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 <sal/log.hxx>
+
+#include <algorithm>
+#include <cassert>
+#include <cstdlib>
+#include <map>
+#include <set>
+#include <string_view>
+#include <memory>
+#include <utility>
+#include <vector>
+#include <iostream>
+
+#include <rtl/alloc.h>
+#include <rtl/ref.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <rtl/ustring.hxx>
+#include <rtl/strbuf.hxx>
+#include <unoidl/unoidl.hxx>
+
+#include <codemaker/commoncpp.hxx>
+#include <codemaker/exceptiontree.hxx>
+#include <codemaker/generatedtypeset.hxx>
+#include <codemaker/typemanager.hxx>
+#include <codemaker/unotype.hxx>
+
+#include "cpputype.hxx"
+#include "cppuoptions.hxx"
+#include "dependencies.hxx"
+#include "dumputils.hxx"
+#include "includes.hxx"
+
+namespace
+{
+
+bool isBootstrapType(OUString const & name)
+{
+ static char const * const names[] = {
+ "com.sun.star.beans.Property",
+ "com.sun.star.beans.PropertyAttribute",
+ "com.sun.star.beans.PropertyChangeEvent",
+ "com.sun.star.beans.PropertyState",
+ "com.sun.star.beans.PropertyValue",
+ "com.sun.star.beans.XFastPropertySet",
+ "com.sun.star.beans.XMultiPropertySet",
+ "com.sun.star.beans.XPropertiesChangeListener",
+ "com.sun.star.beans.XPropertyAccess",
+ "com.sun.star.beans.XPropertyChangeListener",
+ "com.sun.star.beans.XPropertySet",
+ "com.sun.star.beans.XPropertySetInfo",
+ "com.sun.star.beans.XPropertySetOption",
+ "com.sun.star.beans.XVetoableChangeListener",
+ "com.sun.star.bridge.UnoUrlResolver",
+ "com.sun.star.bridge.XUnoUrlResolver",
+ "com.sun.star.connection.SocketPermission",
+ "com.sun.star.container.XElementAccess",
+ "com.sun.star.container.XEnumeration",
+ "com.sun.star.container.XEnumerationAccess",
+ "com.sun.star.container.XHierarchicalNameAccess",
+ "com.sun.star.container.XNameAccess",
+ "com.sun.star.container.XNameContainer",
+ "com.sun.star.container.XNameReplace",
+ "com.sun.star.container.XSet",
+ "com.sun.star.io.FilePermission",
+ "com.sun.star.io.IOException",
+ "com.sun.star.lang.DisposedException",
+ "com.sun.star.lang.EventObject",
+ "com.sun.star.lang.WrappedTargetRuntimeException",
+ "com.sun.star.lang.XComponent",
+ "com.sun.star.lang.XEventListener",
+ "com.sun.star.lang.XInitialization",
+ "com.sun.star.lang.XMultiComponentFactory",
+ "com.sun.star.lang.XMultiServiceFactory",
+ "com.sun.star.lang.XServiceInfo",
+ "com.sun.star.lang.XSingleComponentFactory",
+ "com.sun.star.lang.XSingleServiceFactory",
+ "com.sun.star.lang.XTypeProvider",
+ "com.sun.star.loader.XImplementationLoader",
+ "com.sun.star.reflection.FieldAccessMode",
+ "com.sun.star.reflection.MethodMode",
+ "com.sun.star.reflection.ParamInfo",
+ "com.sun.star.reflection.ParamMode",
+ "com.sun.star.reflection.TypeDescriptionSearchDepth",
+ "com.sun.star.reflection.XCompoundTypeDescription",
+ "com.sun.star.reflection.XEnumTypeDescription",
+ "com.sun.star.reflection.XIdlArray",
+ "com.sun.star.reflection.XIdlClass",
+ "com.sun.star.reflection.XIdlField",
+ "com.sun.star.reflection.XIdlField2",
+ "com.sun.star.reflection.XIdlMethod",
+ "com.sun.star.reflection.XIdlReflection",
+ "com.sun.star.reflection.XIndirectTypeDescription",
+ "com.sun.star.reflection.XInterfaceAttributeTypeDescription",
+ "com.sun.star.reflection.XInterfaceAttributeTypeDescription2",
+ "com.sun.star.reflection.XInterfaceMemberTypeDescription",
+ "com.sun.star.reflection.XInterfaceMethodTypeDescription",
+ "com.sun.star.reflection.XInterfaceTypeDescription",
+ "com.sun.star.reflection.XInterfaceTypeDescription2",
+ "com.sun.star.reflection.XMethodParameter",
+ "com.sun.star.reflection.XStructTypeDescription",
+ "com.sun.star.reflection.XTypeDescription",
+ "com.sun.star.reflection.XTypeDescriptionEnumeration",
+ "com.sun.star.reflection.XTypeDescriptionEnumerationAccess",
+ "com.sun.star.registry.RegistryKeyType",
+ "com.sun.star.registry.RegistryValueType",
+ "com.sun.star.registry.XImplementationRegistration",
+ "com.sun.star.registry.XRegistryKey",
+ "com.sun.star.registry.XSimpleRegistry",
+ "com.sun.star.security.RuntimePermission",
+ "com.sun.star.security.XAccessControlContext",
+ "com.sun.star.security.XAccessController",
+ "com.sun.star.security.XAction",
+ "com.sun.star.uno.DeploymentException",
+ "com.sun.star.uno.RuntimeException",
+ "com.sun.star.uno.TypeClass",
+ "com.sun.star.uno.Uik",
+ "com.sun.star.uno.XAdapter",
+ "com.sun.star.uno.XAggregation",
+ "com.sun.star.uno.XComponentContext",
+ "com.sun.star.uno.XCurrentContext",
+ "com.sun.star.uno.XInterface",
+ "com.sun.star.uno.XReference",
+ "com.sun.star.uno.XUnloadingPreference",
+ "com.sun.star.uno.XWeak",
+ "com.sun.star.util.XMacroExpander" };
+ // cf. cppuhelper/unotypes/Makefile UNOTYPES (plus missing dependencies)
+ auto const pred = [&name](const char* aName) {
+ return name.equalsAscii(aName);
+ };
+ return std::any_of(std::begin(names), std::end(names), pred);
+}
+
+class CppuType
+{
+public:
+ CppuType(OUString name, rtl::Reference< TypeManager > const & typeMgr);
+
+ virtual ~CppuType() {}
+
+ CppuType(const CppuType&) = delete;
+ const CppuType& operator=(const CppuType&) = delete;
+
+ void dump(CppuOptions const & options);
+
+ void dumpFile(
+ std::u16string_view uri, std::u16string_view name, bool hpp,
+ CppuOptions const & options);
+
+ void dumpDependedTypes(
+ codemaker::GeneratedTypeSet & generated, CppuOptions const & options) const;
+
+ virtual void dumpHdlFile(
+ FileStream & out, codemaker::cppumaker::Includes & includes) {
+ dumpHFileContent(out, includes);
+ }
+
+ virtual void dumpHppFile(FileStream& o, codemaker::cppumaker::Includes & includes) = 0;
+
+ OUString dumpHeaderDefine(FileStream& o, std::u16string_view extension) const;
+
+ void dumpGetCppuType(FileStream & out);
+
+ virtual void dumpLightGetCppuType(FileStream & out);
+
+ virtual void dumpNormalGetCppuType(FileStream &) {
+ assert(false); // this cannot happen
+ }
+
+ virtual void dumpComprehensiveGetCppuType(FileStream &) {
+ assert(false); // this cannot happen
+ }
+
+ void dumpType(
+ FileStream & out, std::u16string_view name, bool isConst = false,
+ bool isRef = false, bool native = false, bool cppuUnoType = false)
+ const;
+
+ OUString getTypeClass(OUString const & name, bool cStyle = false);
+
+ void dumpCppuGetType(
+ FileStream & out, std::u16string_view name, OUString const * ownName = nullptr) const;
+
+ sal_uInt32 getInheritedMemberCount();
+
+ void inc(sal_Int32 num=4);
+ void dec(sal_Int32 num=4);
+ OUString indent() const;
+protected:
+ virtual sal_uInt32 checkInheritedMemberCount() const {
+ assert(false); // this cannot happen
+ return 0;
+ }
+
+ bool passByReference(OUString const & name) const;
+
+ bool canBeWarnUnused(OUString const & name) const;
+ bool canBeWarnUnused(OUString const & name, int depth) const;
+
+ OUString resolveOuterTypedefs(OUString const & name) const;
+
+ OUString resolveAllTypedefs(std::u16string_view name) const;
+
+ codemaker::cpp::IdentifierTranslationMode isGlobal() const;
+
+ virtual void dumpDeclaration(FileStream &) {
+ assert(false); // this cannot happen
+ }
+
+ virtual void dumpFiles(OUString const & uri, CppuOptions const & options);
+
+ virtual void addLightGetCppuTypeIncludes(
+ codemaker::cppumaker::Includes & includes) const;
+
+ virtual void addNormalGetCppuTypeIncludes(
+ codemaker::cppumaker::Includes & includes) const;
+
+ virtual void addComprehensiveGetCppuTypeIncludes(
+ codemaker::cppumaker::Includes & includes) const;
+
+ virtual bool isPolymorphic() const;
+
+ virtual void dumpTemplateHead(FileStream &) const {}
+
+ virtual void dumpTemplateParameters(FileStream &) const {}
+
+ void dumpGetCppuTypePreamble(FileStream & out);
+
+ void dumpGetCppuTypePostamble(FileStream & out);
+
+ void addDefaultHIncludes(codemaker::cppumaker::Includes & includes) const;
+ void addDefaultHxxIncludes(codemaker::cppumaker::Includes & includes) const;
+
+ void dumpInitializer(
+ FileStream & out, bool parameterized, std::u16string_view name) const;
+
+ void dumpHFileContent(
+ FileStream & out, codemaker::cppumaker::Includes & includes);
+
+protected:
+ sal_uInt32 m_inheritedMemberCount;
+
+ bool m_cppuTypeLeak;
+ bool m_cppuTypeDynamic;
+ sal_Int32 m_indentLength;
+ OUString name_;
+ OUString id_;
+ rtl::Reference< TypeManager > m_typeMgr;
+ codemaker::cppumaker::Dependencies m_dependencies;
+
+private:
+ void addGetCppuTypeIncludes(codemaker::cppumaker::Includes & includes)
+ const;
+};
+
+CppuType::CppuType(
+ OUString name, rtl::Reference< TypeManager > const & typeMgr):
+ m_inheritedMemberCount(0)
+ , m_cppuTypeLeak(false)
+ , m_cppuTypeDynamic(true)
+ , m_indentLength(0)
+ , name_(std::move(name))
+ , id_(name_.copy(name_.lastIndexOf('.') + 1))
+ , m_typeMgr(typeMgr)
+ , m_dependencies(typeMgr, name_)
+{}
+
+void CppuType::addGetCppuTypeIncludes(codemaker::cppumaker::Includes & includes)
+const
+{
+ if (name_ == "com.sun.star.uno.XInterface"
+ || name_ == "com.sun.star.uno.Exception") {
+ includes.addType();
+ includes.addCppuUnotypeHxx();
+ includes.addSalTypesH();
+ includes.addTypelibTypeclassH();
+ includes.addTypelibTypedescriptionH();
+ } else if (m_cppuTypeLeak) {
+ addLightGetCppuTypeIncludes(includes);
+ } else if (m_cppuTypeDynamic) {
+ addNormalGetCppuTypeIncludes(includes);
+ } else {
+ addComprehensiveGetCppuTypeIncludes(includes);
+ }
+}
+
+void CppuType::dumpFiles(OUString const & uri, CppuOptions const & options)
+{
+ dumpFile(uri, name_, false, options);
+ dumpFile(uri, name_, true, options);
+}
+
+void CppuType::addLightGetCppuTypeIncludes(
+ codemaker::cppumaker::Includes & includes) const
+{
+ //TODO: Determine what is really needed, instead of relying on
+ // addDefaultHxxIncludes
+ includes.addCppuUnotypeHxx();
+}
+
+void CppuType::addNormalGetCppuTypeIncludes(
+ codemaker::cppumaker::Includes & includes) const
+{
+ //TODO: Determine what is really needed, instead of relying on
+ // addDefaultHxxIncludes
+ includes.addCppuUnotypeHxx();
+}
+
+void CppuType::addComprehensiveGetCppuTypeIncludes(
+ codemaker::cppumaker::Includes & includes) const
+{
+ //TODO: Determine what is really needed, instead of relying on
+ // addDefaultHxxIncludes
+ includes.addCppuUnotypeHxx();
+}
+
+bool CppuType::isPolymorphic() const
+{
+ return false;
+}
+
+void CppuType::dumpGetCppuTypePreamble(FileStream & out)
+{
+ if (isPolymorphic()) {
+ out << "namespace cppu {\n\n";
+ dumpTemplateHead(out);
+ out << "class UnoType< ";
+ dumpType(out, name_);
+ dumpTemplateParameters(out);
+ out << " > {\npublic:\n";
+ inc();
+ out << indent()
+ << "static inline ::css::uno::Type const & get() {\n";
+ } else {
+ if (codemaker::cppumaker::dumpNamespaceOpen(out, name_, false)) {
+ out << "\n\n";
+ }
+ out << ("inline ::css::uno::Type const &"
+ " cppu_detail_getUnoType(SAL_UNUSED_PARAMETER ");
+ dumpType(out, name_, false, false, true);
+ out << " const *) {\n";
+ }
+ inc();
+}
+
+void CppuType::dumpGetCppuTypePostamble(FileStream & out)
+{
+ dec();
+ if (isPolymorphic()) {
+ out << indent() << "}\n\nprivate:\n"
+ << indent() << "UnoType(UnoType &); // not defined\n"
+ << indent() << "~UnoType(); // not defined\n"
+ << indent()
+ << "void operator =(UnoType); // not defined\n};\n\n}\n\n";
+ } else {
+ out << "}\n\n";
+ if (codemaker::cppumaker::dumpNamespaceClose(out, name_, false)) {
+ out << "\n\n";
+ }
+ }
+ dumpTemplateHead(out);
+ out << ("SAL_DEPRECATED(\"use cppu::UnoType\") inline ::css::uno::Type const & SAL_CALL"
+ " getCppuType(SAL_UNUSED_PARAMETER ");
+ dumpType(out, name_);
+ dumpTemplateParameters(out);
+ out << " const *) {\n";
+ inc();
+ out << indent() << "return ::cppu::UnoType< ";
+ dumpType(out, name_);
+ dumpTemplateParameters(out);
+ out << " >::get();\n";
+ dec();
+ out << indent() << "}\n";
+}
+
+void CppuType::dump(CppuOptions const & options)
+{
+ if (isBootstrapType(name_)) {
+ m_cppuTypeDynamic = false;
+ } else {
+ // -CS was used as an undocumented option to generate static getCppuType
+ // functions; since the introduction of cppu::UnoType this no longer is
+ // meaningful (getCppuType is just a forward to cppu::UnoType::get now),
+ // and -CS is handled the same way as -C now:
+ if (options.isValid("-L"))
+ m_cppuTypeLeak = true;
+ if (options.isValid("-C") || options.isValid("-CS"))
+ m_cppuTypeDynamic = false;
+ }
+ dumpFiles(
+ options.isValid("-O") ? b2u(options.getOption("-O")) : "", options);
+}
+
+void CppuType::dumpFile(
+ std::u16string_view uri, std::u16string_view name, bool hpp,
+ CppuOptions const & options)
+{
+ OUString fileUri(
+ b2u(createFileNameFromType(
+ u2b(uri), u2b(name), hpp ? ".hpp" : ".hdl")));
+ if (fileUri.isEmpty()) {
+ throw CannotDumpException(OUString::Concat("empty target URI for entity ") + name);
+ }
+ bool exists = fileExists(u2b(fileUri));
+ if (exists && options.isValid("-G")) {
+ return;
+ }
+ FileStream out;
+ out.createTempFile(getTempDir(u2b(fileUri)));
+ OUString tmpUri(b2u(out.getName()));
+ if(!out.isValid()) {
+ throw CannotDumpException("cannot open " + tmpUri + " for writing");
+ }
+ codemaker::cppumaker::Includes includes(m_typeMgr, m_dependencies, hpp);
+ try {
+ if (hpp) {
+ addGetCppuTypeIncludes(includes);
+ dumpHppFile(out, includes);
+ } else {
+ dumpHdlFile(out, includes);
+ }
+ } catch (...) {
+ out.close();
+ // Remove existing type file if something goes wrong to ensure
+ // consistency:
+ if (fileExists(u2b(fileUri))) {
+ removeTypeFile(u2b(fileUri));
+ }
+ removeTypeFile(u2b(tmpUri));
+ throw;
+ }
+ out.close();
+ (void)makeValidTypeFile(
+ u2b(fileUri), u2b(tmpUri), exists && options.isValid("-Gc"));
+}
+
+void CppuType::dumpDependedTypes(
+ codemaker::GeneratedTypeSet & generated, CppuOptions const & options) const
+{
+ if (!options.isValid("-nD")) {
+ codemaker::cppumaker::Dependencies::Map const & map
+ = m_dependencies.getMap();
+ for (const auto& entry : map) {
+ produce(entry.first, m_typeMgr, generated, options);
+ }
+ }
+}
+
+OUString CppuType::dumpHeaderDefine(
+ FileStream & out, std::u16string_view extension) const
+{
+ OUString def(
+ "INCLUDED_" + name_.replace('.', '_').toAsciiUpperCase() + "_"
+ + extension);
+ out << "#ifndef " << def << "\n#define " << def << "\n";
+ return def;
+}
+
+void CppuType::addDefaultHIncludes(codemaker::cppumaker::Includes & includes)
+const
+{
+ //TODO: Only include what is really needed
+ includes.addCppuMacrosHxx();
+ if (m_typeMgr->getSort(name_)
+ == codemaker::UnoType::Sort::Interface) {
+ includes.addReference();
+ }
+}
+
+void CppuType::addDefaultHxxIncludes(codemaker::cppumaker::Includes & includes)
+const
+{
+ //TODO: Only include what is really needed
+ includes.addType();
+ if (m_typeMgr->getSort(name_)
+ == codemaker::UnoType::Sort::Interface) {
+ includes.addReference();
+ }
+}
+
+void CppuType::dumpInitializer(
+ FileStream & out, bool parameterized, std::u16string_view name) const
+{
+ out << "(";
+ if (!parameterized) {
+ sal_Int32 k;
+ std::vector< OString > args;
+ OUString n(
+ b2u(codemaker::UnoType::decompose(
+ u2b(resolveAllTypedefs(name)), &k, &args)));
+ if (k == 0) {
+ rtl::Reference< unoidl::Entity > ent;
+ switch (m_typeMgr->getSort(n, &ent)) {
+ case codemaker::UnoType::Sort::Boolean:
+ out << "false";
+ break;
+ case codemaker::UnoType::Sort::Byte:
+ case codemaker::UnoType::Sort::Short:
+ case codemaker::UnoType::Sort::UnsignedShort:
+ case codemaker::UnoType::Sort::Long:
+ case codemaker::UnoType::Sort::UnsignedLong:
+ case codemaker::UnoType::Sort::Hyper:
+ case codemaker::UnoType::Sort::UnsignedHyper:
+ case codemaker::UnoType::Sort::Float:
+ case codemaker::UnoType::Sort::Double:
+ case codemaker::UnoType::Sort::Char:
+ out << "0";
+ break;
+ case codemaker::UnoType::Sort::Enum:
+ out << codemaker::cpp::scopedCppName(u2b(n)) << "_"
+ << (dynamic_cast<unoidl::EnumTypeEntity&>(*ent).
+ getMembers()[0].name);
+ break;
+ case codemaker::UnoType::Sort::String:
+ case codemaker::UnoType::Sort::Type:
+ case codemaker::UnoType::Sort::Any:
+ case codemaker::UnoType::Sort::PlainStruct:
+ case codemaker::UnoType::Sort::PolymorphicStructTemplate:
+ case codemaker::UnoType::Sort::Interface:
+ break;
+ default:
+ throw CannotDumpException(
+ OUString::Concat("unexpected entity \"") + name
+ + "\" in call to CppuType::dumpInitializer");
+ }
+ }
+ }
+ out << ")";
+}
+
+void CppuType::dumpHFileContent(
+ FileStream & out, codemaker::cppumaker::Includes & includes)
+{
+ addDefaultHIncludes(includes);
+ dumpHeaderDefine(out, u"HDL");
+ out << "\n";
+ includes.dump(out, nullptr, false);
+ // 'exceptions = false' would be wrong for services/singletons, but
+ // those don't dump .hdl files anyway
+ out << ("\nnamespace com { namespace sun { namespace star { namespace uno"
+ " { class Type; } } } }\n\n");
+ if (codemaker::cppumaker::dumpNamespaceOpen(out, name_, false)) {
+ out << "\n";
+ }
+ dumpDeclaration(out);
+ if (!(name_ == "com.sun.star.uno.XInterface"
+ || name_ == "com.sun.star.uno.Exception"
+ || isPolymorphic())) {
+ out << "\n" << indent()
+ << ("inline ::css::uno::Type const &"
+ " cppu_detail_getUnoType(SAL_UNUSED_PARAMETER ");
+ dumpType(out, name_, false, false, true);
+ out << " const *);\n";
+ }
+ if (codemaker::cppumaker::dumpNamespaceClose(out, name_, false)) {
+ out << "\n";
+ }
+ out << "\n";
+ dumpTemplateHead(out);
+ out << "SAL_DEPRECATED(\"use cppu::UnoType\") inline ::css::uno::Type const & SAL_CALL getCppuType(";
+ dumpType(out, name_, true);
+ dumpTemplateParameters(out);
+ out << " *);\n\n#endif\n";
+}
+
+void CppuType::dumpGetCppuType(FileStream & out)
+{
+ if (name_ == "com.sun.star.uno.XInterface") {
+ out << indent()
+ << ("SAL_DEPRECATED(\"use cppu::UnoType\") inline ::css::uno::Type const & SAL_CALL"
+ " getCppuType(SAL_UNUSED_PARAMETER ");
+ dumpType(out, name_, true);
+ out << " *) {\n";
+ inc();
+ out << indent()
+ << ("return ::cppu::UnoType< ::css::uno::XInterface"
+ " >::get();\n");
+ dec();
+ out << indent() << "}\n";
+ } else if (name_ == "com.sun.star.uno.Exception") {
+ out << indent()
+ << ("SAL_DEPRECATED(\"use cppu::UnoType\") inline ::css::uno::Type const & SAL_CALL"
+ " getCppuType(SAL_UNUSED_PARAMETER ");
+ dumpType(out, name_, true);
+ out << " *) {\n";
+ inc();
+ out << indent()
+ << ("return ::cppu::UnoType< ::css::uno::Exception"
+ " >::get();\n");
+ dec();
+ out << indent() << "}\n";
+ } else if (m_cppuTypeLeak) {
+ dumpLightGetCppuType(out);
+ } else if (m_cppuTypeDynamic) {
+ dumpNormalGetCppuType(out);
+ } else {
+ dumpComprehensiveGetCppuType(out);
+ }
+}
+
+void CppuType::dumpLightGetCppuType(FileStream & out)
+{
+ dumpGetCppuTypePreamble(out);
+ out << indent()
+ << "static typelib_TypeDescriptionReference * the_type = 0;\n"
+ << indent() << "if ( !the_type )\n" << indent() << "{\n";
+ inc();
+ out << indent() << "typelib_static_type_init( &the_type, "
+ << getTypeClass(name_, true) << ", \"" << name_ << "\" );\n";
+ dec();
+ out << indent() << "}\n" << indent()
+ << ("return * reinterpret_cast< ::css::uno::Type * >("
+ " &the_type );\n");
+ dumpGetCppuTypePostamble(out);
+}
+
+codemaker::cpp::IdentifierTranslationMode CppuType::isGlobal() const
+{
+ return name_.indexOf('.') == -1
+ ? codemaker::cpp::IdentifierTranslationMode::Global : codemaker::cpp::IdentifierTranslationMode::NonGlobal;
+}
+
+sal_uInt32 CppuType::getInheritedMemberCount()
+{
+ if (m_inheritedMemberCount == 0) {
+ m_inheritedMemberCount = checkInheritedMemberCount();
+ }
+
+ return m_inheritedMemberCount;
+}
+
+OUString CppuType::getTypeClass(OUString const & name, bool cStyle)
+{
+ rtl::Reference< unoidl::Entity > ent;
+ switch (m_typeMgr->getSort(name, &ent)) {
+ case codemaker::UnoType::Sort::Void:
+ return cStyle
+ ? OUString("typelib_TypeClass_VOID")
+ : OUString("::css::uno::TypeClass_VOID");
+ case codemaker::UnoType::Sort::Boolean:
+ return cStyle
+ ? OUString("typelib_TypeClass_BOOLEAN")
+ : OUString("::css::uno::TypeClass_BOOLEAN");
+ case codemaker::UnoType::Sort::Byte:
+ return cStyle
+ ? OUString("typelib_TypeClass_BYTE")
+ : OUString("::css::uno::TypeClass_BYTE");
+ case codemaker::UnoType::Sort::Short:
+ return cStyle
+ ? OUString("typelib_TypeClass_SHORT")
+ : OUString("::css::uno::TypeClass_SHORT");
+ case codemaker::UnoType::Sort::UnsignedShort:
+ return cStyle
+ ? OUString("typelib_TypeClass_UNSIGNED_SHORT")
+ : OUString("::css::uno::TypeClass_UNSIGNED_SHORT");
+ case codemaker::UnoType::Sort::Long:
+ return cStyle
+ ? OUString("typelib_TypeClass_LONG")
+ : OUString("::css::uno::TypeClass_LONG");
+ case codemaker::UnoType::Sort::UnsignedLong:
+ return cStyle
+ ? OUString("typelib_TypeClass_UNSIGNED_LONG")
+ : OUString("::css::uno::TypeClass_UNSIGNED_LONG");
+ case codemaker::UnoType::Sort::Hyper:
+ return cStyle
+ ? OUString("typelib_TypeClass_HYPER")
+ : OUString("::css::uno::TypeClass_HYPER");
+ case codemaker::UnoType::Sort::UnsignedHyper:
+ return cStyle
+ ? OUString("typelib_TypeClass_UNSIGNED_HYPER")
+ : OUString("::css::uno::TypeClass_UNSIGNED_HYPER");
+ case codemaker::UnoType::Sort::Float:
+ return cStyle
+ ? OUString("typelib_TypeClass_FLOAT")
+ : OUString("::css::uno::TypeClass_FLOAT");
+ case codemaker::UnoType::Sort::Double:
+ return cStyle
+ ? OUString("typelib_TypeClass_DOUBLE")
+ : OUString("::css::uno::TypeClass_DOUBLE");
+ case codemaker::UnoType::Sort::Char:
+ return cStyle
+ ? OUString("typelib_TypeClass_CHAR")
+ : OUString("::css::uno::TypeClass_CHAR");
+ case codemaker::UnoType::Sort::String:
+ return cStyle
+ ? OUString("typelib_TypeClass_STRING")
+ : OUString("::css::uno::TypeClass_STRING");
+ case codemaker::UnoType::Sort::Type:
+ return cStyle
+ ? OUString("typelib_TypeClass_TYPE")
+ : OUString("::css::uno::TypeClass_TYPE");
+ case codemaker::UnoType::Sort::Any:
+ return cStyle
+ ? OUString("typelib_TypeClass_ANY")
+ : OUString("::css::uno::TypeClass_ANY");
+ case codemaker::UnoType::Sort::Sequence:
+ return cStyle
+ ? OUString("typelib_TypeClass_SEQUENCE")
+ : OUString("::css::uno::TypeClass_SEQUENCE");
+ case codemaker::UnoType::Sort::Enum:
+ return cStyle
+ ? OUString("typelib_TypeClass_ENUM")
+ : OUString("::css::uno::TypeClass_ENUM");
+ case codemaker::UnoType::Sort::PlainStruct:
+ case codemaker::UnoType::Sort::PolymorphicStructTemplate:
+ case codemaker::UnoType::Sort::InstantiatedPolymorphicStruct:
+ return cStyle
+ ? OUString("typelib_TypeClass_STRUCT")
+ : OUString("::css::uno::TypeClass_STRUCT");
+ case codemaker::UnoType::Sort::Exception:
+ return cStyle
+ ? OUString("typelib_TypeClass_EXCEPTION")
+ : OUString("::css::uno::TypeClass_EXCEPTION");
+ case codemaker::UnoType::Sort::Interface:
+ return cStyle
+ ? OUString("typelib_TypeClass_INTERFACE")
+ : OUString("::css::uno::TypeClass_INTERFACE");
+ case codemaker::UnoType::Sort::Typedef:
+ return getTypeClass(dynamic_cast<unoidl::TypedefEntity&>(*ent).getType(), cStyle);
+ default:
+ for (;;) {
+ std::abort();
+ }
+ }
+}
+
+void CppuType::dumpType(
+ FileStream & out, std::u16string_view name, bool isConst, bool isRef,
+ bool native, bool cppuUnoType) const
+{
+ sal_Int32 k;
+ std::vector< OString > args;
+ OUString n(
+ b2u(codemaker::UnoType::decompose(
+ u2b(resolveAllTypedefs(name)), &k, &args)));
+ if (isConst) {
+ out << "const ";
+ }
+ for (sal_Int32 i = 0; i != k; ++i) {
+ out << (cppuUnoType
+ ? "::cppu::UnoSequenceType" : "::css::uno::Sequence")
+ << "< ";
+ }
+ switch (m_typeMgr->getSort(n)) {
+ case codemaker::UnoType::Sort::Void:
+ out << "void";
+ break;
+ case codemaker::UnoType::Sort::Boolean:
+ out << "::sal_Bool";
+ break;
+ case codemaker::UnoType::Sort::Byte:
+ out << "::sal_Int8";
+ break;
+ case codemaker::UnoType::Sort::Short:
+ out << "::sal_Int16";
+ break;
+ case codemaker::UnoType::Sort::UnsignedShort:
+ out << (cppuUnoType ? "::cppu::UnoUnsignedShortType" : "::sal_uInt16");
+ break;
+ case codemaker::UnoType::Sort::Long:
+ out << "::sal_Int32";
+ break;
+ case codemaker::UnoType::Sort::UnsignedLong:
+ out << "::sal_uInt32";
+ break;
+ case codemaker::UnoType::Sort::Hyper:
+ out << "::sal_Int64";
+ break;
+ case codemaker::UnoType::Sort::UnsignedHyper:
+ out << "::sal_uInt64";
+ break;
+ case codemaker::UnoType::Sort::Float:
+ out << "float";
+ break;
+ case codemaker::UnoType::Sort::Double:
+ out << "double";
+ break;
+ case codemaker::UnoType::Sort::Char:
+ out << (cppuUnoType ? "::cppu::UnoCharType" : "::sal_Unicode");
+ break;
+ case codemaker::UnoType::Sort::String:
+ out << "::rtl::OUString";
+ break;
+ case codemaker::UnoType::Sort::Type:
+ out << "::css::uno::Type";
+ break;
+ case codemaker::UnoType::Sort::Any:
+ out << "::css::uno::Any";
+ break;
+ case codemaker::UnoType::Sort::Enum:
+ case codemaker::UnoType::Sort::PlainStruct:
+ case codemaker::UnoType::Sort::Exception:
+ out << codemaker::cpp::scopedCppName(u2b(n));
+ break;
+ case codemaker::UnoType::Sort::PolymorphicStructTemplate:
+ out << codemaker::cpp::scopedCppName(u2b(n));
+ if (!args.empty()) {
+ out << "< ";
+ for (std::vector< OString >::iterator i(args.begin());
+ i != args.end(); ++i) {
+ if (i != args.begin()) {
+ out << ", ";
+ }
+ dumpType(out, b2u(*i));
+ }
+ out << " >";
+ }
+ break;
+ case codemaker::UnoType::Sort::Interface:
+ if (!native) {
+ out << "::css::uno::Reference< ";
+ }
+ out << codemaker::cpp::scopedCppName(u2b(n));
+ if (!native) {
+ out << " >";
+ }
+ break;
+ default:
+ throw CannotDumpException(
+ OUString::Concat("unexpected entity \"") + name + "\" in call to CppuType::dumpType");
+ }
+ for (sal_Int32 i = 0; i != k; ++i) {
+ out << " >";
+ }
+ if (isRef) {
+ out << "&";
+ }
+}
+
+void CppuType::dumpCppuGetType(
+ FileStream & out, std::u16string_view name, OUString const * ownName) const
+{
+ //TODO: What are these calls good for?
+ OUString nucleus;
+ sal_Int32 rank;
+ codemaker::UnoType::Sort sort = m_typeMgr->decompose(
+ name, true, &nucleus, &rank, nullptr, nullptr);
+ switch (rank == 0 ? sort : codemaker::UnoType::Sort::Sequence) {
+ case codemaker::UnoType::Sort::Void:
+ case codemaker::UnoType::Sort::Boolean:
+ case codemaker::UnoType::Sort::Byte:
+ case codemaker::UnoType::Sort::Short:
+ case codemaker::UnoType::Sort::UnsignedShort:
+ case codemaker::UnoType::Sort::Long:
+ case codemaker::UnoType::Sort::UnsignedLong:
+ case codemaker::UnoType::Sort::Hyper:
+ case codemaker::UnoType::Sort::UnsignedHyper:
+ case codemaker::UnoType::Sort::Float:
+ case codemaker::UnoType::Sort::Double:
+ case codemaker::UnoType::Sort::Char:
+ case codemaker::UnoType::Sort::String:
+ case codemaker::UnoType::Sort::Type:
+ case codemaker::UnoType::Sort::Any:
+ break;
+ case codemaker::UnoType::Sort::Sequence:
+ case codemaker::UnoType::Sort::Enum:
+ case codemaker::UnoType::Sort::PlainStruct:
+ case codemaker::UnoType::Sort::InstantiatedPolymorphicStruct:
+ case codemaker::UnoType::Sort::Exception:
+ case codemaker::UnoType::Sort::Interface:
+ // Take care of recursion like struct S { sequence<S> x; }:
+ if (ownName == nullptr || nucleus != *ownName) {
+ out << indent() << "::cppu::UnoType< ";
+ dumpType(out, name, false, false, false, true);
+ out << " >::get();\n";
+ }
+ break;
+ case codemaker::UnoType::Sort::Typedef:
+ for (;;) std::abort(); // this cannot happen
+ default:
+ throw CannotDumpException(
+ OUString::Concat("unexpected entity \"") + name
+ + "\" in call to CppuType::dumpCppuGetType");
+ }
+}
+
+bool CppuType::passByReference(OUString const & name) const
+{
+ switch (m_typeMgr->getSort(resolveOuterTypedefs(name))) {
+ case codemaker::UnoType::Sort::Boolean:
+ case codemaker::UnoType::Sort::Byte:
+ case codemaker::UnoType::Sort::Short:
+ case codemaker::UnoType::Sort::UnsignedShort:
+ case codemaker::UnoType::Sort::Long:
+ case codemaker::UnoType::Sort::UnsignedLong:
+ case codemaker::UnoType::Sort::Hyper:
+ case codemaker::UnoType::Sort::UnsignedHyper:
+ case codemaker::UnoType::Sort::Float:
+ case codemaker::UnoType::Sort::Double:
+ case codemaker::UnoType::Sort::Char:
+ case codemaker::UnoType::Sort::Enum:
+ return false;
+ case codemaker::UnoType::Sort::String:
+ case codemaker::UnoType::Sort::Type:
+ case codemaker::UnoType::Sort::Any:
+ case codemaker::UnoType::Sort::Sequence:
+ case codemaker::UnoType::Sort::PlainStruct:
+ case codemaker::UnoType::Sort::InstantiatedPolymorphicStruct:
+ case codemaker::UnoType::Sort::Interface:
+ return true;
+ default:
+ throw CannotDumpException(
+ "unexpected entity \"" + name
+ + "\" in call to CppuType::passByReference");
+ }
+}
+
+bool CppuType::canBeWarnUnused(OUString const & name) const
+{
+ return canBeWarnUnused(name, 0);
+}
+bool CppuType::canBeWarnUnused(OUString const & name, int depth) const
+{
+ // prevent infinite recursion and blowing the stack
+ if (depth > 10)
+ return false;
+ OUString aResolvedName = resolveOuterTypedefs(name);
+ switch (m_typeMgr->getSort(aResolvedName)) {
+ case codemaker::UnoType::Sort::Boolean:
+ case codemaker::UnoType::Sort::Byte:
+ case codemaker::UnoType::Sort::Short:
+ case codemaker::UnoType::Sort::UnsignedShort:
+ case codemaker::UnoType::Sort::Long:
+ case codemaker::UnoType::Sort::UnsignedLong:
+ case codemaker::UnoType::Sort::Hyper:
+ case codemaker::UnoType::Sort::UnsignedHyper:
+ case codemaker::UnoType::Sort::Float:
+ case codemaker::UnoType::Sort::Double:
+ case codemaker::UnoType::Sort::Char:
+ case codemaker::UnoType::Sort::Enum:
+ case codemaker::UnoType::Sort::String:
+ case codemaker::UnoType::Sort::Type:
+ return true;
+ case codemaker::UnoType::Sort::PlainStruct: {
+ rtl::Reference< unoidl::Entity > ent;
+ m_typeMgr->getSort(aResolvedName, &ent);
+ rtl::Reference< unoidl::PlainStructTypeEntity > ent2(
+ dynamic_cast< unoidl::PlainStructTypeEntity * >(ent.get()));
+ if (!ent2->getDirectBase().isEmpty() && !canBeWarnUnused(ent2->getDirectBase(), depth+1))
+ return false;
+ for ( const unoidl::PlainStructTypeEntity::Member& rMember : ent2->getDirectMembers()) {
+ if (!canBeWarnUnused(rMember.type, depth+1))
+ return false;
+ }
+ return true;
+ }
+ case codemaker::UnoType::Sort::Sequence: {
+ OUString aInnerType = aResolvedName.copy(2);
+ return canBeWarnUnused(aInnerType, depth+1);
+ }
+ case codemaker::UnoType::Sort::Any:
+ case codemaker::UnoType::Sort::InstantiatedPolymorphicStruct:
+ case codemaker::UnoType::Sort::Interface:
+ return false;
+ default:
+ throw CannotDumpException(
+ "unexpected entity \"" + name
+ + "\" in call to CppuType::canBeWarnUnused");
+ }
+}
+
+OUString CppuType::resolveOuterTypedefs(OUString const & name) const
+{
+ for (OUString n(name);;) {
+ rtl::Reference< unoidl::Entity > ent;
+ if (m_typeMgr->getSort(n, &ent) != codemaker::UnoType::Sort::Typedef) {
+ return n;
+ }
+ n = dynamic_cast<unoidl::TypedefEntity&>(*ent).getType();
+ }
+}
+
+OUString CppuType::resolveAllTypedefs(std::u16string_view name) const
+{
+ sal_Int32 k1;
+ OUString n(b2u(codemaker::UnoType::decompose(u2b(name), &k1)));
+ for (;;) {
+ rtl::Reference< unoidl::Entity > ent;
+ if (m_typeMgr->getSort(n, &ent) != codemaker::UnoType::Sort::Typedef) {
+ break;
+ }
+ sal_Int32 k2;
+ n = b2u(codemaker::UnoType::decompose(
+ u2b(dynamic_cast<unoidl::TypedefEntity&>(*ent).getType()), &k2));
+ k1 += k2; //TODO: overflow
+ }
+ OUStringBuffer b(k1*2 + n.getLength());
+ for (sal_Int32 i = 0; i != k1; ++i) {
+ b.append("[]");
+ }
+ b.append(n);
+ return b.makeStringAndClear();
+}
+
+void CppuType::inc(sal_Int32 num)
+{
+ m_indentLength += num;
+}
+
+void CppuType::dec(sal_Int32 num)
+{
+ m_indentLength = std::max< sal_Int32 >(m_indentLength - num, 0);
+}
+
+OUString CppuType::indent() const
+{
+ OUStringBuffer buf(m_indentLength);
+ for (sal_Int32 i = 0; i != m_indentLength; ++i) {
+ buf.append(' ');
+ }
+ return buf.makeStringAndClear();
+}
+
+bool isDeprecated(std::vector< OUString > const & annotations)
+{
+ for (const OUString& r : annotations) {
+ if (r == "deprecated") {
+ return true;
+ }
+ }
+ return false;
+}
+
+void dumpDeprecation(FileStream & out, bool deprecated)
+{
+ if (deprecated) {
+ out << "SAL_DEPRECATED_INTERNAL(\"marked @deprecated in UNOIDL\") ";
+ }
+}
+
+class BaseOffset
+{
+public:
+ BaseOffset(
+ rtl::Reference< TypeManager > manager,
+ rtl::Reference< unoidl::InterfaceTypeEntity > const & entity):
+ manager_(std::move(manager)), offset_(0) {
+ calculateBases(entity);
+ }
+ BaseOffset(const BaseOffset&) = delete;
+ const BaseOffset& operator=(const BaseOffset&) = delete;
+
+ sal_Int32 get() const {
+ return offset_;
+ }
+
+private:
+ void calculateBases(
+ rtl::Reference< unoidl::InterfaceTypeEntity > const & entity);
+
+ rtl::Reference< TypeManager > manager_;
+ std::set< OUString > set_;
+ sal_Int32 offset_;
+};
+
+void BaseOffset::calculateBases(
+ rtl::Reference< unoidl::InterfaceTypeEntity > const & entity)
+{
+ assert(entity.is());
+ for (const unoidl::AnnotatedReference& ar : entity->getDirectMandatoryBases()) {
+ if (set_.insert(ar.name).second) {
+ rtl::Reference< unoidl::Entity > ent;
+ codemaker::UnoType::Sort sort = manager_->getSort(ar.name, &ent);
+ if (sort != codemaker::UnoType::Sort::Interface) {
+ throw CannotDumpException(
+ "interface type base " + ar.name
+ + " is not an interface type");
+ }
+ rtl::Reference< unoidl::InterfaceTypeEntity > ent2(
+ dynamic_cast< unoidl::InterfaceTypeEntity * >(ent.get()));
+ assert(ent2.is());
+ calculateBases(ent2);
+ offset_ += ent2->getDirectAttributes().size()
+ + ent2->getDirectMethods().size(); //TODO: overflow
+ }
+ }
+}
+
+class InterfaceType: public CppuType
+{
+public:
+ InterfaceType(
+ rtl::Reference< unoidl::InterfaceTypeEntity > const & entity,
+ OUString const & name, rtl::Reference< TypeManager > const & typeMgr);
+
+ virtual void dumpDeclaration(FileStream& o) override;
+ void dumpHppFile(FileStream& o, codemaker::cppumaker::Includes & includes) override;
+
+ void dumpAttributes(FileStream& o) const;
+ void dumpMethods(FileStream& o) const;
+ void dumpNormalGetCppuType(FileStream& o) override;
+ void dumpComprehensiveGetCppuType(FileStream& o) override;
+ void dumpCppuAttributeRefs(FileStream& o, sal_uInt32& index);
+ void dumpCppuMethodRefs(FileStream& o, sal_uInt32& index);
+ void dumpCppuAttributes(FileStream& o, sal_uInt32& index);
+ void dumpCppuMethods(FileStream& o, sal_uInt32& index);
+ void dumpAttributesCppuDecl(FileStream & out, std::set< OUString > * seen) const;
+ void dumpMethodsCppuDecl(FileStream & out, std::set< OUString > * seen) const;
+
+private:
+ virtual void addComprehensiveGetCppuTypeIncludes(
+ codemaker::cppumaker::Includes & includes) const override;
+
+ virtual sal_uInt32 checkInheritedMemberCount() const override {
+ return BaseOffset(m_typeMgr, entity_).get();
+ }
+
+ void dumpExceptionTypeName(
+ FileStream & out, std::u16string_view prefix, sal_uInt32 index,
+ std::u16string_view name) const;
+
+ sal_Int32 dumpExceptionTypeNames(
+ FileStream & out, std::u16string_view prefix,
+ std::vector< OUString > const & exceptions, bool runtimeException) const;
+
+ rtl::Reference< unoidl::InterfaceTypeEntity > entity_;
+ bool m_isDeprecated;
+};
+
+InterfaceType::InterfaceType(
+ rtl::Reference< unoidl::InterfaceTypeEntity > const & entity,
+ OUString const & name, rtl::Reference< TypeManager > const & typeMgr):
+ CppuType(name, typeMgr), entity_(entity),
+ m_isDeprecated(isDeprecated(entity->getAnnotations()))
+{
+ assert(entity.is());
+}
+
+void InterfaceType::dumpDeclaration(FileStream & out)
+{
+ out << "\nclass SAL_NO_VTABLE SAL_DLLPUBLIC_RTTI " << id_;
+ for (std::vector< unoidl::AnnotatedReference >::const_iterator i(
+ entity_->getDirectMandatoryBases().begin());
+ i != entity_->getDirectMandatoryBases().end(); ++i) {
+ out << (i == entity_->getDirectMandatoryBases().begin() ? " :" : ",")
+ << " public " << codemaker::cpp::scopedCppName(u2b(i->name));
+ }
+ out << "\n{\npublic:\n";
+ inc();
+ out << "#if defined LIBO_INTERNAL_ONLY\n"
+ << indent() << id_ << "() = default;\n"
+ << indent() << id_ << "(" << id_ << " const &) = default;\n"
+ << indent() << id_ << "(" << id_ << " &&) = default;\n"
+ << indent() << id_ << " & operator =(" << id_ << " const &) = default;\n"
+ << indent() << id_ << " & operator =(" << id_ << " &&) = default;\n#endif\n\n";
+ dumpAttributes(out);
+ dumpMethods(out);
+ out << "\n" << indent()
+ << ("static inline ::css::uno::Type const & SAL_CALL"
+ " static_type(void * = 0);\n\n");
+ dec();
+ out << "protected:\n";
+ inc();
+ out << indent() << "~" << id_
+ << ("() SAL_NOEXCEPT {} // avoid warnings about virtual members and"
+ " non-virtual dtor\n");
+ dec();
+ out << "};\n\n";
+}
+
+void InterfaceType::dumpHppFile(
+ FileStream & out, codemaker::cppumaker::Includes & includes)
+{
+ OUString headerDefine(dumpHeaderDefine(out, u"HPP"));
+ out << "\n";
+ addDefaultHxxIncludes(includes);
+ includes.dump(out, &name_, !(m_cppuTypeLeak || m_cppuTypeDynamic));
+ out << "\n";
+ dumpGetCppuType(out);
+ out << "\n::css::uno::Type const & "
+ << codemaker::cpp::scopedCppName(u2b(name_))
+ << "::static_type(SAL_UNUSED_PARAMETER void *) {\n";
+ inc();
+ out << indent() << "return ::cppu::UnoType< ";
+ dumpType(out, name_, false, false, true);
+ out << " >::get();\n";
+ dec();
+ out << "}\n\n#endif // "<< headerDefine << "\n";
+}
+
+void InterfaceType::dumpAttributes(FileStream & out) const
+{
+ if (!entity_->getDirectAttributes().empty()) {
+ out << "\n" << indent() << "// Attributes\n";
+ }
+ for (const unoidl::InterfaceTypeEntity::Attribute& attr : entity_->getDirectAttributes()) {
+ bool depr = m_isDeprecated || isDeprecated(attr.annotations);
+ out << indent();
+ dumpDeprecation(out, depr);
+ out << "virtual ";
+ dumpType(out, attr.type);
+ out << " SAL_CALL get" << attr.name << "() = 0;\n";
+ if (!attr.readOnly) {
+ bool byRef = passByReference(attr.type);
+ out << indent();
+ dumpDeprecation(out, depr);
+ out << "virtual void SAL_CALL set" << attr.name << "( ";
+ dumpType(out, attr.type, byRef, byRef);
+ out << " _" << attr.name.toAsciiLowerCase() << " ) = 0;\n";
+ }
+ }
+}
+
+void InterfaceType::dumpMethods(FileStream & out) const
+{
+ if (!entity_->getDirectMethods().empty()) {
+ out << "\n" << indent() << "// Methods\n";
+ }
+ for (const unoidl::InterfaceTypeEntity::Method& method : entity_->getDirectMethods()) {
+ out << indent();
+ dumpDeprecation(out, m_isDeprecated || isDeprecated(method.annotations));
+ out << "virtual ";
+ dumpType(out, method.returnType);
+ out << " SAL_CALL " << method.name << "(";
+ if (!method.parameters.empty()) {
+ out << " ";
+ for (std::vector< unoidl::InterfaceTypeEntity::Method::Parameter >::
+ const_iterator j(method.parameters.begin());
+ j != method.parameters.end();) {
+ bool isConst;
+ bool isRef;
+ if (j->direction
+ == unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_IN)
+ {
+ isConst = passByReference(j->type);
+ isRef = isConst;
+ } else {
+ isConst = false;
+ isRef = true;
+ }
+ dumpType(out, j->type, isConst, isRef);
+ out << " " << j->name;
+ ++j;
+ if (j != method.parameters.end()) {
+ out << ", ";
+ }
+ }
+ out << " ";
+ }
+ out << ") = 0;\n";
+ }
+}
+
+void InterfaceType::dumpNormalGetCppuType(FileStream & out)
+{
+ dumpGetCppuTypePreamble(out);
+ out << indent()
+ << "static typelib_TypeDescriptionReference * the_type = 0;\n"
+ << indent() << "if ( !the_type )\n" << indent() << "{\n";
+ inc();
+ std::vector< unoidl::AnnotatedReference >::size_type bases(
+ entity_->getDirectMandatoryBases().size());
+ if (bases == 1
+ && (entity_->getDirectMandatoryBases()[0].name
+ == "com.sun.star.uno.XInterface")) {
+ bases = 0;
+ }
+ if (bases != 0) {
+ out << indent() << "typelib_TypeDescriptionReference * aSuperTypes["
+ << entity_->getDirectMandatoryBases().size() << "];\n";
+ std::vector< unoidl::AnnotatedReference >::size_type n = 0;
+ for (const unoidl::AnnotatedReference& ar : entity_->getDirectMandatoryBases()) {
+ out << indent() << "aSuperTypes[" << n++ << "] = ::cppu::UnoType< ";
+ dumpType(out, ar.name, true, false, false, true);
+ out << " >::get().getTypeLibType();\n";
+ }
+ }
+ out << indent() << "typelib_static_mi_interface_type_init( &the_type, \""
+ << name_ << "\", " << bases << ", "
+ << (bases == 0 ? "0" : "aSuperTypes") << " );\n";
+ dec();
+ out << indent() << "}\n" << indent()
+ << ("return * reinterpret_cast< ::css::uno::Type * >("
+ " &the_type );\n");
+ dumpGetCppuTypePostamble(out);
+}
+
+void InterfaceType::dumpComprehensiveGetCppuType(FileStream & out)
+{
+ codemaker::cppumaker::dumpNamespaceOpen(out, name_, false);
+ OUString staticTypeClass("the" + id_ + "Type");
+ out << " namespace detail {\n\n" << indent() << "struct " << staticTypeClass
+ << " : public rtl::StaticWithInit< ::css::uno::Type *, "
+ << staticTypeClass << " >\n" << indent() << "{\n";
+ inc();
+ out << indent() << "::css::uno::Type * operator()() const\n"
+ << indent() << "{\n";
+ inc();
+ out << indent() << "::rtl::OUString sTypeName( \"" << name_ << "\" );\n\n"
+ << indent() << "// Start inline typedescription generation\n"
+ << indent() << "typelib_InterfaceTypeDescription * pTD = 0;\n\n";
+ out << indent() << "typelib_TypeDescriptionReference * aSuperTypes["
+ << entity_->getDirectMandatoryBases().size() << "];\n";
+ std::vector< unoidl::AnnotatedReference >::size_type n = 0;
+ for (const unoidl::AnnotatedReference& ar : entity_->getDirectMandatoryBases()) {
+ out << indent() << "aSuperTypes[" << n++ << "] = ::cppu::UnoType< ";
+ dumpType(out, ar.name, false, false, false, true);
+ out << " >::get().getTypeLibType();\n";
+ }
+ std::size_t count = entity_->getDirectAttributes().size()
+ + entity_->getDirectMethods().size(); //TODO: overflow
+ if (count != 0) {
+ out << indent() << "typelib_TypeDescriptionReference * pMembers["
+ << count << "] = { ";
+ for (std::size_t i = 0; i != count; ++i) {
+ out << "0";
+ if (i + 1 != count) {
+ out << ",";
+ }
+ }
+ out << " };\n";
+ sal_uInt32 index = 0;
+ dumpCppuAttributeRefs(out, index);
+ dumpCppuMethodRefs(out, index);
+ }
+ out << "\n" << indent() << "typelib_typedescription_newMIInterface(\n";
+ inc();
+ out << indent() << "&pTD,\n" << indent()
+ << "sTypeName.pData, 0, 0, 0, 0, 0,\n" << indent()
+ << entity_->getDirectMandatoryBases().size() << ", aSuperTypes,\n"
+ << indent() << count << ",\n" << indent()
+ << (count == 0 ? "0" : "pMembers") << " );\n\n";
+ dec();
+ out << indent()
+ << ("typelib_typedescription_register( (typelib_TypeDescription**)&pTD"
+ " );\n");
+ for (std::size_t i = 0; i != count; ++i) {
+ out << indent() << "typelib_typedescriptionreference_release( pMembers["
+ << i << "] );\n";
+ }
+ out << indent()
+ << ("typelib_typedescription_release( (typelib_TypeDescription*)pTD"
+ " );\n\n")
+ << indent() << "return new ::css::uno::Type( "
+ << getTypeClass(name_) << ", sTypeName ); // leaked\n";
+ dec();
+ out << indent() << "}\n";
+ dec();
+ out << indent() << "};\n\n";
+ codemaker::cppumaker::dumpNamespaceClose(out, name_, false);
+ out << " }\n\n";
+ dumpGetCppuTypePreamble(out);
+ out << indent() << "const ::css::uno::Type &rRet = *detail::"
+ << staticTypeClass << "::get();\n" << indent()
+ << "// End inline typedescription generation\n" << indent()
+ << "static bool bInitStarted = false;\n" << indent()
+ << "if (!bInitStarted)\n" << indent() << "{\n";
+ inc();
+ out << indent()
+ << "::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );\n"
+ << indent() << "if (!bInitStarted)\n" << indent() << "{\n";
+ inc();
+ out << indent() << "OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();\n"
+ << indent() << "bInitStarted = true;\n";
+ std::set< OUString > seen;
+ // Type for RuntimeException is always needed:
+ seen.insert("com.sun.star.uno.RuntimeException");
+ dumpCppuGetType(out, u"com.sun.star.uno.RuntimeException");
+ dumpAttributesCppuDecl(out, &seen);
+ dumpMethodsCppuDecl(out, &seen);
+ if (count != 0) {
+ sal_uInt32 index = getInheritedMemberCount();
+ dumpCppuAttributes(out, index);
+ dumpCppuMethods(out, index);
+ }
+ dec();
+ out << indent() << "}\n";
+ dec();
+ out << indent() << "}\n" << indent() << "else\n" << indent() << "{\n";
+ inc();
+ out << indent() << "OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();\n";
+ dec();
+ out << indent() << "}\n" << indent() << "return rRet;\n";
+ dumpGetCppuTypePostamble(out);
+}
+
+void InterfaceType::dumpCppuAttributeRefs(FileStream & out, sal_uInt32 & index)
+{
+ std::vector< unoidl::InterfaceTypeEntity::Attribute >::size_type n = 0;
+ for (const unoidl::InterfaceTypeEntity::Attribute& attr : entity_->getDirectAttributes()) {
+ out << indent() << "::rtl::OUString sAttributeName" << n << "( \""
+ << name_ << "::" << attr.name << "\" );\n" << indent()
+ << "typelib_typedescriptionreference_new( &pMembers[" << index++
+ << "],\n";
+ inc(38);
+ out << indent()
+ << "(typelib_TypeClass)::css::uno::TypeClass_INTERFACE_ATTRIBUTE,\n"
+ << indent() << "sAttributeName" << n << ".pData );\n";
+ dec(38);
+ ++n;
+ }
+}
+
+void InterfaceType::dumpCppuMethodRefs(FileStream & out, sal_uInt32 & index)
+{
+ std::vector< unoidl::InterfaceTypeEntity::Method >::size_type n = 0;
+ for (const unoidl::InterfaceTypeEntity::Method& method : entity_->getDirectMethods()) {
+ out << indent() << "::rtl::OUString sMethodName" << n << "( \"" << name_
+ << "::" << method.name << "\" );\n" << indent()
+ << "typelib_typedescriptionreference_new( &pMembers[" << index++
+ << "],\n";
+ inc(38);
+ out << indent()
+ << "(typelib_TypeClass)::css::uno::TypeClass_INTERFACE_METHOD,\n"
+ << indent() << "sMethodName" << n << ".pData );\n";
+ dec(38);
+ ++n;
+ }
+}
+
+void InterfaceType::addComprehensiveGetCppuTypeIncludes(
+ codemaker::cppumaker::Includes & includes) const
+{
+ // The comprehensive getCppuType method always includes a line
+ // "getCppuType( (const ::css::uno::RuntimeException*)0 );":
+ includes.addCppuUnotypeHxx();
+ includes.addRtlInstanceHxx(); // using rtl::StaticWithInit
+ includes.addOslMutexHxx();
+ includes.add("com.sun.star.uno.RuntimeException");
+}
+
+void InterfaceType::dumpCppuAttributes(FileStream & out, sal_uInt32 & index)
+{
+ if (entity_->getDirectAttributes().empty())
+ return;
+
+ out << "\n" << indent()
+ << "typelib_InterfaceAttributeTypeDescription * pAttribute = 0;\n";
+ std::vector< unoidl::InterfaceTypeEntity::Attribute >::size_type n = 0;
+ for (const unoidl::InterfaceTypeEntity::Attribute& attr : entity_->getDirectAttributes()) {
+ OUString type(resolveAllTypedefs(attr.type));
+ out << indent() << "{\n";
+ inc();
+ out << indent() << "::rtl::OUString sAttributeType" << n << "( \""
+ << type << "\" );\n" << indent()
+ << "::rtl::OUString sAttributeName" << n << "( \"" << name_
+ << "::" << attr.name << "\" );\n";
+ sal_Int32 getExcn = dumpExceptionTypeNames(
+ out, u"get", attr.getExceptions, false);
+ sal_Int32 setExcn = dumpExceptionTypeNames(
+ out, u"set", attr.setExceptions, false);
+ out << indent()
+ << ("typelib_typedescription_newExtendedInterfaceAttribute("
+ " &pAttribute,\n");
+ inc();
+ out << indent() << index++ << ", sAttributeName" << n
+ << ".pData,\n" << indent() << "(typelib_TypeClass)"
+ << getTypeClass(type) << ", sAttributeType" << n << ".pData,\n"
+ << indent() << "sal_" << (attr.readOnly ? "True" : "False")
+ << ", " << getExcn << ", "
+ << (getExcn == 0 ? "0" : "the_getExceptions") << ", " << setExcn
+ << ", " << (setExcn == 0 ? "0" : "the_setExceptions")
+ << " );\n";
+ dec();
+ out << indent()
+ << ("typelib_typedescription_register("
+ " (typelib_TypeDescription**)&pAttribute );\n");
+ dec();
+ out << indent() << "}\n";
+ ++n;
+ }
+ out << indent()
+ << ("typelib_typedescription_release("
+ " (typelib_TypeDescription*)pAttribute );\n");
+}
+
+void InterfaceType::dumpCppuMethods(FileStream & out, sal_uInt32 & index)
+{
+ if (entity_->getDirectMethods().empty())
+ return;
+
+ out << "\n" << indent()
+ << "typelib_InterfaceMethodTypeDescription * pMethod = 0;\n";
+ std::vector< unoidl::InterfaceTypeEntity::Method >::size_type n = 0;
+ for (const unoidl::InterfaceTypeEntity::Method& method : entity_->getDirectMethods()) {
+ OUString returnType(resolveAllTypedefs(method.returnType));
+ out << indent() << "{\n";
+ inc();
+ if (!method.parameters.empty()) {
+ out << indent() << "typelib_Parameter_Init aParameters["
+ << method.parameters.size() << "];\n";
+ }
+ std::vector< unoidl::InterfaceTypeEntity::Method::Parameter >::
+ size_type m = 0;
+ for (const unoidl::InterfaceTypeEntity::Method::Parameter& param : method.parameters) {
+ OUString type(resolveAllTypedefs(param.type));
+ out << indent() << "::rtl::OUString sParamName" << m << "( \""
+ << param.name << "\" );\n" << indent()
+ << "::rtl::OUString sParamType" << m << "( \"" << type
+ << "\" );\n" << indent() << "aParameters[" << m
+ << "].pParamName = sParamName" << m << ".pData;\n"
+ << indent() << "aParameters[" << m
+ << "].eTypeClass = (typelib_TypeClass)"
+ << getTypeClass(type) << ";\n" << indent() << "aParameters["
+ << m << "].pTypeName = sParamType" << m << ".pData;\n"
+ << indent() << "aParameters[" << m << "].bIn = "
+ << ((param.direction
+ == unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_OUT)
+ ? "sal_False" : "sal_True")
+ << ";\n" << indent() << "aParameters[" << m << "].bOut = "
+ << ((param.direction
+ == unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_IN)
+ ? "sal_False" : "sal_True")
+ << ";\n";
+ ++m;
+ }
+ sal_Int32 excn = dumpExceptionTypeNames(
+ out, u"", method.exceptions,
+ method.name != "acquire" && method.name != "release");
+ out << indent() << "::rtl::OUString sReturnType" << n << "( \""
+ << returnType << "\" );\n" << indent()
+ << "::rtl::OUString sMethodName" << n << "( \"" << name_ << "::"
+ << method.name << "\" );\n" << indent()
+ << "typelib_typedescription_newInterfaceMethod( &pMethod,\n";
+ inc();
+ out << indent() << index++ << ", sal_False,\n" << indent()
+ << "sMethodName" << n << ".pData,\n" << indent()
+ << "(typelib_TypeClass)" << getTypeClass(returnType)
+ << ", sReturnType" << n << ".pData,\n" << indent()
+ << method.parameters.size() << ", "
+ << (method.parameters.empty() ? "0" : "aParameters") << ",\n"
+ << indent() << excn << ", "
+ << (excn == 0 ? "0" : "the_Exceptions") << " );\n";
+ dec();
+ out << indent()
+ << ("typelib_typedescription_register("
+ " (typelib_TypeDescription**)&pMethod );\n");
+ dec();
+ out << indent() << "}\n";
+ ++n;
+ }
+ out << indent()
+ << ("typelib_typedescription_release("
+ " (typelib_TypeDescription*)pMethod );\n");
+}
+
+void InterfaceType::dumpAttributesCppuDecl(
+ FileStream & out, std::set< OUString > * seen) const
+{
+ assert(seen != nullptr);
+ for (const unoidl::InterfaceTypeEntity::Attribute& attr : entity_->getDirectAttributes()) {
+ if (seen->insert(attr.type).second) {
+ dumpCppuGetType(out, attr.type);
+ }
+ for (const OUString& exc : attr.getExceptions) {
+ if (seen->insert(exc).second) {
+ dumpCppuGetType(out, exc);
+ }
+ }
+ for (const OUString& exc : attr.setExceptions) {
+ if (seen->insert(exc).second) {
+ dumpCppuGetType(out, exc);
+ }
+ }
+ }
+}
+
+void InterfaceType::dumpMethodsCppuDecl(
+ FileStream & out, std::set< OUString > * seen) const
+{
+ assert(seen != nullptr);
+ for (const unoidl::InterfaceTypeEntity::Method& method : entity_->getDirectMethods()) {
+ for (const OUString& ex : method.exceptions) {
+ if (seen->insert(ex).second) {
+ dumpCppuGetType(out, ex);
+ }
+ }
+ }
+}
+
+void InterfaceType::dumpExceptionTypeName(
+ FileStream & out, std::u16string_view prefix, sal_uInt32 index,
+ std::u16string_view name) const
+{
+ out << indent() << "::rtl::OUString the_" << prefix << "ExceptionName"
+ << index << "( \"" << name << "\" );\n";
+}
+
+sal_Int32 InterfaceType::dumpExceptionTypeNames(
+ FileStream & out, std::u16string_view prefix,
+ std::vector< OUString > const & exceptions, bool runtimeException) const
+{
+ sal_Int32 count = 0;
+ for (const OUString& ex : exceptions) {
+ if (ex != "com.sun.star.uno.RuntimeException") {
+ dumpExceptionTypeName(out, prefix, count++, ex);
+ }
+ }
+ if (runtimeException) {
+ dumpExceptionTypeName(
+ out, prefix, count++, u"com.sun.star.uno.RuntimeException");
+ }
+ if (count != 0) {
+ out << indent() << "rtl_uString * the_" << prefix << "Exceptions[] = {";
+ for (sal_Int32 i = 0; i != count; ++i) {
+ out << (i == 0 ? " " : ", ") << "the_" << prefix << "ExceptionName"
+ << i << ".pData";
+ }
+ out << " };\n";
+ }
+ return count;
+}
+
+class ConstantGroup: public CppuType
+{
+public:
+ ConstantGroup(
+ rtl::Reference< unoidl::ConstantGroupEntity > const & entity,
+ OUString const & name, rtl::Reference< TypeManager > const & typeMgr):
+ CppuType(name, typeMgr), entity_(entity) {
+ assert(entity.is());
+ }
+
+ bool hasConstants() const {
+ return !entity_->getMembers().empty();
+ }
+
+private:
+ virtual void dumpHdlFile(
+ FileStream & out, codemaker::cppumaker::Includes & includes) override;
+
+ virtual void dumpHppFile(
+ FileStream & out, codemaker::cppumaker::Includes & includes) override;
+
+ virtual void dumpDeclaration(FileStream & out) override;
+
+ rtl::Reference< unoidl::ConstantGroupEntity > entity_;
+};
+
+void ConstantGroup::dumpHdlFile(
+ FileStream & out, codemaker::cppumaker::Includes & includes)
+{
+ OUString headerDefine(dumpHeaderDefine(out, u"HDL"));
+ out << "\n";
+ addDefaultHIncludes(includes);
+ includes.dump(out, nullptr, true);
+ out << "\n";
+ if (codemaker::cppumaker::dumpNamespaceOpen(out, name_, true)) {
+ out << "\n";
+ }
+ out << "\n";
+ dumpDeclaration(out);
+ out << "\n";
+ if (codemaker::cppumaker::dumpNamespaceClose(out, name_, true)) {
+ out << "\n";
+ }
+ out << "\n#endif // "<< headerDefine << "\n";
+}
+
+void ConstantGroup::dumpHppFile(
+ FileStream & out, codemaker::cppumaker::Includes &)
+{
+ OUString headerDefine(dumpHeaderDefine(out, u"HPP"));
+ out << "\n";
+ codemaker::cppumaker::Includes::dumpInclude(out, u2b(name_), false);
+ out << "\n#endif // "<< headerDefine << "\n";
+}
+
+void ConstantGroup::dumpDeclaration(FileStream & out)
+{
+ for (const unoidl::ConstantGroupEntity::Member& member : entity_->getMembers()) {
+ out << "static const ";
+ switch (member.value.type) {
+ case unoidl::ConstantValue::TYPE_BOOLEAN:
+ out << "::sal_Bool";
+ break;
+ case unoidl::ConstantValue::TYPE_BYTE:
+ out << "::sal_Int8";
+ break;
+ case unoidl::ConstantValue::TYPE_SHORT:
+ out << "::sal_Int16";
+ break;
+ case unoidl::ConstantValue::TYPE_UNSIGNED_SHORT:
+ out << "::sal_uInt16";
+ break;
+ case unoidl::ConstantValue::TYPE_LONG:
+ out << "::sal_Int32";
+ break;
+ case unoidl::ConstantValue::TYPE_UNSIGNED_LONG:
+ out << "::sal_uInt32";
+ break;
+ case unoidl::ConstantValue::TYPE_HYPER:
+ out << "::sal_Int64";
+ break;
+ case unoidl::ConstantValue::TYPE_UNSIGNED_HYPER:
+ out << "::sal_uInt64";
+ break;
+ case unoidl::ConstantValue::TYPE_FLOAT:
+ out << "float";
+ break;
+ case unoidl::ConstantValue::TYPE_DOUBLE:
+ out << "double";
+ break;
+ }
+ out << " " << member.name << " = ";
+ switch (member.value.type) {
+ case unoidl::ConstantValue::TYPE_BOOLEAN:
+ out << (member.value.booleanValue ? "sal_True" : "sal_False");
+ break;
+ case unoidl::ConstantValue::TYPE_BYTE:
+ out << "(sal_Int8)" << OUString::number(member.value.byteValue);
+ break;
+ case unoidl::ConstantValue::TYPE_SHORT:
+ out << "(sal_Int16)" << OUString::number(member.value.shortValue);
+ break;
+ case unoidl::ConstantValue::TYPE_UNSIGNED_SHORT:
+ out << "(sal_uInt16)"
+ << OUString::number(member.value.unsignedShortValue);
+ break;
+ case unoidl::ConstantValue::TYPE_LONG:
+ // Avoid C++ compiler warnings about (un)signedness of literal
+ // -2^31:
+ if (member.value.longValue == SAL_MIN_INT32) {
+ out << "SAL_MIN_INT32";
+ } else {
+ out << "(sal_Int32)" << OUString::number(member.value.longValue);
+ }
+ break;
+ case unoidl::ConstantValue::TYPE_UNSIGNED_LONG:
+ out << "(sal_uInt32)"
+ << OUString::number(member.value.unsignedLongValue) << "U";
+ break;
+ case unoidl::ConstantValue::TYPE_HYPER:
+ // Avoid C++ compiler warnings about (un)signedness of literal
+ // -2^63:
+ if (member.value.hyperValue == SAL_MIN_INT64) {
+ out << "SAL_MIN_INT64";
+ } else {
+ out << "(sal_Int64) SAL_CONST_INT64("
+ << OUString::number(member.value.hyperValue) << ")";
+ }
+ break;
+ case unoidl::ConstantValue::TYPE_UNSIGNED_HYPER:
+ out << "SAL_CONST_UINT64("
+ << OUString::number(member.value.unsignedHyperValue) << ")";
+ break;
+ case unoidl::ConstantValue::TYPE_FLOAT:
+ out << "(float)" << OUString::number(member.value.floatValue);
+ break;
+ case unoidl::ConstantValue::TYPE_DOUBLE:
+ out << "(double)" << OUString::number(member.value.doubleValue);
+ break;
+ }
+ out << ";\n";
+ }
+}
+
+void dumpTypeParameterName(FileStream & out, std::u16string_view name)
+{
+ // Prefix all type parameters with "typeparam_" to avoid problems when a
+ // struct member has the same name as a type parameter, as in
+ // struct<T> { T T; };
+ out << "typeparam_" << name;
+}
+
+class PlainStructType: public CppuType
+{
+public:
+ PlainStructType(
+ rtl::Reference< unoidl::PlainStructTypeEntity > const & entity,
+ OUString const & name, rtl::Reference< TypeManager > const & typeMgr):
+ CppuType(name, typeMgr), entity_(entity) {
+ assert(entity.is());
+ }
+
+private:
+ virtual sal_uInt32 checkInheritedMemberCount() const override {
+ return getTotalMemberCount(entity_->getDirectBase());
+ }
+
+ virtual void dumpDeclaration(FileStream& o) override;
+
+ void dumpHppFile(FileStream& o, codemaker::cppumaker::Includes & includes) override;
+
+ virtual void dumpLightGetCppuType(FileStream & out) override;
+
+ virtual void dumpNormalGetCppuType(FileStream & out) override;
+
+ virtual void dumpComprehensiveGetCppuType(FileStream & out) override;
+
+ virtual void addLightGetCppuTypeIncludes(
+ codemaker::cppumaker::Includes & includes) const override;
+
+ virtual void addNormalGetCppuTypeIncludes(
+ codemaker::cppumaker::Includes & includes) const override;
+
+ virtual void addComprehensiveGetCppuTypeIncludes(
+ codemaker::cppumaker::Includes & includes) const override;
+
+ bool dumpBaseMembers(
+ FileStream & out, OUString const & base, bool withType);
+
+ sal_uInt32 getTotalMemberCount(OUString const & base) const;
+
+ rtl::Reference< unoidl::PlainStructTypeEntity > entity_;
+};
+
+void PlainStructType::dumpDeclaration(FileStream & out)
+{
+ out << "\n#ifdef _WIN32\n# pragma pack(push, 8)\n#endif\n\n" << indent();
+ out << "struct SAL_DLLPUBLIC_RTTI ";
+ if (canBeWarnUnused(name_))
+ out << "SAL_WARN_UNUSED ";
+ out << id_;
+ OUString base(entity_->getDirectBase());
+ if (!base.isEmpty()) {
+ out << ": public " << codemaker::cpp::scopedCppName(u2b(base));
+ }
+ out << " {\n";
+ inc();
+ out << indent() << "inline " << id_ << "();\n";
+ if (!entity_->getDirectMembers().empty() || getInheritedMemberCount() > 0) {
+ out << "\n" << indent() << "inline " << id_ << "(";
+ bool bFirst = !dumpBaseMembers(out, base, true);
+ for (const unoidl::PlainStructTypeEntity::Member& member : entity_->getDirectMembers()) {
+ if (!bFirst) {
+ out << ", ";
+ }
+ dumpType(out, member.type, true, true);
+ out << " " << member.name << "_";
+ bFirst = false;
+ }
+ out << ");\n";
+ }
+ if (!entity_->getDirectMembers().empty()) {
+ out << "\n";
+ for (std::vector< unoidl::PlainStructTypeEntity::Member >::
+ const_iterator i(entity_->getDirectMembers().begin());
+ i != entity_->getDirectMembers().end(); ++i) {
+ out << indent();
+ dumpType(out, i->type);
+ out << " " << i->name;
+ if (i == entity_->getDirectMembers().begin() && !base.isEmpty()
+ && i->type != "hyper" && i->type != "unsigned hyper"
+ && i->type != "double") {
+ out << " CPPU_GCC3_ALIGN("
+ << codemaker::cpp::scopedCppName(u2b(base)) << ")";
+ }
+ out << ";\n";
+ }
+ }
+ dec();
+ out << "};\n\n#ifdef _WIN32\n# pragma pack(pop)\n#endif\n\n";
+}
+
+void PlainStructType::dumpHppFile(
+ FileStream & out, codemaker::cppumaker::Includes & includes)
+{
+ OUString headerDefine(dumpHeaderDefine(out, u"HPP"));
+ out << "\n";
+ includes.dump(out, &name_, true);
+ out << "\n";
+ if (codemaker::cppumaker::dumpNamespaceOpen(out, name_, false)) {
+ out << "\n";
+ }
+ out << "\ninline " << id_ << "::" << id_ << "()\n";
+ inc();
+ OUString base(entity_->getDirectBase());
+ bool bFirst = true;
+ if (!base.isEmpty()) {
+ out << indent() << ": " << codemaker::cpp::scopedCppName(u2b(base))
+ << "()\n";
+ bFirst = false;
+ }
+ for (const unoidl::PlainStructTypeEntity::Member& member : entity_->getDirectMembers()) {
+ out << indent() << (bFirst ? ":" : ",") << " " << member.name;
+ dumpInitializer(out, false, member.type);
+ out << "\n";
+ bFirst = false;
+ }
+ dec();
+ out << "{\n}\n\n";
+ if (!entity_->getDirectMembers().empty() || getInheritedMemberCount() > 0) {
+ out << "inline " << id_;
+ out << "::" << id_ << "(";
+ bFirst = !dumpBaseMembers(out, base, true);
+ for (const unoidl::PlainStructTypeEntity::Member& member : entity_->getDirectMembers()) {
+ if (!bFirst) {
+ out << ", ";
+ }
+ dumpType(out, member.type, true, true);
+ out << " " << member.name << "_";
+ bFirst = false;
+ }
+ out << ")\n";
+ inc();
+ bFirst = true;
+ if (!base.isEmpty()) {
+ out << indent() << ": " << codemaker::cpp::scopedCppName(u2b(base))
+ << "(";
+ dumpBaseMembers(out, base, false);
+ out << ")\n";
+ bFirst = false;
+ }
+ for (const unoidl::PlainStructTypeEntity::Member& member : entity_->getDirectMembers()) {
+ out << indent() << (bFirst ? ":" : ",") << " " << member.name << "("
+ << member.name << "_)\n";
+ bFirst = false;
+ }
+ dec();
+ out << "{\n}\n\n";
+ }
+ // print the operator==
+ out << "\ninline bool operator==(const " << id_ << "& the_lhs, const " << id_ << "& the_rhs)\n";
+ out << "{\n";
+ inc();
+ out << indent() << "return ";
+ bFirst = true;
+ if (!base.isEmpty()) {
+ out << "operator==( static_cast< " << codemaker::cpp::scopedCppName(u2b(base))
+ << ">(the_lhs), static_cast< " << codemaker::cpp::scopedCppName(u2b(base)) << ">(the_rhs) )\n";
+ bFirst = false;
+ }
+ for (const unoidl::PlainStructTypeEntity::Member& member : entity_->getDirectMembers()) {
+ if (!bFirst)
+ out << "\n" << indent() << indent() << "&& ";
+ out << "the_lhs." << member.name << " == the_rhs." << member.name;
+ bFirst = false;
+ }
+ out << ";\n";
+ dec();
+ out << "}\n";
+ // print the operator!=
+ out << "\ninline bool operator!=(const " << id_ << "& the_lhs, const " << id_ << "& the_rhs)\n";
+ out << "{\n";
+ out << indent() << "return !operator==(the_lhs, the_rhs);\n";
+ out << "}\n";
+ // close namespace
+ if (codemaker::cppumaker::dumpNamespaceClose(out, name_, false)) {
+ out << "\n";
+ }
+ out << "\n";
+ dumpGetCppuType(out);
+ out << "\n#endif // "<< headerDefine << "\n";
+}
+
+void PlainStructType::dumpLightGetCppuType(FileStream & out)
+{
+ dumpGetCppuTypePreamble(out);
+ out << indent()
+ << ("//TODO: On certain platforms with weak memory models, the"
+ " following code can result in some threads observing that the_type"
+ " points to garbage\n")
+ << indent()
+ << "static ::typelib_TypeDescriptionReference * the_type = 0;\n"
+ << indent() << "if (the_type == 0) {\n";
+ inc();
+ out << indent() << "::typelib_static_type_init(&the_type, "
+ << getTypeClass(name_, true) << ", \"" << name_ << "\");\n";
+ dec();
+ out << indent() << "}\n" << indent()
+ << "return *reinterpret_cast< ::css::uno::Type * >(&the_type);\n";
+ dumpGetCppuTypePostamble(out);
+}
+
+void PlainStructType::dumpNormalGetCppuType(FileStream & out)
+{
+ dumpGetCppuTypePreamble(out);
+ out << indent()
+ << ("//TODO: On certain platforms with weak memory models, the"
+ " following code can result in some threads observing that the_type"
+ " points to garbage\n")
+ << indent()
+ << "static ::typelib_TypeDescriptionReference * the_type = 0;\n"
+ << indent() << "if (the_type == 0) {\n";
+ inc();
+ out << indent()
+ << "::typelib_TypeDescriptionReference * the_members[] = {\n";
+ inc();
+ for (std::vector< unoidl::PlainStructTypeEntity::Member >::const_iterator i(
+ entity_->getDirectMembers().begin());
+ i != entity_->getDirectMembers().end();) {
+ out << indent() << "::cppu::UnoType< ";
+ dumpType(out, i->type, false, false, false, true);
+ ++i;
+ out << " >::get().getTypeLibType()"
+ << (i == entity_->getDirectMembers().end() ? " };" : ",") << "\n";
+ }
+ dec();
+ out << indent() << "::typelib_static_struct_type_init(&the_type, \""
+ << name_ << "\", ";
+ if (entity_->getDirectBase().isEmpty()) {
+ out << "0";
+ } else {
+ out << "::cppu::UnoType< ";
+ dumpType(out, entity_->getDirectBase(), false, false, false, true);
+ out << " >::get().getTypeLibType()";
+ }
+ out << ", " << entity_->getDirectMembers().size() << ", the_members, 0);\n";
+ dec();
+ out << indent() << "}\n" << indent()
+ << "return *reinterpret_cast< ::css::uno::Type * >(&the_type);\n";
+ dumpGetCppuTypePostamble(out);
+}
+
+void PlainStructType::dumpComprehensiveGetCppuType(FileStream & out)
+{
+ OUString staticTypeClass("the" + id_ + "Type");
+ codemaker::cppumaker::dumpNamespaceOpen(out, name_, false);
+ out << " namespace detail {\n\n" << indent() << "struct "
+ << staticTypeClass
+ << " : public rtl::StaticWithInit< ::css::uno::Type *, "
+ << staticTypeClass << " >\n" << indent() << "{\n";
+ inc();
+ out << indent() << "::css::uno::Type * operator()() const\n"
+ << indent() << "{\n";
+ inc();
+ out << indent() << "::rtl::OUString the_name( \"" << name_ << "\" );\n";
+ std::map< OUString, sal_uInt32 > types;
+ std::vector< unoidl::PlainStructTypeEntity::Member >::size_type n = 0;
+ for (const unoidl::PlainStructTypeEntity::Member& member : entity_->getDirectMembers()) {
+ if (types.emplace(
+ member.type, static_cast< sal_uInt32 >(types.size())).
+ second) {
+ dumpCppuGetType(out, member.type, &name_);
+ // For typedefs, use the resolved type name, as there will be no
+ // information available about the typedef itself at runtime (the
+ // above getCppuType call will make available information about the
+ // resolved type); no extra #include for the resolved type is
+ // needed, as the header for the typedef includes it already:
+ out << indent() << "::rtl::OUString the_tname"
+ << static_cast< sal_uInt32 >(types.size() - 1) << "( \""
+ << resolveAllTypedefs(member.type) << "\" );\n";
+ }
+ out << indent() << "::rtl::OUString the_name" << n++ << "( \""
+ << member.name << "\" );\n";
+ }
+ out << indent() << "::typelib_StructMember_Init the_members[] = {\n";
+ inc();
+ n = 0;
+ for (std::vector< unoidl::PlainStructTypeEntity::Member >::const_iterator i(
+ entity_->getDirectMembers().begin());
+ i != entity_->getDirectMembers().end();) {
+ out << indent() << "{ { " << getTypeClass(i->type, true)
+ << ", the_tname" << types.find(i->type)->second
+ << ".pData, the_name" << n++ << ".pData }, false }";
+ ++i;
+ out << (i == entity_->getDirectMembers().end() ? " };" : ",") << "\n";
+ }
+ dec();
+ out << indent() << "::typelib_TypeDescription * the_newType = 0;\n"
+ << indent()
+ << "::typelib_typedescription_newStruct(&the_newType, the_name.pData, ";
+ if (entity_->getDirectBase().isEmpty()) {
+ out << "0";
+ } else {
+ out << "::cppu::UnoType< ";
+ dumpType(out, entity_->getDirectBase(), false, false, false, true);
+ out << " >::get().getTypeLibType()";
+ }
+ out << ", " << entity_->getDirectMembers().size() << ", the_members);\n"
+ << indent() << "::typelib_typedescription_register(&the_newType);\n"
+ << indent() << "::typelib_typedescription_release(the_newType);\n"
+ << indent() << "return new ::css::uno::Type("
+ << getTypeClass(name_) << ", the_name); // leaked\n";
+ dec();
+ out << indent() << "}\n";
+ dec();
+ out << indent() << "};\n";
+ codemaker::cppumaker::dumpNamespaceClose(out, name_, false);
+ out << " }\n\n";
+ dumpGetCppuTypePreamble(out);
+ out << indent() << "return *detail::" << staticTypeClass << "::get();\n";
+ dumpGetCppuTypePostamble(out);
+}
+
+bool PlainStructType::dumpBaseMembers(
+ FileStream & out, OUString const & base, bool withType)
+{
+ if (base.isEmpty())
+ return false;
+
+ rtl::Reference< unoidl::Entity > ent;
+ codemaker::UnoType::Sort sort = m_typeMgr->getSort(base, &ent);
+ if (sort != codemaker::UnoType::Sort::PlainStruct) {
+ throw CannotDumpException(
+ "plain struct type base " + base
+ + " is not a plain struct type");
+ }
+ rtl::Reference< unoidl::PlainStructTypeEntity > ent2(
+ dynamic_cast< unoidl::PlainStructTypeEntity * >(ent.get()));
+ assert(ent2.is());
+ if (!ent2.is()) {
+ return false;
+ }
+ bool hasMember = dumpBaseMembers(out, ent2->getDirectBase(), withType);
+ for (const unoidl::PlainStructTypeEntity::Member& member : ent2->getDirectMembers()) {
+ if (hasMember) {
+ out << ", ";
+ }
+ if (withType) {
+ dumpType(out, member.type, true, true);
+ out << " ";
+ }
+ out << member.name << "_";
+ hasMember = true;
+ }
+ return hasMember;
+}
+
+void PlainStructType::addLightGetCppuTypeIncludes(
+ codemaker::cppumaker::Includes & includes) const
+{
+ includes.addType();
+ includes.addCppuUnotypeHxx();
+ includes.addSalTypesH();
+ includes.addTypelibTypeclassH();
+ includes.addTypelibTypedescriptionH();
+}
+
+void PlainStructType::addNormalGetCppuTypeIncludes(
+ codemaker::cppumaker::Includes & includes) const
+{
+ includes.addType();
+ includes.addCppuUnotypeHxx();
+ includes.addSalTypesH();
+ includes.addTypelibTypeclassH();
+ includes.addTypelibTypedescriptionH();
+}
+
+void PlainStructType::addComprehensiveGetCppuTypeIncludes(
+ codemaker::cppumaker::Includes & includes) const
+{
+ includes.addType();
+ includes.addCppuUnotypeHxx();
+ includes.addRtlInstanceHxx();
+ includes.addRtlUstringH();
+ includes.addRtlUstringHxx();
+ includes.addSalTypesH();
+ includes.addTypelibTypeclassH();
+ includes.addTypelibTypedescriptionH();
+}
+
+sal_uInt32 PlainStructType::getTotalMemberCount(OUString const & base) const
+{
+ if (base.isEmpty()) {
+ return 0;
+ }
+ rtl::Reference< unoidl::Entity > ent;
+ codemaker::UnoType::Sort sort = m_typeMgr->getSort(base, &ent);
+ if (sort != codemaker::UnoType::Sort::PlainStruct) {
+ throw CannotDumpException(
+ "plain struct type base " + base + " is not a plain struct type");
+ }
+ rtl::Reference< unoidl::PlainStructTypeEntity > ent2(
+ dynamic_cast< unoidl::PlainStructTypeEntity * >(ent.get()));
+ assert(ent2.is());
+ if (!ent2.is()) {
+ return 0;
+ }
+ return getTotalMemberCount(ent2->getDirectBase())
+ + ent2->getDirectMembers().size(); //TODO: overflow
+}
+
+class PolyStructType: public CppuType
+{
+public:
+ PolyStructType(
+ rtl::Reference< unoidl::PolymorphicStructTypeTemplateEntity > const &
+ entity,
+ OUString const & name, rtl::Reference< TypeManager > const & typeMgr):
+ CppuType(name, typeMgr), entity_(entity) {
+ assert(entity.is());
+ }
+
+private:
+ virtual void dumpDeclaration(FileStream& o) override;
+
+ void dumpHppFile(FileStream& o, codemaker::cppumaker::Includes & includes) override;
+
+ virtual void dumpLightGetCppuType(FileStream & out) override;
+
+ virtual void dumpNormalGetCppuType(FileStream & out) override;
+
+ virtual void dumpComprehensiveGetCppuType(FileStream & out) override;
+
+ virtual void addLightGetCppuTypeIncludes(
+ codemaker::cppumaker::Includes & includes) const override;
+
+ virtual void addNormalGetCppuTypeIncludes(
+ codemaker::cppumaker::Includes & includes) const override;
+
+ virtual void addComprehensiveGetCppuTypeIncludes(
+ codemaker::cppumaker::Includes & includes) const override;
+
+ virtual bool isPolymorphic() const override {
+ return true;
+ }
+
+ virtual void dumpTemplateHead(FileStream & out) const override;
+
+ virtual void dumpTemplateParameters(FileStream & out) const override;
+
+ rtl::Reference< unoidl::PolymorphicStructTypeTemplateEntity > entity_;
+};
+
+void PolyStructType::dumpDeclaration(FileStream & out)
+{
+ out << "\n#ifdef _WIN32\n# pragma pack(push, 8)\n#endif\n\n" << indent();
+ dumpTemplateHead(out);
+ out << "struct SAL_DLLPUBLIC_RTTI " << id_ << " {\n";
+ inc();
+ out << indent() << "inline " << id_ << "();\n";
+ if (!entity_->getMembers().empty()) {
+ out << "\n" << indent() << "inline " << id_ << "(";
+ for (std::vector<
+ unoidl::PolymorphicStructTypeTemplateEntity::Member >::
+ const_iterator i(entity_->getMembers().begin());
+ i != entity_->getMembers().end(); ++i) {
+ if (i != entity_->getMembers().begin()) {
+ out << ", ";
+ }
+ if (i->parameterized) {
+ dumpTypeParameterName(out, i->type);
+ out << " const &";
+ } else {
+ dumpType(out, i->type, true, true);
+ }
+ out << " " << i->name << "_";
+ }
+ out << ");\n\n";
+ // print the member fields
+ for (const unoidl::PolymorphicStructTypeTemplateEntity::Member& member :
+ entity_->getMembers()) {
+ out << indent();
+ if (member.parameterized) {
+ dumpTypeParameterName(out, member.type);
+ } else {
+ dumpType(out, member.type);
+ }
+ out << " " << member.name << ";\n";
+ }
+ }
+ dec();
+ out << "};\n\n#ifdef _WIN32\n# pragma pack(pop)\n#endif\n\n";
+}
+
+void PolyStructType::dumpHppFile(
+ FileStream & out, codemaker::cppumaker::Includes & includes)
+{
+ OUString headerDefine(dumpHeaderDefine(out, u"HPP"));
+ out << "\n";
+ includes.dump(out, &name_, true);
+ out << "\n";
+ if (codemaker::cppumaker::dumpNamespaceOpen(out, name_, false)) {
+ out << "\n";
+ }
+ out << "\n";
+ // dump default (no-arg) constructor
+ dumpTemplateHead(out);
+ out << "inline " << id_;
+ dumpTemplateParameters(out);
+ out << "::" << id_ << "()\n";
+ inc();
+ for (std::vector< unoidl::PolymorphicStructTypeTemplateEntity::Member >::
+ const_iterator i(entity_->getMembers().begin());
+ i != entity_->getMembers().end(); ++i) {
+ out << indent() << (i == entity_->getMembers().begin() ? ":" : ",")
+ << " " << i->name;
+ dumpInitializer(out, i->parameterized, i->type);
+ out << "\n";
+ }
+ dec();
+ out << "{\n}\n\n";
+ if (!entity_->getMembers().empty()) {
+ // dump takes-all-fields constructor
+ dumpTemplateHead(out);
+ out << "inline " << id_;
+ dumpTemplateParameters(out);
+ out << "::" << id_ << "(";
+ for (std::vector<
+ unoidl::PolymorphicStructTypeTemplateEntity::Member >::
+ const_iterator i(entity_->getMembers().begin());
+ i != entity_->getMembers().end(); ++i) {
+ if (i != entity_->getMembers().begin()) {
+ out << ", ";
+ }
+ if (i->parameterized) {
+ dumpTypeParameterName(out, i->type);
+ out << " const &";
+ } else {
+ dumpType(out, i->type, true, true);
+ }
+ out << " " << i->name << "_";
+ }
+ out << ")\n";
+ inc();
+ for (std::vector<
+ unoidl::PolymorphicStructTypeTemplateEntity::Member >::
+ const_iterator i(entity_->getMembers().begin());
+ i != entity_->getMembers().end(); ++i) {
+ out << indent() << (i == entity_->getMembers().begin() ? ":" : ",")
+ << " " << i->name << "(" << i->name << "_)\n";
+ }
+ dec();
+ out << "{\n}\n\n" << indent();
+ // dump make_T method
+ dumpTemplateHead(out);
+ out << "\n" << indent() << "inline " << id_;
+ dumpTemplateParameters(out);
+ out << "\n" << indent() << "make_" << id_ << "(";
+ for (std::vector<
+ unoidl::PolymorphicStructTypeTemplateEntity::Member >::
+ const_iterator i(entity_->getMembers().begin());
+ i != entity_->getMembers().end(); ++i) {
+ if (i != entity_->getMembers().begin()) {
+ out << ", ";
+ }
+ if (i->parameterized) {
+ dumpTypeParameterName(out, i->type);
+ out << " const &";
+ } else {
+ dumpType(out, i->type, true, true);
+ }
+ out << " " << i->name << "_";
+ }
+ out << ")\n" << indent() << "{\n";
+ inc();
+ out << indent() << "return " << id_;
+ dumpTemplateParameters(out);
+ out << "(";
+ for (std::vector<
+ unoidl::PolymorphicStructTypeTemplateEntity::Member >::
+ const_iterator i(entity_->getMembers().begin());
+ i != entity_->getMembers().end(); ++i) {
+ if (i != entity_->getMembers().begin()) {
+ out << ", ";
+ }
+ out << i->name << "_";
+ }
+ out << ");\n";
+ dec();
+ out << indent() << "}\n\n";
+ }
+ // print the operator==
+ dumpTemplateHead(out);
+ out << " inline bool operator==(const " << id_;
+ dumpTemplateParameters(out);
+ out << "& the_lhs, const " << id_;
+ dumpTemplateParameters(out);
+ out << "& the_rhs)\n";
+ out << "{\n";
+ inc();
+ out << indent() << "return ";
+ bool bFirst = true;
+ for (const unoidl::PolymorphicStructTypeTemplateEntity::Member& member : entity_->getMembers()) {
+ if (!bFirst)
+ out << "\n" << indent() << indent() << "&& ";
+ out << "the_lhs." << member.name << " == the_rhs." << member.name;
+ bFirst = false;
+ }
+ out << ";\n";
+ dec();
+ out << "}\n";
+ // print the operator!=
+ dumpTemplateHead(out);
+ out << " inline bool operator!=(const " << id_;
+ dumpTemplateParameters(out);
+ out << "& the_lhs, const " << id_;
+ dumpTemplateParameters(out);
+ out << "& the_rhs)\n";
+ out << "{\n";
+ out << indent() << "return !operator==(the_lhs, the_rhs);\n";
+ out << "}\n";
+ // close namespace
+ if (codemaker::cppumaker::dumpNamespaceClose(out, name_, false)) {
+ out << "\n";
+ }
+ out << "\n";
+ dumpGetCppuType(out);
+ out << "\n#endif // "<< headerDefine << "\n";
+}
+
+void PolyStructType::dumpLightGetCppuType(FileStream & out)
+{
+ dumpGetCppuTypePreamble(out);
+ out << indent()
+ << ("//TODO: On certain platforms with weak memory models, the"
+ " following code can result in some threads observing that the_type"
+ " points to garbage\n")
+ << indent()
+ << "static ::typelib_TypeDescriptionReference * the_type = 0;\n"
+ << indent() << "if (the_type == 0) {\n";
+ inc();
+
+ out << "#ifdef LIBO_INTERNAL_ONLY\n";
+
+ out << indent() << "::rtl::OString the_buffer = \"" << name_
+ << "<\" +\n";
+ for (std::vector< OUString >::const_iterator i(
+ entity_->getTypeParameters().begin());
+ i != entity_->getTypeParameters().end();) {
+ out << indent()
+ << ("::rtl::OUStringToOString("
+ "::cppu::getTypeFavourChar(static_cast< ");
+ dumpTypeParameterName(out, *i);
+ out << " * >(0)).getTypeName(), RTL_TEXTENCODING_UTF8) +\n";
+ ++i;
+ if (i != entity_->getTypeParameters().end()) {
+ out << indent() << "\",\" +\n";
+ }
+ }
+ out << indent() << "\">\";\n";
+
+ out << "#else\n";
+
+ out << indent() << "::rtl::OStringBuffer the_buffer(\"" << name_
+ << "<\");\n";
+ for (std::vector< OUString >::const_iterator i(
+ entity_->getTypeParameters().begin());
+ i != entity_->getTypeParameters().end();) {
+ out << indent()
+ << ("the_buffer.append(::rtl::OUStringToOString("
+ "::cppu::getTypeFavourChar(static_cast< ");
+ dumpTypeParameterName(out, *i);
+ out << " * >(0)).getTypeName(), RTL_TEXTENCODING_UTF8));\n";
+ ++i;
+ if (i != entity_->getTypeParameters().end()) {
+ out << indent() << "the_buffer.append(',');\n";
+ }
+ }
+ out << indent() << "the_buffer.append('>');\n";
+
+ out << "#endif\n";
+
+ out << indent()
+ << "::typelib_static_type_init(&the_type, " << getTypeClass(name_, true)
+ << ", the_buffer.getStr());\n";
+
+ dec();
+ out << indent() << "}\n" << indent()
+ << "return *reinterpret_cast< ::css::uno::Type * >(&the_type);\n";
+ dumpGetCppuTypePostamble(out);
+}
+
+void PolyStructType::dumpNormalGetCppuType(FileStream & out)
+{
+ dumpGetCppuTypePreamble(out);
+ out << indent()
+ << ("//TODO: On certain platforms with weak memory models, the"
+ " following code can result in some threads observing that the_type"
+ " points to garbage\n")
+ << indent()
+ << "static ::typelib_TypeDescriptionReference * the_type = 0;\n"
+ << indent() << "if (the_type == 0) {\n";
+ inc();
+ out << indent() << "::rtl::OStringBuffer the_buffer(\"" << name_
+ << "<\");\n";
+ for (std::vector< OUString >::const_iterator i(
+ entity_->getTypeParameters().begin());
+ i != entity_->getTypeParameters().end();) {
+ out << indent()
+ << ("the_buffer.append(::rtl::OUStringToOString("
+ "::cppu::getTypeFavourChar(static_cast< ");
+ dumpTypeParameterName(out, *i);
+ out << " * >(0)).getTypeName(), RTL_TEXTENCODING_UTF8));\n";
+ ++i;
+ if (i != entity_->getTypeParameters().end()) {
+ out << indent() << "the_buffer.append(',');\n";
+ }
+ }
+ out << indent() << "the_buffer.append('>');\n" << indent()
+ << "::typelib_TypeDescriptionReference * the_members[] = {\n";
+ inc();
+ for (std::vector< unoidl::PolymorphicStructTypeTemplateEntity::Member >::
+ const_iterator i(entity_->getMembers().begin());
+ i != entity_->getMembers().end();) {
+ out << indent();
+ if (i->parameterized) {
+ out << "::cppu::getTypeFavourChar(static_cast< ";
+ dumpTypeParameterName(out, i->type);
+ out << " * >(0))";
+ } else {
+ out << "::cppu::UnoType< ";
+ dumpType(out, i->type, false, false, false, true);
+ out << " >::get()";
+ }
+ ++i;
+ out << ".getTypeLibType()"
+ << (i == entity_->getMembers().end() ? " };" : ",") << "\n";
+ }
+ dec();
+ out << indent() << "static ::sal_Bool const the_parameterizedTypes[] = { ";
+ for (std::vector< unoidl::PolymorphicStructTypeTemplateEntity::Member >::
+ const_iterator i(entity_->getMembers().begin());
+ i != entity_->getMembers().end(); ++i) {
+ if (i != entity_->getMembers().begin()) {
+ out << ", ";
+ }
+ out << (i->parameterized ? "true" : "false");
+ }
+ out << " };\n" << indent()
+ << ("::typelib_static_struct_type_init(&the_type, the_buffer.getStr(),"
+ " 0, ")
+ << entity_->getMembers().size()
+ << ", the_members, the_parameterizedTypes);\n";
+ dec();
+ out << indent() << "}\n" << indent()
+ << ("return *reinterpret_cast< ::css::uno::Type * >("
+ "&the_type);\n");
+ dumpGetCppuTypePostamble(out);
+}
+
+void PolyStructType::dumpComprehensiveGetCppuType(FileStream & out)
+{
+ out << "namespace cppu { namespace detail {\n\n" << indent();
+ dumpTemplateHead(out);
+ OUString staticTypeClass("the" + id_ + "Type");
+ out << "struct " << staticTypeClass
+ << " : public rtl::StaticWithInit< ::css::uno::Type *, "
+ << staticTypeClass;
+ dumpTemplateParameters(out);
+ out << " >\n" << indent() << "{\n";
+ inc();
+ out << indent() << "::css::uno::Type * operator()() const\n"
+ << indent() << "{\n";
+ inc();
+
+ out << "#ifdef LIBO_INTERNAL_ONLY\n";
+ out << indent()
+ << "::rtl::OUString the_name =\n";
+ out << indent() << "\"" << name_ << "<\" +\n";
+ for (std::vector< OUString >::const_iterator i(
+ entity_->getTypeParameters().begin());
+ i != entity_->getTypeParameters().end();) {
+ out << indent()
+ << "::cppu::getTypeFavourChar(static_cast< ";
+ dumpTypeParameterName(out, *i);
+ out << " * >(0)).getTypeName() +\n";
+ ++i;
+ if (i != entity_->getTypeParameters().end()) {
+ out << indent()
+ << "\",\" +\n";
+ }
+ }
+ out << indent()
+ << "\">\";\n";
+ out << "#else\n";
+ out << indent() << "::rtl::OUStringBuffer the_buffer;\n" << indent()
+ << "the_buffer.append(\"" << name_ << "<\");\n";
+ for (std::vector< OUString >::const_iterator i(
+ entity_->getTypeParameters().begin());
+ i != entity_->getTypeParameters().end();) {
+ out << indent()
+ << "the_buffer.append(::cppu::getTypeFavourChar(static_cast< ";
+ dumpTypeParameterName(out, *i);
+ out << " * >(0)).getTypeName());\n";
+ ++i;
+ if (i != entity_->getTypeParameters().end()) {
+ out << indent()
+ << ("the_buffer.append("
+ "static_cast< ::sal_Unicode >(','));\n");
+ }
+ }
+ out << indent() << "the_buffer.append(static_cast< ::sal_Unicode >('>'));\n";
+ out << indent()
+ << "::rtl::OUString the_name(the_buffer.makeStringAndClear());\n";
+ out << "#endif\n";
+ std::map< OUString, sal_uInt32 > parameters;
+ std::map< OUString, sal_uInt32 > types;
+ std::vector< unoidl::PolymorphicStructTypeTemplateEntity::Member >::
+ size_type n = 0;
+ for (const unoidl::PolymorphicStructTypeTemplateEntity::Member& member : entity_->getMembers()) {
+ if (member.parameterized) {
+ if (parameters.emplace(
+ member.type, static_cast< sal_uInt32 >(parameters.size())).
+ second) {
+ sal_uInt32 k = static_cast< sal_uInt32 >(parameters.size() - 1);
+ out << indent()
+ << "::css::uno::Type const & the_ptype" << k
+ << " = ::cppu::getTypeFavourChar(static_cast< ";
+ dumpTypeParameterName(out, member.type);
+ out << " * >(0));\n" << indent()
+ << "::typelib_TypeClass the_pclass" << k
+ << " = (::typelib_TypeClass) the_ptype" << k
+ << ".getTypeClass();\n" << indent()
+ << "::rtl::OUString the_pname" << k << "(the_ptype" << k
+ << ".getTypeName());\n";
+ }
+ } else if (types.emplace(member.type, static_cast< sal_uInt32 >(types.size())).
+ second) {
+ dumpCppuGetType(out, member.type, &name_);
+ // For typedefs, use the resolved type name, as there will be no
+ // information available about the typedef itself at runtime (the
+ // above getCppuType call will make available information about the
+ // resolved type); no extra #include for the resolved type is
+ // needed, as the header for the typedef includes it already:
+ out << indent() << "::rtl::OUString the_tname"
+ << static_cast< sal_uInt32 >(types.size() - 1) << "( \""
+ << resolveAllTypedefs(member.type) << "\" );\n";
+ }
+ out << indent() << "::rtl::OUString the_name" << n++ << "( \""
+ << member.name << "\" );\n";
+ }
+ out << indent() << "::typelib_StructMember_Init the_members[] = {\n";
+ inc();
+ n = 0;
+ for (std::vector< unoidl::PolymorphicStructTypeTemplateEntity::Member >::
+ const_iterator i(entity_->getMembers().begin());
+ i != entity_->getMembers().end();) {
+ out << indent() << "{ { ";
+ if (i->parameterized) {
+ sal_uInt32 k = parameters.find(i->type)->second;
+ out << "the_pclass" << k << ", the_pname" << k << ".pData";
+ } else {
+ out << getTypeClass(i->type, true) << ", the_tname"
+ << types.find(i->type)->second << ".pData";
+ }
+ out << ", the_name" << n++ << ".pData }, "
+ << (i->parameterized ? "true" : "false") << " }";
+ ++i;
+ out << (i == entity_->getMembers().end() ? " };" : ",") << "\n";
+ }
+ dec();
+ out << indent() << "::typelib_TypeDescription * the_newType = 0;\n";
+ out << indent()
+ << ("::typelib_typedescription_newStruct(&the_newType, the_name.pData,"
+ " 0, ")
+ << entity_->getMembers().size() << ", the_members);\n" << indent()
+ << "::typelib_typedescription_register(&the_newType);\n" << indent()
+ << "::typelib_typedescription_release(the_newType);\n" << indent()
+ << "return new ::css::uno::Type(" << getTypeClass(name_)
+ << ", the_name); // leaked\n";
+ dec();
+ out << indent() << "}\n";
+ dec();
+ out << indent() << "};\n } }\n\n";
+ dumpGetCppuTypePreamble(out);
+ out << indent() << "return *detail::" << staticTypeClass;
+ dumpTemplateParameters(out);
+ out << "::get();\n";
+ dumpGetCppuTypePostamble(out);
+}
+
+void PolyStructType::addLightGetCppuTypeIncludes(
+ codemaker::cppumaker::Includes & includes) const
+{
+ includes.addType();
+ includes.addCppuUnotypeHxx();
+ includes.addSalTypesH();
+ includes.addTypelibTypeclassH();
+ includes.addTypelibTypedescriptionH();
+ includes.addRtlStrbufHxx();
+ includes.addRtlTextencH();
+ includes.addRtlUstringHxx();
+}
+
+void PolyStructType::addNormalGetCppuTypeIncludes(
+ codemaker::cppumaker::Includes & includes) const
+{
+ includes.addType();
+ includes.addCppuUnotypeHxx();
+ includes.addSalTypesH();
+ includes.addTypelibTypeclassH();
+ includes.addTypelibTypedescriptionH();
+ includes.addRtlStrbufHxx();
+ includes.addRtlTextencH();
+ includes.addRtlUstringHxx();
+}
+
+void PolyStructType::addComprehensiveGetCppuTypeIncludes(
+ codemaker::cppumaker::Includes & includes) const
+{
+ includes.addType();
+ includes.addCppuUnotypeHxx();
+ includes.addRtlInstanceHxx();
+ includes.addRtlUstringH();
+ includes.addRtlUstringHxx();
+ includes.addSalTypesH();
+ includes.addTypelibTypeclassH();
+ includes.addTypelibTypedescriptionH();
+ includes.addRtlStringH();
+ includes.addRtlUstrbufHxx();
+}
+
+void PolyStructType::dumpTemplateHead(FileStream & out) const
+{
+ out << "template< ";
+ for (std::vector< OUString >::const_iterator i(
+ entity_->getTypeParameters().begin());
+ i != entity_->getTypeParameters().end(); ++i) {
+ if (i != entity_->getTypeParameters().begin()) {
+ out << ", ";
+ }
+ out << "typename ";
+ dumpTypeParameterName(out, *i);
+ }
+ out << " > ";
+}
+
+void PolyStructType::dumpTemplateParameters(FileStream & out) const
+{
+ out << "< ";
+ for (std::vector< OUString >::const_iterator i(
+ entity_->getTypeParameters().begin());
+ i != entity_->getTypeParameters().end(); ++i) {
+ if (i != entity_->getTypeParameters().begin()) {
+ out << ", ";
+ }
+ dumpTypeParameterName(out, *i);
+ }
+ out << " >";
+}
+
+OUString typeToIdentifier(std::u16string_view name)
+{
+ sal_Int32 k;
+ OUString n(b2u(codemaker::UnoType::decompose(u2b(name), &k)));
+ OUStringBuffer b(4*k + n.getLength());
+ for (sal_Int32 i = 0; i != k; ++i) {
+ b.append("seq_");
+ }
+ b.append(n);
+ b.replace(' ', '_');
+ b.replace(',', '_');
+ b.replace('.', '_');
+ b.replace('<', '_');
+ b.replace('>', '_');
+ return b.makeStringAndClear();
+}
+
+class ExceptionType: public CppuType
+{
+public:
+ ExceptionType(
+ rtl::Reference< unoidl::ExceptionTypeEntity > const & entity,
+ OUString const & name, rtl::Reference< TypeManager > const & typeMgr):
+ CppuType(name, typeMgr), entity_(entity) {
+ assert(entity.is());
+ }
+
+private:
+ virtual void dumpHdlFile(
+ FileStream & out, codemaker::cppumaker::Includes & includes) override;
+
+ virtual void dumpHppFile(
+ FileStream & out, codemaker::cppumaker::Includes & includes) override;
+
+ virtual void addComprehensiveGetCppuTypeIncludes(
+ codemaker::cppumaker::Includes & includes) const override;
+
+ virtual void dumpLightGetCppuType(FileStream & out) override;
+
+ virtual void dumpNormalGetCppuType(FileStream & out) override;
+
+ virtual void dumpComprehensiveGetCppuType(FileStream & out) override;
+
+ virtual sal_uInt32 checkInheritedMemberCount() const override {
+ return getTotalMemberCount(entity_->getDirectBase());
+ }
+
+ virtual void dumpDeclaration(FileStream & out) override;
+
+ bool dumpBaseMembers(
+ FileStream & out, OUString const & base, bool withType,
+ bool eligibleForDefaults);
+
+ sal_uInt32 getTotalMemberCount(OUString const & base) const;
+
+ rtl::Reference< unoidl::ExceptionTypeEntity > entity_;
+};
+
+void ExceptionType::dumpHdlFile(
+ FileStream & out, codemaker::cppumaker::Includes & includes)
+{
+ if (name_ == "com.sun.star.uno.Exception")
+ {
+ // LIBO_INTERNAL_ONLY implies GCC >= 7, which we need for this
+ // Merely checking __has_include is not enough because some systems have the header,
+ // but do not have a new enough Clang 9 supporting __builtin_FILE/LINE/FUNCTION as used by
+ // that libstdc++ header.
+ includes.addCustom("#if defined LIBO_INTERNAL_ONLY && ((defined __GNUC__ && !defined __clang__) || (defined __clang__ && __clang_major__ >= 9)) && __has_include(<experimental/source_location>)");
+ includes.addCustom("#define LIBO_USE_SOURCE_LOCATION");
+ includes.addCustom("#endif");
+ includes.addCustom("#if defined LIBO_USE_SOURCE_LOCATION");
+ includes.addCustom("#include <experimental/source_location>");
+ includes.addCustom("#include <o3tl/runtimetooustring.hxx>");
+ includes.addCustom("#endif");
+ }
+ dumpHFileContent(out, includes);
+}
+
+void ExceptionType::addComprehensiveGetCppuTypeIncludes(
+ codemaker::cppumaker::Includes & includes) const
+{
+ includes.addCppuUnotypeHxx();
+ includes.addRtlInstanceHxx(); // using rtl::StaticWithInit
+}
+
+void ExceptionType::dumpHppFile(
+ FileStream & out, codemaker::cppumaker::Includes & includes)
+{
+ OUString headerDefine(dumpHeaderDefine(out, u"HPP"));
+ out << "\n";
+ addDefaultHxxIncludes(includes);
+ includes.dump(out, &name_, true);
+
+ // for the output operator below
+ if (name_ == "com.sun.star.uno.Exception")
+ {
+ out << "#if defined LIBO_INTERNAL_ONLY\n";
+ out << "#include <ostream>\n";
+ out << "#include <typeinfo>\n";
+ out << "#endif\n";
+ }
+
+ out << "\n";
+
+ if (codemaker::cppumaker::dumpNamespaceOpen(out, name_, false)) {
+ out << "\n";
+ }
+
+ // default constructor
+ out << "\ninline " << id_ << "::" << id_ << "(\n";
+ out << "#if defined LIBO_USE_SOURCE_LOCATION\n";
+ out << " std::experimental::source_location location\n";
+ out << "#endif\n";
+ out << " )\n";
+ inc();
+ OUString base(entity_->getDirectBase());
+ bool bFirst = true;
+ if (!base.isEmpty()) {
+ out << indent() << ": " << codemaker::cpp::scopedCppName(u2b(base))
+ << "(\n";
+ out << "#if defined LIBO_USE_SOURCE_LOCATION\n";
+ out << " location\n";
+ out << "#endif\n";
+ out << ")\n";
+ bFirst = false;
+ }
+ for (const unoidl::ExceptionTypeEntity::Member& member : entity_->getDirectMembers()) {
+ out << indent() << (bFirst ? ":" : ",") << " ";
+ out << member.name;
+ dumpInitializer(out, false, member.type);
+ out << "\n";
+ bFirst = false;
+ }
+ dec();
+ out << "{";
+ if (!m_cppuTypeDynamic) {
+ out << "\n";
+ inc();
+ dumpCppuGetType(out, name_);
+ dec();
+ } else {
+ out << " ";
+ }
+ if (name_ == "com.sun.star.uno.Exception")
+ {
+ out << "\n#if defined LIBO_USE_SOURCE_LOCATION\n";
+ out << " if (!Message.isEmpty())\n";
+ out << " Message += \" \";\n";
+ out << " Message += \"at \" + o3tl::runtimeToOUString(location.file_name()) + \":\" + OUString::number(location.line());\n";
+ out << "#endif\n";
+ }
+ out << "}\n\n";
+
+ // fields constructor
+ if (!entity_->getDirectMembers().empty() || getInheritedMemberCount() > 0) {
+ out << indent() << "inline " << id_ << "::" << id_ << "(";
+ bFirst = !dumpBaseMembers(out, base, true, false);
+ for (const unoidl::ExceptionTypeEntity::Member& member : entity_->getDirectMembers()) {
+ if (!bFirst) {
+ out << ", ";
+ }
+ dumpType(out, member.type, true, true);
+ out << " " << member.name << "_";
+ bFirst = false;
+ }
+ out << "\n#if defined LIBO_USE_SOURCE_LOCATION\n";
+ out << " " << (bFirst ? "" : ", ") << "std::experimental::source_location location\n";
+ out << "#endif\n";
+ out << ")\n";
+ inc();
+ bFirst = true;
+ if (!base.isEmpty()) {
+ out << indent() << ": " << codemaker::cpp::scopedCppName(u2b(base))
+ << "(";
+ dumpBaseMembers(out, base, false, false);
+ out << "\n#if defined LIBO_USE_SOURCE_LOCATION\n";
+ out << " , location\n";
+ out << "#endif\n";
+ out << ")\n";
+ bFirst = false;
+ }
+ for (const unoidl::ExceptionTypeEntity::Member& member : entity_->getDirectMembers()) {
+ out << indent() << (bFirst ? ":" : ",") << " " << member.name << "("
+ << member.name << "_)\n";
+ bFirst = false;
+ }
+ dec();
+ out << "{";
+ if (!m_cppuTypeDynamic) {
+ out << "\n";
+ inc();
+ dumpCppuGetType(out, name_);
+ dec();
+ } else {
+ out << " ";
+ }
+ if (name_ == "com.sun.star.uno.Exception")
+ {
+ out << "\n#if defined LIBO_USE_SOURCE_LOCATION\n";
+ out << " if (!Message.isEmpty())\n";
+ out << " Message += \" \";\n";
+ out << " Message += \"at \" + o3tl::runtimeToOUString(location.file_name()) + \":\" + OUString::number(location.line());\n";
+ out << "#endif\n";
+ }
+ out << "}\n\n";
+ }
+ out << "#if !defined LIBO_INTERNAL_ONLY\n" << indent() << id_ << "::" << id_
+ << "(" << id_ << " const & the_other)";
+ bFirst = true;
+ if (!base.isEmpty()) {
+ out << ": " << codemaker::cpp::scopedCppName(u2b(base))
+ << "(the_other)";
+ bFirst = false;
+ }
+ for (const unoidl::ExceptionTypeEntity::Member& member : entity_->getDirectMembers()) {
+ out << (bFirst ? ":" : ",") << " " << member.name << "(the_other." << member.name
+ << ")";
+ bFirst = false;
+ }
+ out << indent() << " {}\n\n" << indent() << id_ << "::~" << id_
+ << "() {}\n\n" << indent() << id_ << " & " << id_ << "::operator =("
+ << id_ << " const & the_other) {\n";
+ inc();
+ out << indent()
+ << ("//TODO: Just like its implicitly-defined counterpart, this"
+ " function definition is not exception-safe\n");
+ if (!base.isEmpty()) {
+ out << indent() << codemaker::cpp::scopedCppName(u2b(base))
+ << "::operator =(the_other);\n";
+ }
+ for (const unoidl::ExceptionTypeEntity::Member& member : entity_->getDirectMembers()) {
+ out << indent() << member.name << " = the_other." << member.name << ";\n";
+ }
+ out << indent() << "return *this;\n";
+ dec();
+ out << indent() << "}\n#endif\n\n";
+
+ // Provide an output operator for printing Exception information to SAL_WARN/SAL_INFO.
+ if (name_ == "com.sun.star.uno.Exception")
+ {
+ out << "#if defined LIBO_INTERNAL_ONLY\n";
+ out << "template< typename charT, typename traits >\n";
+ out << "inline ::std::basic_ostream<charT, traits> & operator<<(\n";
+ out << " ::std::basic_ostream<charT, traits> & os, ::com::sun::star::uno::Exception const & exception)\n";
+ out << "{\n";
+ out << " // the class name is useful because exception throwing code does not always pass in a useful message\n";
+ out << " os << typeid(exception).name();\n";
+ out << " if (!exception.Message.isEmpty())\n";
+ out << " os << \" msg: \" << exception.Message;\n";
+ out << " return os;\n";
+ out << "}\n";
+ out << "#endif\n";
+ out << "\n";
+ }
+
+ if (codemaker::cppumaker::dumpNamespaceClose(out, name_, false)) {
+ out << "\n";
+ }
+ out << "\n";
+
+ dumpGetCppuType(out);
+ out << "\n#endif // "<< headerDefine << "\n";
+}
+
+void ExceptionType::dumpLightGetCppuType(FileStream & out)
+{
+ dumpGetCppuTypePreamble(out);
+ out << indent()
+ << "static typelib_TypeDescriptionReference * the_type = 0;\n"
+ << indent() << "if ( !the_type )\n" << indent() << "{\n";
+ inc();
+ out << indent() << "typelib_static_type_init( &the_type, "
+ << getTypeClass(name_, true) << ", \"" << name_ << "\" );\n";
+ dec();
+ out << indent() << "}\n" << indent()
+ << ("return * reinterpret_cast< ::css::uno::Type * >("
+ " &the_type );\n");
+ dumpGetCppuTypePostamble(out);
+}
+
+void ExceptionType::dumpNormalGetCppuType(FileStream & out)
+{
+ dumpGetCppuTypePreamble(out);
+ out << indent()
+ << "static typelib_TypeDescriptionReference * the_type = 0;\n"
+ << indent() << "if ( !the_type )\n" << indent() << "{\n";
+ inc();
+ OUString base(entity_->getDirectBase());
+ bool baseException = false;
+ if (!base.isEmpty()) {
+ if (base == "com.sun.star.uno.Exception") {
+ baseException = true;
+ } else {
+ out << indent()
+ << ("const ::css::uno::Type& rBaseType ="
+ " ::cppu::UnoType< ");
+ dumpType(out, base, true, false, false, true);
+ out << " >::get();\n\n";
+ }
+ }
+ if (!entity_->getDirectMembers().empty()) {
+ out << indent() << "typelib_TypeDescriptionReference * aMemberRefs["
+ << entity_->getDirectMembers().size() << "];\n";
+ std::set< OUString > seen;
+ std::vector< unoidl::ExceptionTypeEntity::Member >::size_type n = 0;
+ for (const unoidl::ExceptionTypeEntity::Member& member : entity_->getDirectMembers()) {
+ OUString type(resolveAllTypedefs(member.type));
+ OUString modType(typeToIdentifier(type));
+ if (seen.insert(type).second) {
+ out << indent()
+ << "const ::css::uno::Type& rMemberType_"
+ << modType << " = ::cppu::UnoType< ";
+ dumpType(out, type, false, false, false, true);
+ out << " >::get();\n";
+ }
+ out << indent() << "aMemberRefs[" << n++ << "] = rMemberType_"
+ << modType << ".getTypeLibType();\n";
+ }
+ out << "\n";
+ }
+ out << indent() << "typelib_static_compound_type_init( &the_type, "
+ << getTypeClass(name_, true) << ", \"" << name_ << "\", ";
+ if (baseException) {
+ out << ("* ::typelib_static_type_getByTypeClass("
+ " typelib_TypeClass_EXCEPTION )");
+ } else if (base.isEmpty()) {
+ out << "0";
+ } else {
+ out << "rBaseType.getTypeLibType()";
+ }
+ out << ", " << entity_->getDirectMembers().size() << ", "
+ << (entity_->getDirectMembers().empty() ? "0" : "aMemberRefs")
+ << " );\n";
+ dec();
+ out << indent() << "}\n" << indent()
+ << ("return * reinterpret_cast< const ::css::uno::Type * >("
+ " &the_type );\n");
+ dumpGetCppuTypePostamble(out);
+}
+
+void ExceptionType::dumpComprehensiveGetCppuType(FileStream & out)
+{
+ codemaker::cppumaker::dumpNamespaceOpen(out, name_, false);
+ out << " namespace detail {\n\n";
+ OUString staticTypeClass("the" + id_ + "Type");
+ out << indent() << "struct " << staticTypeClass
+ << " : public rtl::StaticWithInit< ::css::uno::Type *, "
+ << staticTypeClass << " >\n" << indent() << "{\n";
+ inc();
+ out << indent() << "::css::uno::Type * operator()() const\n"
+ << indent() << "{\n";
+ inc();
+ out << indent() << "::rtl::OUString sTypeName( \"" << name_ << "\" );\n\n"
+ << indent() << "// Start inline typedescription generation\n"
+ << indent() << "typelib_TypeDescription * pTD = 0;\n";
+ OUString base(entity_->getDirectBase());
+ if (!base.isEmpty()) {
+ out << indent()
+ << ("const ::css::uno::Type& rSuperType ="
+ " ::cppu::UnoType< ");
+ dumpType(out, base, false, false, false, true);
+ out << " >::get();\n";
+ }
+ std::set< OUString > seen;
+ for (const unoidl::ExceptionTypeEntity::Member& member : entity_->getDirectMembers()) {
+ if (seen.insert(member.type).second) {
+ dumpCppuGetType(out, member.type);
+ }
+ }
+ if (!entity_->getDirectMembers().empty()) {
+ out << "\n" << indent() << "typelib_CompoundMember_Init aMembers["
+ << entity_->getDirectMembers().size() << "];\n";
+ std::vector< unoidl::ExceptionTypeEntity::Member >::size_type n = 0;
+ for (const unoidl::ExceptionTypeEntity::Member& member : entity_->getDirectMembers()) {
+ OUString type(resolveAllTypedefs(member.type));
+ out << indent() << "::rtl::OUString sMemberType" << n << "( \""
+ << type << "\" );\n" << indent()
+ << "::rtl::OUString sMemberName" << n << "( \"" << member.name
+ << "\" );\n" << indent() << "aMembers[" << n
+ << "].eTypeClass = (typelib_TypeClass)" << getTypeClass(type)
+ << ";\n" << indent() << "aMembers[" << n
+ << "].pTypeName = sMemberType" << n << ".pData;\n" << indent()
+ << "aMembers[" << n << "].pMemberName = sMemberName" << n
+ << ".pData;\n";
+ ++n;
+ }
+ }
+ out << "\n" << indent() << "typelib_typedescription_new(\n";
+ inc();
+ out << indent() << "&pTD,\n" << indent() << "(typelib_TypeClass)"
+ << getTypeClass(name_) << ", sTypeName.pData,\n" << indent()
+ << (base.isEmpty() ? "0" : "rSuperType.getTypeLibType()") << ",\n"
+ << indent() << entity_->getDirectMembers().size() << ",\n" << indent()
+ << (entity_->getDirectMembers().empty() ? "0" : "aMembers")
+ << " );\n\n";
+ dec();
+ out << indent()
+ << ("typelib_typedescription_register( (typelib_TypeDescription**)&pTD"
+ " );\n\n")
+ << indent() << "typelib_typedescription_release( pTD );\n" << indent()
+ << "// End inline typedescription generation\n\n" << indent()
+ << "return new ::css::uno::Type( " << getTypeClass(name_)
+ << ", sTypeName ); // leaked\n";
+ dec();
+ out << indent() << "}\n";
+ dec();
+ out << indent() << "};\n\n";
+ codemaker::cppumaker::dumpNamespaceClose(out, name_, false);
+ out << " }\n\n";
+ dumpGetCppuTypePreamble(out);
+ out << indent() << "return *detail::" << staticTypeClass << "::get();\n";
+ dumpGetCppuTypePostamble(out);
+}
+
+void ExceptionType::dumpDeclaration(FileStream & out)
+{
+ out << "\nclass CPPU_GCC_DLLPUBLIC_EXPORT SAL_WARN_UNUSED " << id_;
+ OUString base(entity_->getDirectBase());
+ if (!base.isEmpty()) {
+ out << " : public " << codemaker::cpp::scopedCppName(u2b(base));
+ }
+ out << "\n{\npublic:\n";
+ inc();
+
+ // default constructor
+ out << indent() << "inline CPPU_GCC_DLLPRIVATE " << id_ << "(\n";
+ out << "#if defined LIBO_USE_SOURCE_LOCATION\n";
+ out << " std::experimental::source_location location = std::experimental::source_location::current()\n";
+ out << "#endif\n\n";
+ out << " );\n";
+
+ // constructor that initializes data members
+ if (!entity_->getDirectMembers().empty() || getInheritedMemberCount() > 0) {
+ out << indent() << "inline CPPU_GCC_DLLPRIVATE " << id_ << "(";
+ bool eligibleForDefaults = entity_->getDirectMembers().empty();
+ bool bFirst = !dumpBaseMembers(out, base, true, eligibleForDefaults);
+ for (const unoidl::ExceptionTypeEntity::Member& member : entity_->getDirectMembers()) {
+ if (!bFirst) {
+ out << ", ";
+ }
+ dumpType(out, member.type, true, true);
+ out << " " << member.name << "_";
+ bFirst = false;
+ }
+ out << "\n#if defined LIBO_USE_SOURCE_LOCATION\n";
+ out << ", std::experimental::source_location location = std::experimental::source_location::current()\n";
+ out << "#endif\n";
+ out << " );\n\n";
+ }
+ out << "#if !defined LIBO_INTERNAL_ONLY\n" << indent()
+ << "inline CPPU_GCC_DLLPRIVATE " << id_ << "(" << id_
+ << " const &);\n\n" << indent() << "inline CPPU_GCC_DLLPRIVATE ~"
+ << id_ << "();\n\n" << indent() << "inline CPPU_GCC_DLLPRIVATE " << id_
+ << " & operator =(" << id_ << " const &);\n#endif\n\n";
+ for (std::vector< unoidl::ExceptionTypeEntity::Member >::const_iterator i(
+ entity_->getDirectMembers().begin());
+ i != entity_->getDirectMembers().end(); ++i) {
+ out << indent();
+ dumpType(out, i->type);
+ out << " " << i->name;
+ if (i == entity_->getDirectMembers().begin() && !base.isEmpty()
+ && i->type != "hyper" && i->type != "unsigned hyper"
+ && i->type != "double") {
+ out << " CPPU_GCC3_ALIGN( "
+ << codemaker::cpp::scopedCppName(u2b(base)) << " )";
+ }
+ out << ";\n";
+ }
+ dec();
+ out << "};\n\n";
+}
+
+bool ExceptionType::dumpBaseMembers(
+ FileStream & out, OUString const & base, bool withType, bool eligibleForDefaults)
+{
+ if (base.isEmpty())
+ return false;
+
+ bool hasMember = false;
+ rtl::Reference< unoidl::Entity > ent;
+ codemaker::UnoType::Sort sort = m_typeMgr->getSort(base, &ent);
+ if (sort != codemaker::UnoType::Sort::Exception) {
+ throw CannotDumpException(
+ "exception type base " + base + " is not an exception type");
+ }
+ rtl::Reference< unoidl::ExceptionTypeEntity > ent2(
+ dynamic_cast< unoidl::ExceptionTypeEntity * >(ent.get()));
+ assert(ent2.is());
+ if (!ent2.is()) {
+ return false;
+ }
+ hasMember = dumpBaseMembers( out, ent2->getDirectBase(), withType,
+ eligibleForDefaults && ent2->getDirectMembers().empty() );
+ int memberCount = 0;
+ for (const unoidl::ExceptionTypeEntity::Member& member : ent2->getDirectMembers()) {
+ if (hasMember) {
+ out << ", ";
+ }
+ if (withType) {
+ dumpType(out, member.type, true, true);
+ out << " ";
+ }
+ out << member.name << "_";
+ // We want to provide a default parameter value for uno::Exception subtype
+ // constructors, since most of the time we don't pass a Context object in to the exception
+ // throw sites.
+ if (eligibleForDefaults
+ && base == "com.sun.star.uno.Exception"
+ && memberCount == 1
+ && member.name == "Context"
+ && member.type == "com.sun.star.uno.XInterface") {
+ out << " = ::css::uno::Reference< ::css::uno::XInterface >()";
+ }
+ hasMember = true;
+ ++memberCount;
+ }
+ return hasMember;
+}
+
+sal_uInt32 ExceptionType::getTotalMemberCount(OUString const & base) const
+{
+ if (base.isEmpty()) {
+ return 0;
+ }
+ rtl::Reference< unoidl::Entity > ent;
+ codemaker::UnoType::Sort sort = m_typeMgr->getSort(base, &ent);
+ if (sort != codemaker::UnoType::Sort::Exception) {
+ throw CannotDumpException(
+ "exception type base " + base + " is not an exception type");
+ }
+ unoidl::ExceptionTypeEntity& ent2(dynamic_cast<unoidl::ExceptionTypeEntity&>(*ent));
+ return getTotalMemberCount(ent2.getDirectBase())
+ + ent2.getDirectMembers().size(); //TODO: overflow
+}
+
+class EnumType: public CppuType
+{
+public:
+ EnumType(
+ rtl::Reference< unoidl::EnumTypeEntity > const & entity,
+ OUString const & name, rtl::Reference< TypeManager > const & typeMgr):
+ CppuType(name, typeMgr), entity_(entity) {
+ assert(entity.is());
+ }
+
+private:
+ virtual void dumpDeclaration(FileStream& o) override;
+
+ virtual void addComprehensiveGetCppuTypeIncludes(
+ codemaker::cppumaker::Includes & includes) const override;
+
+ void dumpHppFile(FileStream& o, codemaker::cppumaker::Includes & includes) override;
+
+ void dumpNormalGetCppuType(FileStream& o) override;
+ void dumpComprehensiveGetCppuType(FileStream& o) override;
+
+ rtl::Reference< unoidl::EnumTypeEntity > entity_;
+};
+
+void EnumType::addComprehensiveGetCppuTypeIncludes(
+ codemaker::cppumaker::Includes & includes) const
+{
+ includes.addCppuUnotypeHxx();
+ includes.addRtlInstanceHxx(); // using rtl::StaticWithInit
+}
+
+void EnumType::dumpDeclaration(FileStream& o)
+{
+ o << "\n#if defined LIBO_INTERNAL_ONLY\n";
+ o << "\nenum class SAL_DLLPUBLIC_RTTI " << id_ << "\n{\n";
+ o << "\n#else\n";
+ o << "\nenum SAL_DLLPUBLIC_RTTI " << id_ << "\n{\n";
+ o << "\n#endif\n";
+ inc();
+
+ for (const unoidl::EnumTypeEntity::Member& member : entity_->getMembers()) {
+ o << indent() << id_ << "_" << u2b(member.name) << " = " << member.value
+ << ",\n";
+ }
+
+ o << indent() << id_ << "_MAKE_FIXED_SIZE = SAL_MAX_ENUM\n";
+
+ dec();
+ o << "};\n\n";
+
+ // use constexpr to create a kind of type-alias so we don't have to modify existing code
+ o << "#if defined LIBO_INTERNAL_ONLY\n";
+ for (const unoidl::EnumTypeEntity::Member& member : entity_->getMembers()) {
+ o << "constexpr auto " << id_ << "_" << u2b(member.name)
+ << " = "
+ << id_ << "::" << id_ << "_" << u2b(member.name)
+ << ";\n";
+ }
+ o << "#endif\n";
+}
+
+void EnumType::dumpHppFile(
+ FileStream& o, codemaker::cppumaker::Includes & includes)
+{
+ OUString headerDefine(dumpHeaderDefine(o, u"HPP"));
+ o << "\n";
+
+ addDefaultHxxIncludes(includes);
+ includes.dump(o, &name_, true);
+ o << "\n";
+
+ dumpGetCppuType(o);
+
+ o << "\n#endif // "<< headerDefine << "\n";
+}
+
+void EnumType::dumpNormalGetCppuType(FileStream& o)
+{
+ dumpGetCppuTypePreamble(o);
+
+ o << indent()
+ << "static typelib_TypeDescriptionReference * the_type = 0;\n";
+
+ o << indent() << "if ( !the_type )\n" << indent() << "{\n";
+ inc();
+
+ o << indent() << "typelib_static_enum_type_init( &the_type,\n";
+ inc(31);
+ o << indent() << "\"" << name_ << "\",\n"
+ << indent() << codemaker::cpp::scopedCppName(u2b(name_)) << "_"
+ << u2b(entity_->getMembers()[0].name) << " );\n";
+ dec(31);
+ dec();
+ o << indent() << "}\n";
+ o << indent()
+ << ("return * reinterpret_cast< ::css::uno::Type * >("
+ " &the_type );\n");
+ dumpGetCppuTypePostamble(o);
+}
+
+void EnumType::dumpComprehensiveGetCppuType(FileStream& o)
+{
+ if (!isPolymorphic())
+ codemaker::cppumaker::dumpNamespaceOpen(o, name_, false);
+ else
+ o << "namespace cppu { ";
+ o << " namespace detail {\n\n";
+
+ OUString sStaticTypeClass("the" + id_ + "Type");
+ o << indent() << "struct " << sStaticTypeClass << " : public rtl::StaticWithInit< ::css::uno::Type *, " << sStaticTypeClass << " >\n";
+ o << indent() << "{\n";
+ inc();
+ o << indent() << "::css::uno::Type * operator()() const\n";
+ o << indent() << "{\n";
+
+ inc();
+ o << indent() << "::rtl::OUString sTypeName( \"" << name_
+ << "\" );\n\n";
+
+ o << indent() << "// Start inline typedescription generation\n"
+ << indent() << "typelib_TypeDescription * pTD = 0;\n\n";
+
+ o << indent() << "rtl_uString* enumValueNames["
+ << entity_->getMembers().size() << "];\n";
+ std::vector< unoidl::EnumTypeEntity::Member >::size_type n = 0;
+ for (const unoidl::EnumTypeEntity::Member& member : entity_->getMembers()) {
+ o << indent() << "::rtl::OUString sEnumValue" << n << "( \""
+ << u2b(member.name) << "\" );\n";
+ o << indent() << "enumValueNames[" << n << "] = sEnumValue" << n
+ << ".pData;\n";
+ ++n;
+ }
+
+ o << "\n" << indent() << "sal_Int32 enumValues["
+ << entity_->getMembers().size() << "];\n";
+ n = 0;
+ for (const unoidl::EnumTypeEntity::Member& member : entity_->getMembers()) {
+ o << indent() << "enumValues[" << n++ << "] = " << member.value << ";\n";
+ }
+
+ o << "\n" << indent() << "typelib_typedescription_newEnum( &pTD,\n";
+ inc();
+ o << indent() << "sTypeName.pData,\n"
+ << indent() << "(sal_Int32)"
+ << codemaker::cpp::scopedCppName(u2b(name_), false) << "_"
+ << u2b(entity_->getMembers()[0].name) << ",\n"
+ << indent() << entity_->getMembers().size()
+ << ", enumValueNames, enumValues );\n\n";
+ dec();
+
+ o << indent()
+ << ("typelib_typedescription_register( (typelib_TypeDescription**)&pTD"
+ " );\n");
+ o << indent() << "typelib_typedescription_release( pTD );\n"
+ << indent() << "// End inline typedescription generation\n\n";
+
+ o << indent() << "return new ::css::uno::Type( "
+ << getTypeClass(name_) << ", sTypeName ); // leaked\n";
+
+ dec();
+ o << indent() << "}\n";
+ dec();
+ o << indent() << "};\n\n";
+
+ if (!isPolymorphic())
+ codemaker::cppumaker::dumpNamespaceClose(o, name_, false);
+ else
+ o << " }";
+ o << " }\n\n";
+
+ dumpGetCppuTypePreamble(o);
+ o << indent() << "return *detail::" << sStaticTypeClass << "::get();\n";
+ dumpGetCppuTypePostamble(o);
+}
+
+class Typedef: public CppuType
+{
+public:
+ Typedef(
+ rtl::Reference< unoidl::TypedefEntity > const & entity,
+ OUString const & name, rtl::Reference< TypeManager > const & typeMgr):
+ CppuType(name, typeMgr), entity_(entity) {
+ assert(entity.is());
+ }
+
+private:
+ virtual void dumpDeclaration(FileStream& o) override;
+
+ void dumpHdlFile(FileStream& o, codemaker::cppumaker::Includes & includes) override;
+
+ void dumpHppFile(FileStream& o, codemaker::cppumaker::Includes & includes) override;
+
+ rtl::Reference< unoidl::TypedefEntity > entity_;
+};
+
+void Typedef::dumpHdlFile(
+ FileStream& o, codemaker::cppumaker::Includes & includes)
+{
+ OUString headerDefine(dumpHeaderDefine(o, u"HDL"));
+ o << "\n";
+
+ addDefaultHIncludes(includes);
+ includes.dump(o, nullptr, true);
+ o << "\n";
+
+ if (codemaker::cppumaker::dumpNamespaceOpen(o, name_, false)) {
+ o << "\n";
+ }
+
+ dumpDeclaration(o);
+
+ if (codemaker::cppumaker::dumpNamespaceClose(o, name_, false)) {
+ o << "\n";
+ }
+
+ o << "#endif // "<< headerDefine << "\n";
+}
+
+void Typedef::dumpDeclaration(FileStream& o)
+{
+ o << "\ntypedef ";
+ dumpType(o, entity_->getType());
+ o << " " << id_ << ";\n\n";
+}
+
+void Typedef::dumpHppFile(
+ FileStream& o, codemaker::cppumaker::Includes & includes)
+{
+ OUString headerDefine(dumpHeaderDefine(o, u"HPP"));
+ o << "\n";
+
+ addDefaultHxxIncludes(includes);
+ includes.dump(o, &name_, true);
+ o << "\n";
+
+ o << "\n#endif // "<< headerDefine << "\n";
+}
+
+class ConstructiveType: public CppuType
+{
+public:
+ ConstructiveType(
+ OUString const & name, rtl::Reference< TypeManager > const & manager):
+ CppuType(name, manager) {}
+
+private:
+ virtual void dumpHdlFile(FileStream &, codemaker::cppumaker::Includes &) override {
+ assert(false); // this cannot happen
+ }
+
+ virtual void dumpFiles(OUString const & uri, CppuOptions const & options) override {
+ dumpFile(uri, name_, true, options);
+ }
+};
+
+bool hasRestParameter(
+ unoidl::SingleInterfaceBasedServiceEntity::Constructor const & constructor)
+{
+ return !constructor.parameters.empty()
+ && constructor.parameters.back().rest;
+}
+
+void includeExceptions(
+ codemaker::cppumaker::Includes & includes,
+ codemaker::ExceptionTreeNode const * node)
+{
+ if (node->present) {
+ includes.add(node->name);
+ } else {
+ for (std::unique_ptr<codemaker::ExceptionTreeNode> const & pChild : node->children) {
+ includeExceptions(includes, pChild.get());
+ }
+ }
+}
+
+class ServiceType: public ConstructiveType
+{
+public:
+ ServiceType(
+ rtl::Reference< unoidl::SingleInterfaceBasedServiceEntity > const &
+ entity,
+ OUString const & name, rtl::Reference< TypeManager > const & manager):
+ ConstructiveType(name, manager), entity_(entity) {
+ assert(entity.is());
+ }
+
+private:
+ virtual void dumpHppFile(
+ FileStream & o, codemaker::cppumaker::Includes & includes) override;
+
+ void dumpCatchClauses(
+ FileStream & out, codemaker::ExceptionTreeNode const * node);
+
+ rtl::Reference< unoidl::SingleInterfaceBasedServiceEntity > entity_;
+};
+
+void failsToSupply(
+ FileStream & o, std::u16string_view service, OString const & type)
+{
+ o << "::rtl::OUString(\"component context fails to supply service \") + \""
+ << service << "\" + \" of type \" + \"" << type << "\"";
+}
+
+void ServiceType::dumpHppFile(
+ FileStream & o, codemaker::cppumaker::Includes & includes)
+{
+ if (!entity_->getConstructors().empty()) {
+ //TODO: Decide whether the types added to includes should rather be
+ // added to m_dependencies (and thus be generated during
+ // dumpDependedTypes):
+ includes.addCassert();
+ includes.addReference();
+ includes.addRtlUstringH();
+ includes.addRtlUstringHxx();
+ includes.add("com.sun.star.uno.DeploymentException");
+ includes.add("com.sun.star.uno.XComponentContext");
+ for (const unoidl::SingleInterfaceBasedServiceEntity::Constructor& cons : entity_->getConstructors()) {
+ if (cons.defaultConstructor) {
+ includes.add("com.sun.star.uno.Exception");
+ includes.add("com.sun.star.uno.RuntimeException");
+ } else {
+ if (!hasRestParameter(cons)) {
+ includes.addAny();
+ includes.addSequence();
+ for (const unoidl::SingleInterfaceBasedServiceEntity::Constructor::Parameter& param :
+ cons.parameters) {
+ if (m_typeMgr->getSort(
+ b2u(codemaker::UnoType::decompose(
+ u2b(param.type))))
+ == codemaker::UnoType::Sort::Char) {
+ includes.addCppuUnotypeHxx();
+ break;
+ }
+ }
+ }
+ codemaker::ExceptionTree tree;
+ for (const OUString& ex : cons.exceptions) {
+ tree.add(u2b(ex), m_typeMgr);
+ }
+ if (!tree.getRoot().present) {
+ includes.add("com.sun.star.uno.Exception");
+ includes.add("com.sun.star.uno.RuntimeException");
+ includeExceptions(includes, &tree.getRoot());
+ }
+ }
+ }
+ }
+ OString cppName(
+ codemaker::cpp::translateUnoToCppIdentifier(
+ u2b(id_), "service", isGlobal()));
+ OUString headerDefine(dumpHeaderDefine(o, u"HPP"));
+ o << "\n";
+ includes.dump(o, nullptr, true);
+ if (!entity_->getConstructors().empty()) {
+ o << ("\n#if defined ANDROID || defined IOS //TODO\n"
+ "#include <com/sun/star/lang/XInitialization.hpp>\n"
+ "#include <osl/detail/component-defines.h>\n#endif\n\n"
+ "#if defined LO_URE_CURRENT_ENV && defined LO_URE_CTOR_ENV_")
+ << name_.replaceAll(".", "_dot_")
+ << " && (LO_URE_CURRENT_ENV) == (LO_URE_CTOR_ENV_"
+ << name_.replaceAll(".", "_dot_") << ") && defined LO_URE_CTOR_FUN_"
+ << name_.replaceAll(".", "_dot_")
+ << "\nextern \"C\" ::css::uno::XInterface * SAL_CALL LO_URE_CTOR_FUN_"
+ << name_.replaceAll(".", "_dot_")
+ << "(::css::uno::XComponentContext *, ::css::uno::Sequence< "
+ "::css::uno::Any > const &);\n#endif\n";
+ }
+ o << "\n";
+ if (codemaker::cppumaker::dumpNamespaceOpen(o, name_, false)) {
+ o << "\n";
+ }
+ o << "\nclass " << cppName << " {\n";
+ inc();
+ if (!entity_->getConstructors().empty()) {
+ OString baseName(u2b(entity_->getBase()));
+ OString scopedBaseName(codemaker::cpp::scopedCppName(baseName));
+ o << "public:\n";
+ for (const unoidl::SingleInterfaceBasedServiceEntity::Constructor& cons :
+ entity_->getConstructors()) {
+ if (cons.defaultConstructor) {
+ o << indent() << "static ::css::uno::Reference< "
+ << scopedBaseName << " > "
+ << codemaker::cpp::translateUnoToCppIdentifier(
+ "create", "method", codemaker::cpp::IdentifierTranslationMode::NonGlobal,
+ &cppName)
+ << ("(::css::uno::Reference< ::css::uno::XComponentContext > const &"
+ " the_context) {\n");
+ inc();
+ o << indent() << "assert(the_context.is());\n" << indent()
+ << "::css::uno::Reference< " << scopedBaseName
+ << " > the_instance;\n" << indent() << "try {\n";
+ inc();
+ o << ("#if defined LO_URE_CURRENT_ENV && defined "
+ "LO_URE_CTOR_ENV_")
+ << name_.replaceAll(".", "_dot_")
+ << " && (LO_URE_CURRENT_ENV) == (LO_URE_CTOR_ENV_"
+ << name_.replaceAll(".", "_dot_")
+ << ") && defined LO_URE_CTOR_FUN_"
+ << name_.replaceAll(".", "_dot_") << "\n" << indent()
+ << "the_instance = ::css::uno::Reference< " << scopedBaseName
+ << (" >(::css::uno::Reference< ::css::uno::XInterface >("
+ "static_cast< ::css::uno::XInterface * >((*"
+ "LO_URE_CTOR_FUN_")
+ << name_.replaceAll(".", "_dot_")
+ << (")(the_context.get(), ::css::uno::Sequence<"
+ " ::css::uno::Any >())), ::SAL_NO_ACQUIRE),"
+ " ::css::uno::UNO_QUERY);\n#else\n")
+ << indent() << "the_instance = ::css::uno::Reference< "
+ << scopedBaseName
+ << (" >(the_context->getServiceManager()->"
+ "createInstanceWithContext("
+ " \"")
+ << name_
+ << "\", the_context), ::css::uno::UNO_QUERY);\n#endif\n";
+ dec();
+ o << indent()
+ << "} catch (const ::css::uno::RuntimeException &) {\n";
+ inc();
+ o << indent() << "throw;\n";
+ dec();
+ o << indent()
+ << "} catch (const ::css::uno::Exception & the_exception) {\n";
+ inc();
+ o << indent() << "throw ::css::uno::DeploymentException(";
+ failsToSupply(o, name_, baseName);
+ o << " + \": \" + the_exception.Message, the_context);\n";
+ dec();
+ o << indent() << "}\n" << indent()
+ << "if (!the_instance.is()) {\n";
+ inc();
+ o << indent() << "throw ::css::uno::DeploymentException(";
+ failsToSupply(o, name_, baseName);
+ o << ", the_context);\n";
+ dec();
+ o << indent() << "}\n" << indent() << "return the_instance;\n";
+ dec();
+ o << indent() << "}\n\n";
+ } else {
+ o << indent() << "static ::css::uno::Reference< "
+ << scopedBaseName << " > "
+ << codemaker::cpp::translateUnoToCppIdentifier(
+ u2b(cons.name), "method", codemaker::cpp::IdentifierTranslationMode::NonGlobal,
+ &cppName)
+ << ("(::css::uno::Reference< ::css::uno::XComponentContext > const &"
+ " the_context");
+ bool rest = hasRestParameter(cons);
+ for (const unoidl::SingleInterfaceBasedServiceEntity::Constructor::Parameter& param :
+ cons.parameters) {
+ o << ", ";
+ OUStringBuffer buf(2 + param.type.getLength());
+ if (param.rest) {
+ buf.append("[]");
+ }
+ buf.append(param.type);
+ OUString type(buf.makeStringAndClear());
+ bool byRef = passByReference(type);
+ dumpType(o, type, byRef, byRef);
+ o << " "
+ << codemaker::cpp::translateUnoToCppIdentifier(
+ u2b(param.name), "param", codemaker::cpp::IdentifierTranslationMode::NonGlobal);
+ }
+ o << ") {\n";
+ inc();
+ o << indent() << "assert(the_context.is());\n";
+ if (!rest && !cons.parameters.empty()) {
+ o << indent()
+ << "::css::uno::Sequence< ::css::uno::Any > the_arguments("
+ << cons.parameters.size() << ");\n";
+ o << indent()
+ << "::css::uno::Any* the_arguments_array = the_arguments.getArray();\n";
+
+ std::vector<
+ unoidl::SingleInterfaceBasedServiceEntity::Constructor::
+ Parameter >::size_type n = 0;
+ for (const unoidl::SingleInterfaceBasedServiceEntity::Constructor::Parameter& j :
+ cons.parameters) {
+ o << indent() << "the_arguments_array[" << n++ << "] ";
+ OString param(
+ codemaker::cpp::translateUnoToCppIdentifier(
+ u2b(j.name), "param",
+ codemaker::cpp::IdentifierTranslationMode::NonGlobal));
+ sal_Int32 rank;
+ if (resolveOuterTypedefs(j.type) == "any") {
+ o << "= " << param;
+ } else if (m_typeMgr->getSort(
+ b2u(codemaker::UnoType::decompose(
+ u2b(j.type), &rank)))
+ == codemaker::UnoType::Sort::Char) {
+ o << "= ::css::uno::Any(&" << param
+ << ", ::cppu::UnoType< ";
+ for (sal_Int32 k = 0; k < rank; ++k) {
+ o << "::cppu::UnoSequenceType< ";
+ }
+ o << "::cppu::UnoCharType";
+ for (sal_Int32 k = 0; k < rank; ++k) {
+ o << " >";
+ }
+ o << " >::get())";
+ } else {
+ o << "<<= " << param;
+ }
+ o << ";\n";
+ }
+ }
+ o << indent() << "::css::uno::Reference< "
+ << scopedBaseName << " > the_instance;\n";
+ codemaker::ExceptionTree tree;
+ for (const OUString& ex : cons.exceptions) {
+ tree.add(u2b(ex), m_typeMgr);
+ }
+ if (!tree.getRoot().present) {
+ o << indent() << "try {\n";
+ inc();
+ }
+ o << ("#if defined LO_URE_CURRENT_ENV && defined "
+ "LO_URE_CTOR_ENV_")
+ << name_.replaceAll(".", "_dot_")
+ << " && (LO_URE_CURRENT_ENV) == (LO_URE_CTOR_ENV_"
+ << name_.replaceAll(".", "_dot_")
+ << ") && defined LO_URE_CTOR_FUN_"
+ << name_.replaceAll(".", "_dot_") << "\n" << indent()
+ << "the_instance = ::css::uno::Reference< " << scopedBaseName
+ << (" >(::css::uno::Reference< ::css::uno::XInterface >("
+ "static_cast< ::css::uno::XInterface * >((*"
+ "LO_URE_CTOR_FUN_")
+ << name_.replaceAll(".", "_dot_")
+ << ")(the_context.get(), ";
+ if (rest) {
+ o << codemaker::cpp::translateUnoToCppIdentifier(
+ u2b(cons.parameters.back().name), "param",
+ codemaker::cpp::IdentifierTranslationMode::NonGlobal);
+ } else if (cons.parameters.empty()) {
+ o << "::css::uno::Sequence< ::css::uno::Any >()";
+ } else {
+ o << "the_arguments";
+ }
+ o << ")), ::SAL_NO_ACQUIRE), ::css::uno::UNO_QUERY);\n" << indent()
+ << ("::css::uno::Reference< ::css::lang::XInitialization > "
+ "init(the_instance, ::css::uno::UNO_QUERY);\n")
+ << indent() << "if (init.is()) {\n"
+ << indent() << " init->initialize(";
+ if (cons.parameters.empty()) {
+ o << "::css::uno::Sequence< ::css::uno::Any >()";
+ } else {
+ o << "the_arguments";
+ }
+ o << ");\n" << indent() << "}\n";
+ o << "#else\n"
+ << indent() << "the_instance = ::css::uno::Reference< "
+ << scopedBaseName
+ << (" >(the_context->getServiceManager()->"
+ "createInstanceWithArgumentsAndContext("
+ " \"")
+ << name_ << "\", ";
+ if (rest) {
+ o << codemaker::cpp::translateUnoToCppIdentifier(
+ u2b(cons.parameters.back().name), "param",
+ codemaker::cpp::IdentifierTranslationMode::NonGlobal);
+ } else if (cons.parameters.empty()) {
+ o << "::css::uno::Sequence< ::css::uno::Any >()";
+ } else {
+ o << "the_arguments";
+ }
+ o << ", the_context), ::css::uno::UNO_QUERY);\n#endif\n";
+ if (!tree.getRoot().present) {
+ dec();
+ o << indent()
+ << "} catch (const ::css::uno::RuntimeException &) {\n";
+ inc();
+ o << indent() << "throw;\n";
+ dec();
+ dumpCatchClauses(o, &tree.getRoot());
+ o << indent()
+ << ("} catch (const ::css::uno::Exception &"
+ " the_exception) {\n");
+ inc();
+ o << indent() << "throw ::css::uno::DeploymentException(";
+ failsToSupply(o, name_, baseName);
+ o << " + \": \" + the_exception.Message, the_context);\n";
+ dec();
+ o << indent() << "}\n";
+ }
+ o << indent() << "if (!the_instance.is()) {\n";
+ inc();
+ o << indent() << "throw ::css::uno::DeploymentException(";
+ failsToSupply(o, name_, baseName);
+ o << ", the_context);\n";
+ dec();
+ o << indent() << "}\n" << indent() << "return the_instance;\n";
+ dec();
+ o << indent() << "}\n\n";
+ }
+ }
+ }
+ o << "private:\n";
+ o << indent() << cppName << "(); // not implemented\n"
+ << indent() << cppName << "(" << cppName << " &); // not implemented\n"
+ << indent() << "~" << cppName << "(); // not implemented\n"
+ << indent() << "void operator =(" << cppName << "); // not implemented\n";
+ dec();
+ o << "};\n\n";
+ if (codemaker::cppumaker::dumpNamespaceClose(o, name_, false)) {
+ o << "\n";
+ }
+ o << "\n#endif // "<< headerDefine << "\n";
+}
+
+void ServiceType::dumpCatchClauses(
+ FileStream & out, codemaker::ExceptionTreeNode const * node)
+{
+ if (node->present) {
+ out << indent() << "} catch (const ";
+ dumpType(out, b2u(node->name));
+ out << " &) {\n";
+ inc();
+ out << indent() << "throw;\n";
+ dec();
+ } else {
+ for (std::unique_ptr<codemaker::ExceptionTreeNode> const & pChild : node->children) {
+ dumpCatchClauses(out, pChild.get());
+ }
+ }
+}
+
+class SingletonType: public ConstructiveType
+{
+public:
+ SingletonType(
+ rtl::Reference< unoidl::InterfaceBasedSingletonEntity > const & entity,
+ OUString const & name, rtl::Reference< TypeManager > const & manager):
+ ConstructiveType(name, manager), entity_(entity) {
+ assert(entity.is());
+ }
+
+private:
+ virtual void dumpHppFile(
+ FileStream & o, codemaker::cppumaker::Includes & includes) override;
+
+ rtl::Reference< unoidl::InterfaceBasedSingletonEntity > entity_;
+};
+
+void SingletonType::dumpHppFile(
+ FileStream & o, codemaker::cppumaker::Includes & includes)
+{
+ OString cppName(
+ codemaker::cpp::translateUnoToCppIdentifier(
+ u2b(id_), "singleton", isGlobal()));
+ OString baseName(u2b(entity_->getBase()));
+ OString scopedBaseName(codemaker::cpp::scopedCppName(baseName));
+ OUString headerDefine(dumpHeaderDefine(o, u"HPP"));
+ o << "\n";
+ //TODO: Decide whether the types added to includes should rather be added to
+ // m_dependencies (and thus be generated during dumpDependedTypes):
+ includes.add("com.sun.star.uno.DeploymentException");
+ includes.add("com.sun.star.uno.XComponentContext");
+ includes.addCassert();
+ includes.addAny();
+ includes.addReference();
+ includes.addRtlUstringH();
+ includes.addRtlUstringHxx();
+ includes.dump(o, nullptr, true);
+ o << ("\n#if defined ANDROID || defined IOS //TODO\n"
+ "#include <com/sun/star/lang/XInitialization.hpp>\n"
+ "#include <osl/detail/component-defines.h>\n#endif\n\n"
+ "#if defined LO_URE_CURRENT_ENV && defined LO_URE_CTOR_ENV_")
+ << name_.replaceAll(".", "_dot_")
+ << " && (LO_URE_CURRENT_ENV) == (LO_URE_CTOR_ENV_"
+ << name_.replaceAll(".", "_dot_") << ") && defined LO_URE_CTOR_FUN_"
+ << name_.replaceAll(".", "_dot_")
+ << "\nextern \"C\" ::css::uno::XInterface * SAL_CALL LO_URE_CTOR_FUN_"
+ << name_.replaceAll(".", "_dot_")
+ << "(::css::uno::XComponentContext *, ::css::uno::Sequence< "
+ "::css::uno::Any > const &);\n#endif\n";
+ o << "\n";
+ if (codemaker::cppumaker::dumpNamespaceOpen(o, name_, false)) {
+ o << "\n";
+ }
+ o << "\nclass " << cppName << " {\npublic:\n";
+ inc();
+ o << indent() << "static ::css::uno::Reference< "
+ << scopedBaseName << " > "
+ << codemaker::cpp::translateUnoToCppIdentifier(
+ "get", "method", codemaker::cpp::IdentifierTranslationMode::NonGlobal, &cppName)
+ << ("(::css::uno::Reference<"
+ " ::css::uno::XComponentContext > const & the_context)"
+ " {\n");
+ inc();
+ o << indent() << "assert(the_context.is());\n" << indent()
+ << "::css::uno::Reference< " << scopedBaseName
+ << (" > instance;\n#if defined LO_URE_CURRENT_ENV && defined "
+ "LO_URE_CTOR_ENV_")
+ << name_.replaceAll(".", "_dot_")
+ << " && (LO_URE_CURRENT_ENV) == (LO_URE_CTOR_ENV_"
+ << name_.replaceAll(".", "_dot_")
+ << ") && defined LO_URE_CTOR_FUN_"
+ << name_.replaceAll(".", "_dot_") << "\n" << indent()
+ << "instance = ::css::uno::Reference< " << scopedBaseName
+ << (" >(::css::uno::Reference< ::css::uno::XInterface >("
+ "static_cast< ::css::uno::XInterface * >((*"
+ "LO_URE_CTOR_FUN_")
+ << name_.replaceAll(".", "_dot_")
+ << (")(the_context.get(), ::css::uno::Sequence<"
+ " ::css::uno::Any >())), ::SAL_NO_ACQUIRE),"
+ " ::css::uno::UNO_QUERY);\n#else\n")
+ << indent() << ("the_context->getValueByName("
+ "::rtl::OUString( \"/singletons/")
+ << name_ << "\" )) >>= instance;\n#endif\n"
+ << indent() << "if (!instance.is()) {\n";
+ inc();
+ o << indent()
+ << ("throw ::css::uno::DeploymentException("
+ "::rtl::OUString( \"component context"
+ " fails to supply singleton ")
+ << name_ << " of type " << baseName << "\" ), the_context);\n";
+ dec();
+ o << indent() << "}\n" << indent() << "return instance;\n";
+ dec();
+ o << indent() << "}\n\n";
+ o << "private:\n";
+ o << indent() << cppName << "(); // not implemented\n"
+ << indent() << cppName << "(" << cppName << " &); // not implemented\n"
+ << indent() << "~" << cppName << "(); // not implemented\n"
+ << indent() << "void operator =(" << cppName << "); // not implemented\n";
+ dec();
+ o << "};\n\n";
+ if (codemaker::cppumaker::dumpNamespaceClose(o, name_, false)) {
+ o << "\n";
+ }
+ o << "\n#endif // "<< headerDefine << "\n";
+}
+
+}
+
+void produce(
+ OUString const & name, rtl::Reference< TypeManager > const & manager,
+ codemaker::GeneratedTypeSet & generated, CppuOptions const & options)
+{
+ if (generated.contains(u2b(name))) {
+ return;
+ }
+ generated.add(u2b(name));
+ if (!manager->foundAtPrimaryProvider(name)) {
+ return;
+ }
+ rtl::Reference< unoidl::Entity > ent;
+ rtl::Reference< unoidl::MapCursor > cur;
+ switch (manager->getSort(name, &ent, &cur)) {
+ case codemaker::UnoType::Sort::Module: {
+ OUString prefix;
+ if (!name.isEmpty()) {
+ prefix = name + ".";
+ }
+ for (;;) {
+ OUString mem;
+ if (!cur->getNext(&mem).is()) {
+ break;
+ }
+ produce(prefix + mem, manager, generated, options);
+ }
+ break;
+ }
+ case codemaker::UnoType::Sort::Enum: {
+ EnumType t(
+ dynamic_cast< unoidl::EnumTypeEntity * >(ent.get()), name,
+ manager);
+ t.dump(options);
+ t.dumpDependedTypes(generated, options);
+ break;
+ }
+ case codemaker::UnoType::Sort::PlainStruct: {
+ PlainStructType t(
+ dynamic_cast< unoidl::PlainStructTypeEntity * >(ent.get()),
+ name, manager);
+ t.dump(options);
+ t.dumpDependedTypes(generated, options);
+ break;
+ }
+ case codemaker::UnoType::Sort::PolymorphicStructTemplate: {
+ PolyStructType t(
+ dynamic_cast< unoidl::PolymorphicStructTypeTemplateEntity * >(
+ ent.get()),
+ name, manager);
+ t.dump(options);
+ t.dumpDependedTypes(generated, options);
+ break;
+ }
+ case codemaker::UnoType::Sort::Exception: {
+ ExceptionType t(
+ dynamic_cast< unoidl::ExceptionTypeEntity * >(ent.get()), name,
+ manager);
+ t.dump(options);
+ t.dumpDependedTypes(generated, options);
+ break;
+ }
+ case codemaker::UnoType::Sort::Interface: {
+ InterfaceType t(
+ dynamic_cast< unoidl::InterfaceTypeEntity * >(ent.get()), name,
+ manager);
+ t.dump(options);
+ t.dumpDependedTypes(generated, options);
+ break;
+ }
+ case codemaker::UnoType::Sort::Typedef: {
+ Typedef t(
+ dynamic_cast< unoidl::TypedefEntity * >(ent.get()), name,
+ manager);
+ t.dump(options);
+ t.dumpDependedTypes(generated, options);
+ break;
+ }
+ case codemaker::UnoType::Sort::ConstantGroup: {
+ ConstantGroup t(
+ dynamic_cast< unoidl::ConstantGroupEntity * >(ent.get()), name,
+ manager);
+ if (t.hasConstants()) {
+ t.dump(options);
+ }
+ break;
+ }
+ case codemaker::UnoType::Sort::SingleInterfaceBasedService: {
+ ServiceType t(
+ dynamic_cast< unoidl::SingleInterfaceBasedServiceEntity * >(
+ ent.get()),
+ name, manager);
+ t.dump(options);
+ t.dumpDependedTypes(generated, options);
+ break;
+ }
+ case codemaker::UnoType::Sort::InterfaceBasedSingleton: {
+ SingletonType t(
+ dynamic_cast< unoidl::InterfaceBasedSingletonEntity * >(
+ ent.get()),
+ name, manager);
+ t.dump(options);
+ t.dumpDependedTypes(generated, options);
+ break;
+ }
+ case codemaker::UnoType::Sort::AccumulationBasedService:
+ case codemaker::UnoType::Sort::ServiceBasedSingleton:
+ break;
+ default:
+ throw CannotDumpException(
+ "unexpected entity \"" + name + "\" in call to produce");
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/codemaker/source/cppumaker/cpputype.hxx b/codemaker/source/cppumaker/cpputype.hxx
new file mode 100644
index 000000000..40fc94f26
--- /dev/null
+++ b/codemaker/source/cppumaker/cpputype.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 .
+ */
+
+#pragma once
+
+#include <sal/config.h>
+
+#include <rtl/ref.hxx>
+
+namespace codemaker { class GeneratedTypeSet; }
+namespace rtl { class OUString; }
+class CppuOptions;
+class TypeManager;
+
+void produce(
+ OUString const & name, rtl::Reference< TypeManager > const & manager,
+ codemaker::GeneratedTypeSet & generated, CppuOptions const & options);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/codemaker/source/cppumaker/dependencies.cxx b/codemaker/source/cppumaker/dependencies.cxx
new file mode 100644
index 000000000..1af6b9d46
--- /dev/null
+++ b/codemaker/source/cppumaker/dependencies.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 <cassert>
+#include <utility>
+#include <vector>
+
+#include <codemaker/global.hxx>
+#include <codemaker/typemanager.hxx>
+#include <codemaker/unotype.hxx>
+
+#include <rtl/ref.hxx>
+#include <rtl/string.hxx>
+#include <rtl/ustring.hxx>
+#include <sal/types.h>
+#include <unoidl/unoidl.hxx>
+
+#include "dependencies.hxx"
+
+namespace codemaker::cppumaker {
+
+Dependencies::Dependencies(
+ rtl::Reference< TypeManager > const & manager, OUString const & name):
+ m_manager(manager), m_voidDependency(false), m_booleanDependency(false),
+ m_byteDependency(false), m_shortDependency(false),
+ m_unsignedShortDependency(false), m_longDependency(false),
+ m_unsignedLongDependency(false), m_hyperDependency(false),
+ m_unsignedHyperDependency(false), m_charDependency(false),
+ m_stringDependency(false), m_typeDependency(false), m_anyDependency(false),
+ m_sequenceDependency(false)
+{
+ assert(manager.is());
+ rtl::Reference< unoidl::Entity > ent;
+ switch (m_manager->getSort(name, &ent)) {
+ case UnoType::Sort::Enum:
+ break;
+ case UnoType::Sort::PlainStruct:
+ {
+ rtl::Reference< unoidl::PlainStructTypeEntity > ent2(
+ static_cast< unoidl::PlainStructTypeEntity * >(ent.get()));
+ if (!ent2->getDirectBase().isEmpty()) {
+ insert(ent2->getDirectBase(), KIND_NORMAL);
+ }
+ for (const unoidl::PlainStructTypeEntity::Member& member : ent2->getDirectMembers())
+ {
+ insert(member.type, KIND_NORMAL);
+ }
+ break;
+ }
+ case UnoType::Sort::PolymorphicStructTemplate:
+ {
+ rtl::Reference< unoidl::PolymorphicStructTypeTemplateEntity > ent2(
+ static_cast< unoidl::PolymorphicStructTypeTemplateEntity * >(
+ ent.get()));
+ for (const unoidl::PolymorphicStructTypeTemplateEntity::Member& member : ent2->getMembers())
+ {
+ if (!member.parameterized) {
+ insert(member.type, KIND_NORMAL);
+ }
+ }
+ break;
+ }
+ case UnoType::Sort::Exception:
+ {
+ rtl::Reference< unoidl::ExceptionTypeEntity > ent2(
+ static_cast< unoidl::ExceptionTypeEntity * >(ent.get()));
+ if (!ent2->getDirectBase().isEmpty()) {
+ insert(ent2->getDirectBase(), KIND_NORMAL);
+ }
+ for (const unoidl::ExceptionTypeEntity::Member& member : ent2->getDirectMembers())
+ {
+ insert(member.type, KIND_NORMAL);
+ }
+ break;
+ }
+ case UnoType::Sort::Interface:
+ {
+ rtl::Reference< unoidl::InterfaceTypeEntity > ent2(
+ static_cast< unoidl::InterfaceTypeEntity * >(ent.get()));
+ for (const unoidl::AnnotatedReference& ar : ent2->getDirectMandatoryBases())
+ {
+ insert(ar.name, KIND_BASE);
+ }
+ if (!(ent2->getDirectAttributes().empty()
+ && ent2->getDirectMethods().empty()))
+ {
+ insert(u"com.sun.star.uno.RuntimeException", KIND_EXCEPTION);
+ }
+ for (const unoidl::InterfaceTypeEntity::Attribute& attr : ent2->getDirectAttributes())
+ {
+ insert(attr.type, KIND_NORMAL);
+ for (const OUString& ex : attr.getExceptions)
+ {
+ insert(ex, KIND_EXCEPTION);
+ }
+ for (const OUString& ex : attr.setExceptions)
+ {
+ insert(ex, KIND_EXCEPTION);
+ }
+ }
+ for (const unoidl::InterfaceTypeEntity::Method& method : ent2->getDirectMethods())
+ {
+ insert(method.returnType, KIND_NORMAL);
+ for (const unoidl::InterfaceTypeEntity::Method::Parameter& param : method.parameters)
+ {
+ insert(param.type, KIND_NORMAL);
+ }
+ for (const OUString& ex : method.exceptions)
+ {
+ insert(ex, KIND_EXCEPTION);
+ }
+ }
+ break;
+ }
+ case UnoType::Sort::Typedef:
+ insert(
+ static_cast< unoidl::TypedefEntity * >(ent.get())->getType(),
+ KIND_NORMAL);
+ break;
+ case UnoType::Sort::ConstantGroup:
+ {
+ rtl::Reference< unoidl::ConstantGroupEntity > ent2(
+ static_cast< unoidl::ConstantGroupEntity * >(ent.get()));
+ for (const unoidl::ConstantGroupEntity::Member& member : ent2->getMembers())
+ {
+ switch (member.value.type) {
+ case unoidl::ConstantValue::TYPE_BOOLEAN:
+ m_booleanDependency = true;
+ break;
+ case unoidl::ConstantValue::TYPE_BYTE:
+ m_byteDependency = true;
+ break;
+ case unoidl::ConstantValue::TYPE_SHORT:
+ m_shortDependency = true;
+ break;
+ case unoidl::ConstantValue::TYPE_UNSIGNED_SHORT:
+ m_unsignedShortDependency = true;
+ break;
+ case unoidl::ConstantValue::TYPE_LONG:
+ m_longDependency = true;
+ break;
+ case unoidl::ConstantValue::TYPE_UNSIGNED_LONG:
+ m_unsignedLongDependency = true;
+ break;
+ case unoidl::ConstantValue::TYPE_HYPER:
+ m_hyperDependency = true;
+ break;
+ case unoidl::ConstantValue::TYPE_UNSIGNED_HYPER:
+ m_unsignedHyperDependency = true;
+ break;
+ case unoidl::ConstantValue::TYPE_FLOAT:
+ break;
+ case unoidl::ConstantValue::TYPE_DOUBLE:
+ break;
+ }
+ }
+ break;
+ }
+ case UnoType::Sort::SingleInterfaceBasedService:
+ {
+ rtl::Reference< unoidl::SingleInterfaceBasedServiceEntity > ent2(
+ static_cast< unoidl::SingleInterfaceBasedServiceEntity * >(
+ ent.get()));
+ if (!ent2->getConstructors().empty()) {
+ insert(ent2->getBase(), KIND_NORMAL);
+ }
+ for (const unoidl::SingleInterfaceBasedServiceEntity::Constructor& cons : ent2->getConstructors())
+ {
+ for (const unoidl::SingleInterfaceBasedServiceEntity::Constructor::Parameter& param
+ : cons.parameters)
+ {
+ insert(param.type, KIND_NORMAL);
+ if (param.rest) {
+ m_sequenceDependency = true;
+ }
+ }
+ for (const OUString& ex : cons.exceptions)
+ {
+ insert(ex, KIND_EXCEPTION);
+ }
+ }
+ break;
+ }
+ case UnoType::Sort::InterfaceBasedSingleton:
+ insert(
+ static_cast< unoidl::InterfaceBasedSingletonEntity * >(ent.get())->
+ getBase(),
+ KIND_NORMAL);
+ break;
+ default:
+ assert(false); // this cannot happen
+ }
+}
+
+Dependencies::~Dependencies() {}
+
+void Dependencies::insert(std::u16string_view name, Kind kind) {
+ sal_Int32 k;
+ std::vector< OString > args;
+ OUString n(b2u(UnoType::decompose(u2b(name), &k, &args)));
+ if (k != 0) {
+ m_sequenceDependency = true;
+ }
+ switch (m_manager->getSort(n)) {
+ case UnoType::Sort::Void:
+ m_voidDependency = true;
+ break;
+ case UnoType::Sort::Boolean:
+ m_booleanDependency = true;
+ break;
+ case UnoType::Sort::Byte:
+ m_byteDependency = true;
+ break;
+ case UnoType::Sort::Short:
+ m_shortDependency = true;
+ break;
+ case UnoType::Sort::UnsignedShort:
+ m_unsignedShortDependency = true;
+ break;
+ case UnoType::Sort::Long:
+ m_longDependency = true;
+ break;
+ case UnoType::Sort::UnsignedLong:
+ m_unsignedLongDependency = true;
+ break;
+ case UnoType::Sort::Hyper:
+ m_hyperDependency = true;
+ break;
+ case UnoType::Sort::UnsignedHyper:
+ m_unsignedHyperDependency = true;
+ break;
+ case UnoType::Sort::Float:
+ break;
+ case UnoType::Sort::Double:
+ break;
+ case UnoType::Sort::Char:
+ m_charDependency = true;
+ break;
+ case UnoType::Sort::String:
+ m_stringDependency = true;
+ break;
+ case UnoType::Sort::Type:
+ m_typeDependency = true;
+ break;
+ case UnoType::Sort::Any:
+ m_anyDependency = true;
+ break;
+ case UnoType::Sort::PolymorphicStructTemplate:
+ for (const OString& arg : args)
+ {
+ insert(b2u(arg), KIND_NORMAL);
+ }
+ [[fallthrough]];
+ case UnoType::Sort::Sequence:
+ case UnoType::Sort::Enum:
+ case UnoType::Sort::PlainStruct:
+ case UnoType::Sort::Exception:
+ case UnoType::Sort::Interface:
+ case UnoType::Sort::Typedef:
+ {
+ std::pair< Map::iterator, bool > i(
+ m_map.emplace(n, kind));
+ if (!i.second && kind == KIND_BASE) {
+ assert(i.first->second != KIND_EXCEPTION);
+ i.first->second = KIND_BASE;
+ }
+ break;
+ }
+ default:
+ throw CannotDumpException(
+ OUString::Concat("unexpected type \"") + name
+ + "\" in call to codemaker::cppumaker::Dependencies::Dependencies");
+ }
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/codemaker/source/cppumaker/dependencies.hxx b/codemaker/source/cppumaker/dependencies.hxx
new file mode 100644
index 000000000..0071397aa
--- /dev/null
+++ b/codemaker/source/cppumaker/dependencies.hxx
@@ -0,0 +1,126 @@
+/* -*- 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/config.h>
+
+#include <map>
+#include <string_view>
+
+#include <rtl/ref.hxx>
+
+namespace rtl { class OUString; }
+class TypeManager;
+
+/// @HTML
+
+namespace codemaker::cppumaker {
+
+/**
+ A simple class to track which other entities a given entity depends on.
+
+ <p>This class is not multi-thread&ndash;safe.</p>
+ */
+class Dependencies {
+public:
+ /**
+ Flags to distinguish whether one entity depends on another entity because
+ the second is a direct base of the first or an exception thrown by the
+ first.
+ */
+ enum Kind { KIND_NORMAL, KIND_BASE, KIND_EXCEPTION };
+
+ typedef std::map< OUString, Kind > Map;
+
+ /**
+ Constructs the dependencies for a given entity.
+
+ @param manager a type manager, to obtain information about the given
+ entity; must not be null
+
+ @param name the UNOIDL name of an enum type, plain struct type,
+ polymorphic struct type template, exception type, interface type,
+ typedef, constant group, single-interface--based service, or
+ interface-based singleton entity
+ */
+ Dependencies(
+ rtl::Reference< TypeManager > const & manager,
+ OUString const & name);
+
+ ~Dependencies();
+
+ Dependencies(const Dependencies&) = delete;
+ const Dependencies& operator=(const Dependencies&) = delete;
+
+ Map const & getMap() const { return m_map; }
+
+ bool hasBooleanDependency() const { return m_booleanDependency; }
+
+ bool hasByteDependency() const { return m_byteDependency; }
+
+ bool hasShortDependency() const { return m_shortDependency; }
+
+ bool hasUnsignedShortDependency() const
+ { return m_unsignedShortDependency; }
+
+ bool hasLongDependency() const { return m_longDependency; }
+
+ bool hasUnsignedLongDependency() const
+ { return m_unsignedLongDependency; }
+
+ bool hasHyperDependency() const { return m_hyperDependency; }
+
+ bool hasUnsignedHyperDependency() const
+ { return m_unsignedHyperDependency; }
+
+ bool hasCharDependency() const { return m_charDependency; }
+
+ bool hasStringDependency() const { return m_stringDependency; }
+
+ bool hasTypeDependency() const { return m_typeDependency; }
+
+ bool hasAnyDependency() const { return m_anyDependency; }
+
+ bool hasSequenceDependency() const { return m_sequenceDependency; }
+
+private:
+ void insert(std::u16string_view name, Kind kind);
+
+ rtl::Reference< TypeManager > m_manager;
+ Map m_map;
+ bool m_voidDependency;
+ bool m_booleanDependency;
+ bool m_byteDependency;
+ bool m_shortDependency;
+ bool m_unsignedShortDependency;
+ bool m_longDependency;
+ bool m_unsignedLongDependency;
+ bool m_hyperDependency;
+ bool m_unsignedHyperDependency;
+ bool m_charDependency;
+ bool m_stringDependency;
+ bool m_typeDependency;
+ bool m_anyDependency;
+ bool m_sequenceDependency;
+};
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/codemaker/source/cppumaker/dumputils.cxx b/codemaker/source/cppumaker/dumputils.cxx
new file mode 100644
index 000000000..2a3e809e7
--- /dev/null
+++ b/codemaker/source/cppumaker/dumputils.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 "dumputils.hxx"
+
+#include <codemaker/global.hxx>
+
+#include <rtl/ustring.hxx>
+#include <sal/types.h>
+#include <o3tl/string_view.hxx>
+
+
+namespace codemaker::cppumaker {
+
+bool dumpNamespaceOpen(
+ FileStream & out, std::u16string_view entityName, bool fullModuleType)
+{
+ bool bOutput = false;
+ bool bFirst = true;
+ for (sal_Int32 i = 0; i >= 0;) {
+ std::u16string_view id(o3tl::getToken(entityName, 0, '.', i));
+ if (fullModuleType || i >= 0) {
+ if (!bFirst) {
+ out << " ";
+ }
+ out << "namespace " << id << " {";
+ bFirst = false;
+ bOutput = true;
+ }
+ }
+ return bOutput;
+}
+
+bool dumpNamespaceClose(
+ FileStream & out, std::u16string_view entityName, bool fullModuleType)
+{
+ bool bOutput = false;
+ bool bFirst = true;
+ for (size_t i = 0; i != std::u16string_view::npos;) {
+ i = entityName.find('.', i);
+ if (i != std::u16string_view::npos) {
+ ++i;
+ }
+ if (fullModuleType || i != std::u16string_view::npos) {
+ if (!bFirst) {
+ out << " ";
+ }
+ out << "}";
+ bFirst = false;
+ bOutput = true;
+ }
+ }
+ return bOutput;
+}
+
+void dumpTypeIdentifier(FileStream & out, std::u16string_view entityName) {
+ out << entityName.substr(entityName.rfind('.') + 1);
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/codemaker/source/cppumaker/dumputils.hxx b/codemaker/source/cppumaker/dumputils.hxx
new file mode 100644
index 000000000..24e5bae3b
--- /dev/null
+++ b/codemaker/source/cppumaker/dumputils.hxx
@@ -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 .
+ */
+
+#pragma once
+
+#include <sal/config.h>
+#include <string_view>
+
+namespace rtl
+{
+class OUString;
+}
+class FileStream;
+
+namespace codemaker::cppumaker
+{
+bool dumpNamespaceOpen(FileStream& out, std::u16string_view entityName, bool fullModuleType);
+
+bool dumpNamespaceClose(FileStream& out, std::u16string_view entityName, bool fullModuleType);
+
+void dumpTypeIdentifier(FileStream& out, std::u16string_view entityName);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/codemaker/source/cppumaker/includes.cxx b/codemaker/source/cppumaker/includes.cxx
new file mode 100644
index 000000000..9dacdf268
--- /dev/null
+++ b/codemaker/source/cppumaker/includes.cxx
@@ -0,0 +1,273 @@
+/* -*- 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 "includes.hxx"
+
+#include "dependencies.hxx"
+#include "dumputils.hxx"
+
+#include <codemaker/global.hxx>
+#include <codemaker/typemanager.hxx>
+#include <codemaker/unotype.hxx>
+
+#include <osl/diagnose.h>
+#include <rtl/ref.hxx>
+#include <rtl/string.hxx>
+#include <rtl/ustring.hxx>
+#include <sal/types.h>
+
+#include <utility>
+#include <vector>
+
+using codemaker::cppumaker::Includes;
+
+Includes::Includes(
+ rtl::Reference< TypeManager > manager,
+ codemaker::cppumaker::Dependencies const & dependencies, bool hpp):
+ m_manager(std::move(manager)), m_map(dependencies.getMap()), m_hpp(hpp),
+ m_includeCassert(false),
+ m_includeAny(dependencies.hasAnyDependency()), m_includeReference(false),
+ m_includeSequence(dependencies.hasSequenceDependency()),
+ m_includeType(dependencies.hasTypeDependency()),
+ m_includeCppuMacrosHxx(false), m_includeCppuUnotypeHxx(false),
+ m_includeOslMutexHxx(false),
+ m_includeRtlStrbufHxx(false), m_includeRtlStringH(false),
+ m_includeRtlTextencH(false), m_includeRtlUstrbufHxx(false),
+ m_includeRtlUstringH(false),
+ m_includeRtlUstringHxx(dependencies.hasStringDependency()),
+ m_includeRtlInstanceHxx(false),
+ m_includeSalTypesH(
+ dependencies.hasBooleanDependency() || dependencies.hasByteDependency()
+ || dependencies.hasShortDependency()
+ || dependencies.hasUnsignedShortDependency()
+ || dependencies.hasLongDependency()
+ || dependencies.hasUnsignedLongDependency()
+ || dependencies.hasHyperDependency()
+ || dependencies.hasUnsignedHyperDependency()
+ || dependencies.hasCharDependency()),
+ m_includeTypelibTypeclassH(false),
+ m_includeTypelibTypedescriptionH(false)
+{}
+
+Includes::~Includes()
+{}
+
+void Includes::add(OString const & entityName) {
+ sal_Int32 k;
+ std::vector< OString > args;
+ OUString n(b2u(codemaker::UnoType::decompose(entityName, &k, &args)));
+ if (k != 0) {
+ m_includeSequence = true;
+ }
+ switch (m_manager->getSort(n)) {
+ case codemaker::UnoType::Sort::Boolean:
+ case codemaker::UnoType::Sort::Byte:
+ case codemaker::UnoType::Sort::Short:
+ case codemaker::UnoType::Sort::UnsignedShort:
+ case codemaker::UnoType::Sort::Long:
+ case codemaker::UnoType::Sort::UnsignedLong:
+ case codemaker::UnoType::Sort::Hyper:
+ case codemaker::UnoType::Sort::UnsignedHyper:
+ case codemaker::UnoType::Sort::Char:
+ m_includeSalTypesH = true;
+ break;
+ case codemaker::UnoType::Sort::Float:
+ case codemaker::UnoType::Sort::Double:
+ break;
+ case codemaker::UnoType::Sort::String:
+ m_includeRtlUstringHxx = true;
+ break;
+ case codemaker::UnoType::Sort::Type:
+ m_includeType = true;
+ break;
+ case codemaker::UnoType::Sort::Any:
+ m_includeAny = true;
+ break;
+ case codemaker::UnoType::Sort::PolymorphicStructTemplate:
+ for (const OString& arg : args)
+ {
+ add(arg);
+ }
+ [[fallthrough]];
+ case codemaker::UnoType::Sort::Sequence:
+ case codemaker::UnoType::Sort::Enum:
+ case codemaker::UnoType::Sort::PlainStruct:
+ case codemaker::UnoType::Sort::Exception:
+ case codemaker::UnoType::Sort::Interface:
+ case codemaker::UnoType::Sort::Typedef:
+ m_map.emplace(n, Dependencies::KIND_NORMAL);
+ break;
+ default:
+ throw CannotDumpException(
+ "unexpected type \"" + b2u(entityName)
+ + "\" in call to codemaker::cppumaker::Includes::add");
+ }
+}
+
+namespace {
+
+void dumpEmptyLineBeforeFirst(FileStream & out, bool * first) {
+ OSL_ASSERT(first != nullptr);
+ if (*first) {
+ out << "\n";
+ *first = false;
+ }
+}
+
+}
+
+void Includes::dump(
+ FileStream & out, OUString const * companionHdl, bool exceptions)
+{
+ OSL_ASSERT(companionHdl == nullptr || m_hpp);
+ if (!m_includeReference) {
+ for (const auto& pair : m_map)
+ {
+ if (isInterfaceType(u2b(pair.first))) {
+ m_includeReference = true;
+ break;
+ }
+ }
+ }
+ out << "#include \"sal/config.h\"\n";
+ if (m_includeCassert) {
+ out << "\n#include <cassert>\n";
+ }
+ if (companionHdl) {
+ out << "\n";
+ dumpInclude(out, u2b(*companionHdl), false);
+ }
+ bool first = true;
+ for (const auto& pair : m_map)
+ {
+ if (exceptions || pair.second != Dependencies::KIND_EXCEPTION) {
+ dumpEmptyLineBeforeFirst(out, &first);
+ if (m_hpp || pair.second == Dependencies::KIND_BASE
+ || !isInterfaceType(u2b(pair.first)))
+ {
+ // If we know our name, then avoid including ourselves.
+ if (!companionHdl || *companionHdl != pair.first) {
+ dumpInclude(out, u2b(pair.first), m_hpp);
+ }
+ } else {
+ bool ns = dumpNamespaceOpen(out, pair.first, false);
+ if (ns) {
+ out << " ";
+ }
+ out << "class ";
+ dumpTypeIdentifier(out, pair.first);
+ out << ";";
+ if (ns) {
+ out << " ";
+ }
+ dumpNamespaceClose(out, pair.first, false);
+ out << "\n";
+ }
+ }
+ }
+ static char const * hxxExtension[2] = { "h", "hxx" };
+ if (m_includeAny) {
+ dumpEmptyLineBeforeFirst(out, &first);
+ out << "#include \"com/sun/star/uno/Any." << hxxExtension[m_hpp]
+ << "\"\n";
+ }
+ if (m_includeReference) {
+ dumpEmptyLineBeforeFirst(out, &first);
+ out << "#include \"com/sun/star/uno/Reference." << hxxExtension[m_hpp]
+ << "\"\n";
+ }
+ if (m_includeSequence) {
+ dumpEmptyLineBeforeFirst(out, &first);
+ out << "#include \"com/sun/star/uno/Sequence." << hxxExtension[m_hpp]
+ << "\"\n";
+ }
+ if (m_includeType) {
+ dumpEmptyLineBeforeFirst(out, &first);
+ out << "#include \"com/sun/star/uno/Type." << hxxExtension[m_hpp]
+ << "\"\n";
+ }
+ if (m_includeCppuMacrosHxx) {
+ dumpEmptyLineBeforeFirst(out, &first);
+ out << "#include \"cppu/macros.hxx\"\n";
+ }
+ if (m_includeCppuUnotypeHxx) {
+ dumpEmptyLineBeforeFirst(out, &first);
+ out << "#include \"cppu/unotype.hxx\"\n";
+ }
+ if (m_includeOslMutexHxx) {
+ dumpEmptyLineBeforeFirst(out, &first);
+ out << "#include \"osl/mutex.hxx\"\n";
+ }
+ if (m_includeRtlStrbufHxx) {
+ dumpEmptyLineBeforeFirst(out, &first);
+ out << "#include \"rtl/strbuf.hxx\"\n";
+ }
+ if (m_includeRtlStringH) {
+ dumpEmptyLineBeforeFirst(out, &first);
+ out << "#include \"rtl/string.h\"\n";
+ }
+ if (m_includeRtlTextencH) {
+ dumpEmptyLineBeforeFirst(out, &first);
+ out << "#include \"rtl/textenc.h\"\n";
+ }
+ if (m_includeRtlUstrbufHxx) {
+ dumpEmptyLineBeforeFirst(out, &first);
+ out << "#include \"rtl/ustrbuf.hxx\"\n";
+ }
+ if (m_includeRtlUstringH) {
+ dumpEmptyLineBeforeFirst(out, &first);
+ out << "#include \"rtl/ustring.h\"\n";
+ }
+ if (m_includeRtlUstringHxx) {
+ dumpEmptyLineBeforeFirst(out, &first);
+ out << "#include \"rtl/ustring.hxx\"\n";
+ }
+ if (m_includeRtlInstanceHxx) {
+ dumpEmptyLineBeforeFirst(out, &first);
+ out << "#include \"rtl/instance.hxx\"\n";
+ }
+ if (m_includeSalTypesH) {
+ dumpEmptyLineBeforeFirst(out, &first);
+ out << "#include \"sal/types.h\"\n";
+ }
+ if (m_includeTypelibTypeclassH) {
+ dumpEmptyLineBeforeFirst(out, &first);
+ out << "#include \"typelib/typeclass.h\"\n";
+ }
+ if (m_includeTypelibTypedescriptionH) {
+ dumpEmptyLineBeforeFirst(out, &first);
+ out << "#include \"typelib/typedescription.h\"\n";
+ }
+ for (OUString const & s : m_custom)
+ out << s << "\n";
+}
+
+void Includes::dumpInclude(
+ FileStream & out, OString const & entityName, bool hpp)
+{
+ out << "#include \"" << entityName.replace('.', '/') << "."
+ << (hpp ? "hpp" : "hdl") << "\"\n";
+}
+
+bool Includes::isInterfaceType(std::string_view entityName) const {
+ return m_manager->getSort(b2u(entityName)) == UnoType::Sort::Interface;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/codemaker/source/cppumaker/includes.hxx b/codemaker/source/cppumaker/includes.hxx
new file mode 100644
index 000000000..8cd830b4a
--- /dev/null
+++ b/codemaker/source/cppumaker/includes.hxx
@@ -0,0 +1,100 @@
+/* -*- 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 <rtl/ref.hxx>
+#include <rtl/ustring.hxx>
+#include <string_view>
+#include <vector>
+#include "dependencies.hxx"
+
+class FileStream;
+class TypeManager;
+
+namespace codemaker::cppumaker {
+
+class Includes {
+public:
+ Includes(
+ rtl::Reference< TypeManager > manager,
+ Dependencies const & dependencies, bool hpp);
+
+ ~Includes();
+
+ void add(OString const & entityName);
+ void addCassert() { m_includeCassert = true; }
+ void addAny() { m_includeAny = true; }
+ void addReference() { m_includeReference = true; }
+ void addSequence() { m_includeSequence = true; }
+ void addType() { m_includeType = true; }
+ void addCppuMacrosHxx() { m_includeCppuMacrosHxx = true; }
+ void addCppuUnotypeHxx() { m_includeCppuUnotypeHxx = true; }
+ void addOslMutexHxx() { m_includeOslMutexHxx = true; }
+ void addRtlStrbufHxx() { m_includeRtlStrbufHxx = true; }
+ void addRtlStringH() { m_includeRtlStringH = true; }
+ void addRtlTextencH() { m_includeRtlTextencH = true; }
+ void addRtlUstrbufHxx() { m_includeRtlUstrbufHxx = true; }
+ void addRtlUstringH() { m_includeRtlUstringH = true; }
+ void addRtlUstringHxx() { m_includeRtlUstringHxx = true; }
+ void addRtlInstanceHxx() { m_includeRtlInstanceHxx = true; }
+ void addSalTypesH() { m_includeSalTypesH = true; }
+ void addTypelibTypeclassH() { m_includeTypelibTypeclassH = true; }
+ void addTypelibTypedescriptionH()
+ { m_includeTypelibTypedescriptionH = true; }
+ void addCustom(const OUString& s) { m_custom.push_back(s); }
+ void dump(
+ FileStream & out, OUString const * companionHdl, bool exceptions);
+
+ static void dumpInclude(
+ FileStream & out, OString const & entityName, bool hpp);
+
+private:
+ Includes(Includes const &) = delete;
+ Includes& operator =(const Includes&) = delete;
+
+ bool isInterfaceType(std::string_view entityName) const;
+
+ rtl::Reference< TypeManager > m_manager;
+ Dependencies::Map m_map;
+ bool m_hpp;
+ bool m_includeCassert;
+ bool m_includeAny;
+ bool m_includeReference;
+ bool m_includeSequence;
+ bool m_includeType;
+ bool m_includeCppuMacrosHxx;
+ bool m_includeCppuUnotypeHxx;
+ bool m_includeOslMutexHxx;
+ bool m_includeRtlStrbufHxx;
+ bool m_includeRtlStringH;
+ bool m_includeRtlTextencH;
+ bool m_includeRtlUstrbufHxx;
+ bool m_includeRtlUstringH;
+ bool m_includeRtlUstringHxx;
+ bool m_includeRtlInstanceHxx;
+ bool m_includeSalTypesH;
+ bool m_includeTypelibTypeclassH;
+ bool m_includeTypelibTypedescriptionH;
+ std::vector<OUString> m_custom;
+};
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/codemaker/source/javamaker/classfile.cxx b/codemaker/source/javamaker/classfile.cxx
new file mode 100644
index 000000000..67177a718
--- /dev/null
+++ b/codemaker/source/javamaker/classfile.cxx
@@ -0,0 +1,828 @@
+/* -*- 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 "classfile.hxx"
+
+#include <codemaker/global.hxx>
+#include <codemaker/options.hxx>
+#include <codemaker/unotype.hxx>
+
+#include <osl/diagnose.h>
+#include <rtl/string.h>
+#include <rtl/string.hxx>
+#include <sal/types.h>
+
+#include <map>
+#include <utility>
+#include <vector>
+
+using codemaker::javamaker::ClassFile;
+
+namespace {
+
+void appendU1(std::vector< unsigned char > & stream, sal_uInt8 data) {
+ stream.push_back(static_cast< unsigned char >(data));
+}
+
+void appendU2(std::vector< unsigned char > & stream, sal_uInt16 data) {
+ stream.push_back(static_cast< unsigned char >(data >> 8));
+ stream.push_back(static_cast< unsigned char >(data & 0xFF));
+}
+
+void appendU4(std::vector< unsigned char > & stream, sal_uInt32 data) {
+ stream.push_back(static_cast< unsigned char >(data >> 24));
+ stream.push_back(static_cast< unsigned char >((data >> 16) & 0xFF));
+ stream.push_back(static_cast< unsigned char >((data >> 8) & 0xFF));
+ stream.push_back(static_cast< unsigned char >(data & 0xFF));
+}
+
+void appendU8(std::vector< unsigned char > & stream, sal_uInt64 data) {
+ stream.push_back(static_cast< unsigned char >(data >> 56));
+ stream.push_back(static_cast< unsigned char >((data >> 48) & 0xFF));
+ stream.push_back(static_cast< unsigned char >((data >> 40) & 0xFF));
+ stream.push_back(static_cast< unsigned char >((data >> 32) & 0xFF));
+ stream.push_back(static_cast< unsigned char >((data >> 24) & 0xFF));
+ stream.push_back(static_cast< unsigned char >((data >> 16) & 0xFF));
+ stream.push_back(static_cast< unsigned char >((data >> 8) & 0xFF));
+ stream.push_back(static_cast< unsigned char >(data & 0xFF));
+}
+
+void appendStream(
+ std::vector< unsigned char > & stream,
+ std::vector< unsigned char > const & data)
+{
+ stream.insert(stream.end(), data.begin(), data.end());
+}
+
+void write(FileStream & file, void const * buffer, sal_uInt64 size) {
+ if (!file.write(buffer, size))
+ throw CannotDumpException("Error writing file");
+}
+
+void writeU2(FileStream & file, sal_uInt16 data) {
+ unsigned char buf[] = {
+ static_cast< unsigned char >(data >> 8),
+ static_cast< unsigned char >(data & 0xFF) };
+ write(file, buf, sizeof buf);
+}
+
+void writeU4(FileStream & file, sal_uInt32 data) {
+ unsigned char buf[] = {
+ static_cast< unsigned char >(data >> 24),
+ static_cast< unsigned char >((data >> 16) & 0xFF),
+ static_cast< unsigned char >((data >> 8) & 0xFF),
+ static_cast< unsigned char >(data & 0xFF) };
+ write(file, buf, sizeof buf);
+}
+
+void writeStream(FileStream & file, std::vector< unsigned char > const & stream)
+{
+ std::vector< unsigned char >::size_type n = stream.size();
+ static_assert(
+ sizeof (std::vector< unsigned char >::size_type)
+ <= sizeof (sal_uInt64), "must be at most equal in size");
+ // both unsigned integral, so sizeof is a practically sufficient
+ // approximation of std::numeric_limits<T1>::max() <=
+ // std::numeric_limits<T2>::max()
+ if (n != 0) {
+ write(file, stream.data(), static_cast< sal_uInt64 >(n));
+ }
+}
+
+}
+
+ClassFile::Code::~Code() {}
+
+void ClassFile::Code::instrAastore() {
+ // aastore:
+ appendU1(m_code, 0x53);
+}
+
+void ClassFile::Code::instrAconstNull() {
+ // aconst_null:
+ appendU1(m_code, 0x01);
+}
+
+void ClassFile::Code::instrAnewarray(OString const & type) {
+ // anewarray <indexbyte1> <indexbyte2>:
+ appendU1(m_code, 0xBD);
+ appendU2(m_code, m_classFile.addClassInfo(type));
+}
+
+void ClassFile::Code::instrAreturn() {
+ // areturn:
+ appendU1(m_code, 0xB0);
+}
+
+void ClassFile::Code::instrAthrow() {
+ // athrow:
+ appendU1(m_code, 0xBF);
+}
+
+void ClassFile::Code::instrCheckcast(OString const & type) {
+ // checkcast <indexbyte1> <indexbyte2>:
+ appendU1(m_code, 0xC0);
+ appendU2(m_code, m_classFile.addClassInfo(type));
+}
+
+void ClassFile::Code::instrDup() {
+ // dup:
+ appendU1(m_code, 0x59);
+}
+
+void ClassFile::Code::instrGetstatic(
+ OString const & type, OString const & name,
+ OString const & descriptor)
+{
+ // getstatic <indexbyte1> <indexbyte2>:
+ appendU1(m_code, 0xB2);
+ appendU2(m_code, m_classFile.addFieldrefInfo(type, name, descriptor));
+}
+
+ClassFile::Code::Branch ClassFile::Code::instrIfAcmpne() {
+ // if_acmpne <branchbyte1> <branchbyte2>:
+ Branch branch = m_code.size();
+ appendU1(m_code, 0xA6);
+ appendU2(m_code, 0);
+ return branch;
+}
+
+ClassFile::Code::Branch ClassFile::Code::instrIfeq() {
+ // ifeq <branchbyte1> <branchbyte2>:
+ Branch branch = m_code.size();
+ appendU1(m_code, 0x99);
+ appendU2(m_code, 0);
+ return branch;
+}
+
+ClassFile::Code::Branch ClassFile::Code::instrIfnull() {
+ // ifnull <branchbyte1> <branchbyte2>:
+ Branch branch = m_code.size();
+ appendU1(m_code, 0xC6);
+ appendU2(m_code, 0);
+ return branch;
+}
+
+void ClassFile::Code::instrInstanceof(OString const & type) {
+ // instanceof <indexbyte1> <indexbyte2>:
+ appendU1(m_code, 0xC1);
+ appendU2(m_code, m_classFile.addClassInfo(type));
+}
+
+void ClassFile::Code::instrInvokeinterface(
+ OString const & type, OString const & name,
+ OString const & descriptor, sal_uInt8 args)
+{
+ // invokeinterface <indexbyte1> <indexbyte2> <nargs> 0:
+ appendU1(m_code, 0xB9);
+ appendU2(
+ m_code, m_classFile.addInterfaceMethodrefInfo(type, name, descriptor));
+ appendU1(m_code, args);
+ appendU1(m_code, 0);
+}
+
+void ClassFile::Code::instrInvokespecial(
+ OString const & type, OString const & name,
+ OString const & descriptor)
+{
+ // invokespecial <indexbyte1> <indexbyte2>:
+ appendU1(m_code, 0xB7);
+ appendU2(m_code, m_classFile.addMethodrefInfo(type, name, descriptor));
+}
+
+void ClassFile::Code::instrInvokestatic(
+ OString const & type, OString const & name,
+ OString const & descriptor)
+{
+ // invokestatic <indexbyte1> <indexbyte2>:
+ appendU1(m_code, 0xB8);
+ appendU2(m_code, m_classFile.addMethodrefInfo(type, name, descriptor));
+}
+
+void ClassFile::Code::instrInvokevirtual(
+ OString const & type, OString const & name,
+ OString const & descriptor)
+{
+ // invokevirtual <indexbyte1> <indexbyte2>:
+ appendU1(m_code, 0xB6);
+ appendU2(m_code, m_classFile.addMethodrefInfo(type, name, descriptor));
+}
+
+void ClassFile::Code::instrLookupswitch(
+ Code const * defaultBlock,
+ std::vector< std::pair< sal_Int32, Code * > > const & blocks)
+{
+ // lookupswitch <0--3 byte pad> <defaultbyte1> <defaultbyte2> <defaultbyte3>
+ // <defaultbyte4> <npairs1> <npairs2> <npairs3> <npairs4>
+ // <match--offset pairs...>:
+ std::vector< std::pair< sal_Int32, Code * > >::size_type size = blocks.size();
+ if (size > SAL_MAX_INT32) {
+ throw CannotDumpException("Lookup-switch too large for Java class file format");
+ }
+ Position pos1 = m_code.size();
+ appendU1(m_code, 0xAB);
+ int pad = (pos1 + 1) % 4;
+ for (int i = 0; i < pad; ++i) {
+ appendU1(m_code, 0);
+ }
+ Position pos2 = pos1 + 1 + pad + 8 + blocks.size() * 8; //FIXME: overflow
+ appendU4(m_code, static_cast< sal_uInt32 >(pos2 - pos1)); //FIXME: overflow
+ pos2 += defaultBlock->m_code.size(); //FIXME: overflow
+ appendU4(m_code, static_cast< sal_uInt32 >(size));
+ for (const std::pair< sal_Int32, Code * >& pair : blocks)
+ {
+ appendU4(m_code, static_cast< sal_uInt32 >(pair.first));
+ appendU4(m_code, static_cast< sal_uInt32 >(pos2 - pos1));
+ //FIXME: overflow
+ pos2 += pair.second->m_code.size(); //FIXME: overflow
+ }
+ appendStream(m_code, defaultBlock->m_code);
+ for (const std::pair< sal_Int32, Code * >& pair : blocks)
+ {
+ appendStream(m_code, pair.second->m_code);
+ }
+}
+
+void ClassFile::Code::instrNew(OString const & type) {
+ // new <indexbyte1> <indexbyte2>:
+ appendU1(m_code, 0xBB);
+ appendU2(m_code, m_classFile.addClassInfo(type));
+}
+
+void ClassFile::Code::instrNewarray(codemaker::UnoType::Sort sort) {
+ OSL_ASSERT(
+ sort >= codemaker::UnoType::Sort::Boolean
+ && sort <= codemaker::UnoType::Sort::Char);
+ // newarray <atype>:
+ appendU1(m_code, 0xBC);
+ static sal_uInt8 const atypes[static_cast<int>(codemaker::UnoType::Sort::Char)] = {
+ 0x04, 0x08, 0x09, 0x09, 0x0A, 0x0A, 0x0B, 0x0B, 0x06, 0x07, 0x05 };
+ appendU1(m_code, atypes[static_cast<int>(sort) - 1]);
+}
+
+void ClassFile::Code::instrPop() {
+ // pop:
+ appendU1(m_code, 0x57);
+}
+
+void ClassFile::Code::instrPutfield(
+ OString const & type, OString const & name,
+ OString const & descriptor)
+{
+ // putfield <indexbyte1> <indexbyte2>:
+ appendU1(m_code, 0xB5);
+ appendU2(m_code, m_classFile.addFieldrefInfo(type, name, descriptor));
+}
+
+void ClassFile::Code::instrPutstatic(
+ OString const & type, OString const & name,
+ OString const & descriptor)
+{
+ // putstatic <indexbyte1> <indexbyte2>:
+ appendU1(m_code, 0xB3);
+ appendU2(m_code, m_classFile.addFieldrefInfo(type, name, descriptor));
+}
+
+void ClassFile::Code::instrReturn() {
+ // return:
+ appendU1(m_code, 0xB1);
+}
+
+void ClassFile::Code::instrSwap() {
+ // swap:
+ appendU1(m_code, 0x5F);
+}
+
+void ClassFile::Code::instrTableswitch(
+ Code const * defaultBlock, sal_Int32 low,
+ std::vector< std::unique_ptr<Code> > const & blocks)
+{
+ // tableswitch <0--3 byte pad> <defaultbyte1> <defaultbyte2> <defaultbyte3>
+ // <defaultbyte4> <lowbyte1> <lowbyte2> <lowbyte3> <lowbyte4> <highbyte1>
+ // <highbyte2> <highbyte3> <highbyte4> <jump offsets...>:
+ Position pos1 = m_code.size();
+ appendU1(m_code, 0xAA);
+ int pad = (pos1 + 1) % 4;
+ for (int i = 0; i < pad; ++i) {
+ appendU1(m_code, 0);
+ }
+ std::vector< Code * >::size_type size = blocks.size();
+ Position pos2 = pos1 + 1 + pad + 12 + size * 4; //FIXME: overflow
+ sal_uInt32 defaultOffset = static_cast< sal_uInt32 >(pos2 - pos1);
+ //FIXME: overflow
+ appendU4(m_code, defaultOffset);
+ pos2 += defaultBlock->m_code.size(); //FIXME: overflow
+ appendU4(m_code, static_cast< sal_uInt32 >(low));
+ appendU4(m_code, static_cast< sal_uInt32 >(low + (size - 1)));
+ for (std::unique_ptr<Code> const & pCode : blocks)
+ {
+ if (pCode == nullptr) {
+ appendU4(m_code, defaultOffset);
+ } else {
+ appendU4(m_code, static_cast< sal_uInt32 >(pos2 - pos1));
+ //FIXME: overflow
+ pos2 += pCode->m_code.size(); //FIXME: overflow
+ }
+ }
+ appendStream(m_code, defaultBlock->m_code);
+ for (std::unique_ptr<Code> const & pCode : blocks)
+ {
+ if (pCode != nullptr) {
+ appendStream(m_code, pCode->m_code);
+ }
+ }
+}
+
+void ClassFile::Code::loadIntegerConstant(sal_Int32 value) {
+ if (value >= -1 && value <= 5) {
+ // iconst_<i>:
+ appendU1(m_code, static_cast< sal_uInt8 >(0x02 + value + 1));
+ } else if (value >= -128 && value <= 127) {
+ // bipush <byte>:
+ appendU1(m_code, 0x10);
+ appendU1(m_code, static_cast< sal_uInt8 >(value));
+ } else if (value >= -32768 && value <= 32767) {
+ // sipush <byte1> <byte2>:
+ appendU1(m_code, 0x11);
+ appendU2(m_code, static_cast< sal_uInt16 >(value));
+ } else {
+ ldc(m_classFile.addIntegerInfo(value));
+ }
+}
+
+void ClassFile::Code::loadStringConstant(OString const & value) {
+ ldc(m_classFile.addStringInfo(value));
+}
+
+void ClassFile::Code::loadLocalInteger(sal_uInt16 index) {
+ accessLocal(index, 0x1A, 0x15); // iload_<n>, iload
+}
+
+void ClassFile::Code::loadLocalLong(sal_uInt16 index) {
+ accessLocal(index, 0x1E, 0x16); // load_<n>, load
+}
+
+void ClassFile::Code::loadLocalFloat(sal_uInt16 index) {
+ accessLocal(index, 0x22, 0x17); // load_<n>, load
+}
+
+void ClassFile::Code::loadLocalDouble(sal_uInt16 index) {
+ accessLocal(index, 0x26, 0x18); // load_<n>, load
+}
+
+void ClassFile::Code::loadLocalReference(sal_uInt16 index) {
+ accessLocal(index, 0x2A, 0x19); // aload_<n>, aload
+}
+
+void ClassFile::Code::storeLocalReference(sal_uInt16 index) {
+ accessLocal(index, 0x4B, 0x3A); // astore_<n>, astore
+}
+
+void ClassFile::Code::branchHere(Branch branch) {
+ std::vector< unsigned char >::size_type n = m_code.size();
+ OSL_ASSERT(n > branch && n - branch <= SAL_MAX_INT16);
+ n -= branch;
+ m_code[branch + 1] = static_cast< sal_uInt8 >(n >> 8);
+ m_code[branch + 2] = static_cast< sal_uInt8 >(n & 0xFF);
+}
+
+void ClassFile::Code::addException(
+ Position start, Position end, Position handler, OString const & type)
+{
+ OSL_ASSERT(start < end && end <= m_code.size() && handler <= m_code.size());
+ if (m_exceptionTableLength == SAL_MAX_UINT16) {
+ throw CannotDumpException("Too many exception handlers for Java class file format");
+ }
+ ++m_exceptionTableLength;
+ appendU2(m_exceptionTable, static_cast< sal_uInt16 >(start));
+ //FIXME: overflow
+ appendU2(m_exceptionTable, static_cast< sal_uInt16 >(end));
+ //FIXME: overflow
+ appendU2(m_exceptionTable, static_cast< sal_uInt16 >(handler));
+ //FIXME: overflow
+ appendU2(m_exceptionTable, m_classFile.addClassInfo(type));
+}
+
+ClassFile::Code::Position ClassFile::Code::getPosition() const {
+ return m_code.size();
+}
+
+ClassFile::Code::Code(ClassFile & classFile)
+ : m_classFile(classFile)
+ , m_maxStack(0)
+ , m_maxLocals(0)
+ , m_exceptionTableLength(0)
+{}
+
+void ClassFile::Code::ldc(sal_uInt16 index) {
+ if (index <= 0xFF) {
+ // ldc <index>:
+ appendU1(m_code, 0x12);
+ appendU1(m_code, static_cast< sal_uInt8 >(index));
+ } else {
+ // ldc_w <indexbyte1> <indexbyte2>:
+ appendU1(m_code, 0x13);
+ appendU2(m_code, index);
+ }
+}
+
+void ClassFile::Code::accessLocal(
+ sal_uInt16 index, sal_uInt8 fastOp, sal_uInt8 normalOp)
+{
+ if (index <= 3) {
+ // ...load/store_<n>:
+ appendU1(m_code, static_cast< sal_uInt8 >(fastOp + index));
+ } else if (index <= 0xFF) {
+ // ...load/store <index>:
+ appendU1(m_code, normalOp);
+ appendU1(m_code, static_cast< sal_uInt8 >(index));
+ } else {
+ // wide ...load/store <indexbyte1> <indexbyte2>:
+ appendU1(m_code, 0xC4);
+ appendU1(m_code, normalOp);
+ appendU2(m_code, index);
+ }
+}
+
+ClassFile::ClassFile(
+ AccessFlags accessFlags, OString const & thisClass,
+ OString const & superClass, OString const & signature):
+ m_constantPoolCount(1), m_accessFlags(accessFlags), m_interfacesCount(0),
+ m_fieldsCount(0), m_methodsCount(0), m_attributesCount(0)
+{
+ m_thisClass = addClassInfo(thisClass);
+ m_superClass = addClassInfo(superClass);
+ if (!signature.isEmpty()) {
+ ++m_attributesCount;
+ appendU2(m_attributes, addUtf8Info("Signature"));
+ appendU4(m_attributes, 2);
+ appendU2(m_attributes, addUtf8Info(signature));
+ }
+}
+
+ClassFile::~ClassFile() {}
+
+std::unique_ptr<ClassFile::Code> ClassFile::newCode() {
+ return std::unique_ptr<Code>(new Code(*this));
+}
+
+sal_uInt16 ClassFile::addIntegerInfo(sal_Int32 value) {
+ std::map< sal_Int32, sal_uInt16 >::iterator i(m_integerInfos.find(value));
+ if (i != m_integerInfos.end()) {
+ return i->second;
+ }
+ sal_uInt16 index = nextConstantPoolIndex(1);
+ appendU1(m_constantPool, 3);
+ appendU4(m_constantPool, static_cast< sal_uInt32 >(value));
+ if (!m_integerInfos.emplace(value, index).second)
+ {
+ OSL_ASSERT(false);
+ }
+ return index;
+}
+
+sal_uInt16 ClassFile::addFloatInfo(float value) {
+ std::map< float, sal_uInt16 >::iterator i(m_floatInfos.find(value));
+ if (i != m_floatInfos.end()) {
+ return i->second;
+ }
+ sal_uInt16 index = nextConstantPoolIndex(1);
+ appendU1(m_constantPool, 4);
+ union { float floatBytes; sal_uInt32 uint32Bytes; } bytes;
+ bytes.floatBytes = value;
+ appendU4(m_constantPool, bytes.uint32Bytes);
+ if (!m_floatInfos.emplace(value, index).second)
+ {
+ OSL_ASSERT(false);
+ }
+ return index;
+}
+
+sal_uInt16 ClassFile::addLongInfo(sal_Int64 value) {
+ std::map< sal_Int64, sal_uInt16 >::iterator i(m_longInfos.find(value));
+ if (i != m_longInfos.end()) {
+ return i->second;
+ }
+ sal_uInt16 index = nextConstantPoolIndex(2);
+ appendU1(m_constantPool, 5);
+ appendU8(m_constantPool, static_cast< sal_uInt64 >(value));
+ if (!m_longInfos.emplace(value, index).second)
+ {
+ OSL_ASSERT(false);
+ }
+ return index;
+}
+
+sal_uInt16 ClassFile::addDoubleInfo(double value) {
+ std::map< double, sal_uInt16 >::iterator i(m_doubleInfos.find(value));
+ if (i != m_doubleInfos.end()) {
+ return i->second;
+ }
+ sal_uInt16 index = nextConstantPoolIndex(2);
+ appendU1(m_constantPool, 6);
+ union { double doubleBytes; sal_uInt64 uint64Bytes; } bytes;
+ bytes.doubleBytes = value;
+ appendU8(m_constantPool, bytes.uint64Bytes);
+ if (!m_doubleInfos.emplace(value, index).second)
+ {
+ OSL_ASSERT(false);
+ }
+ return index;
+}
+
+void ClassFile::addInterface(OString const & interface) {
+ if (m_interfacesCount == SAL_MAX_UINT16) {
+ throw CannotDumpException("Too many interfaces for Java class file format");
+ }
+ ++m_interfacesCount;
+ appendU2(m_interfaces, addClassInfo(interface));
+}
+
+void ClassFile::addField(
+ AccessFlags accessFlags, OString const & name,
+ OString const & descriptor, sal_uInt16 constantValueIndex,
+ OString const & signature)
+{
+ if (m_fieldsCount == SAL_MAX_UINT16) {
+ throw CannotDumpException("Too many fields for Java class file format");
+ }
+ ++m_fieldsCount;
+ appendU2(m_fields, static_cast< sal_uInt16 >(accessFlags));
+ appendU2(m_fields, addUtf8Info(name));
+ appendU2(m_fields, addUtf8Info(descriptor));
+ appendU2(
+ m_fields,
+ ((constantValueIndex == 0 ? 0 : 1)
+ + (signature.isEmpty() ? 0 : 1)));
+ if (constantValueIndex != 0) {
+ appendU2(m_fields, addUtf8Info("ConstantValue"));
+ appendU4(m_fields, 2);
+ appendU2(m_fields, constantValueIndex);
+ }
+ appendSignatureAttribute(m_fields, signature);
+}
+
+void ClassFile::addMethod(
+ AccessFlags accessFlags, OString const & name,
+ OString const & descriptor, Code const * code,
+ std::vector< OString > const & exceptions,
+ OString const & signature)
+{
+ if (m_methodsCount == SAL_MAX_UINT16) {
+ throw CannotDumpException("Too many methods for Java class file format");
+ }
+ ++m_methodsCount;
+ appendU2(m_methods, static_cast< sal_uInt16 >(accessFlags));
+ appendU2(m_methods, addUtf8Info(name));
+ appendU2(m_methods, addUtf8Info(descriptor));
+ std::vector< OString >::size_type excs = exceptions.size();
+ if (excs > SAL_MAX_UINT16) {
+ throw CannotDumpException("Too many exception specifications for Java class file format");
+ }
+ appendU2(
+ m_methods,
+ ((code == nullptr ? 0 : 1) + (exceptions.empty() ? 0 : 1)
+ + (signature.isEmpty() ? 0 : 1)));
+ if (code != nullptr) {
+ std::vector< unsigned char >::size_type codeSize = code->m_code.size();
+ std::vector< unsigned char >::size_type exceptionTableSize
+ = code->m_exceptionTable.size();
+ if (codeSize > SAL_MAX_UINT32 - (2 + 2 + 4 + 2 + 2)
+ || (exceptionTableSize
+ > (SAL_MAX_UINT32 - (2 + 2 + 4 + 2 + 2)
+ - static_cast< sal_uInt32 >(codeSize))))
+ {
+ throw CannotDumpException("Code block is too big for Java class file format");
+ }
+ appendU2(m_methods, addUtf8Info("Code"));
+ appendU4(
+ m_methods,
+ (2 + 2 + 4 + static_cast< sal_uInt32 >(codeSize) + 2
+ + static_cast< sal_uInt32 >(exceptionTableSize) + 2));
+ appendU2(m_methods, code->m_maxStack);
+ appendU2(m_methods, code->m_maxLocals);
+ appendU4(m_methods, static_cast< sal_uInt32 >(codeSize));
+ appendStream(m_methods, code->m_code);
+ appendU2(m_methods, code->m_exceptionTableLength);
+ appendStream(m_methods, code->m_exceptionTable);
+ appendU2(m_methods, 0);
+ }
+ if (!exceptions.empty()) {
+ appendU2(m_methods, addUtf8Info("Exceptions"));
+ appendU4(
+ m_methods,
+ static_cast< sal_uInt32 >(2 + 2 * static_cast< sal_uInt32 >(excs)));
+ appendU2(m_methods, static_cast< sal_uInt16 >(excs));
+ for (const OString& ex : exceptions)
+ {
+ appendU2(m_methods, addClassInfo(ex));
+ }
+ }
+ appendSignatureAttribute(m_methods, signature);
+}
+
+void ClassFile::write(FileStream & file) const {
+ writeU4(file, 0xCAFEBABE);
+ writeU2(file, 0);
+ writeU2(file, 49); // class file version of JRE 1.5
+ writeU2(file, m_constantPoolCount);
+ writeStream(file, m_constantPool);
+ writeU2(file, static_cast< sal_uInt16 >(m_accessFlags));
+ writeU2(file, m_thisClass);
+ writeU2(file, m_superClass);
+ writeU2(file, m_interfacesCount);
+ writeStream(file, m_interfaces);
+ writeU2(file, m_fieldsCount);
+ writeStream(file, m_fields);
+ writeU2(file, m_methodsCount);
+ writeStream(file, m_methods);
+ writeU2(file, m_attributesCount);
+ writeStream(file, m_attributes);
+}
+
+sal_uInt16 ClassFile::nextConstantPoolIndex(sal_uInt16 width) {
+ OSL_ASSERT(width == 1 || width == 2);
+ if (m_constantPoolCount > SAL_MAX_UINT16 - width) {
+ throw CannotDumpException("Too many constant pool items for Java class file format");
+ }
+ sal_uInt16 index = m_constantPoolCount;
+ m_constantPoolCount = m_constantPoolCount + width;
+ return index;
+}
+
+sal_uInt16 ClassFile::addUtf8Info(OString const & value) {
+ std::map< OString, sal_uInt16 >::iterator i(m_utf8Infos.find(value));
+ if (i != m_utf8Infos.end()) {
+ return i->second;
+ }
+ if (value.getLength() > SAL_MAX_UINT16) {
+ throw CannotDumpException("UTF-8 string too long for Java class file format");
+ }
+ sal_uInt16 index = nextConstantPoolIndex(1);
+ appendU1(m_constantPool, 1);
+ appendU2(m_constantPool, static_cast< sal_uInt16 >(value.getLength()));
+ for (sal_Int32 j = 0; j < value.getLength(); ++j) {
+ appendU1(m_constantPool, static_cast< sal_uInt8 >(value[j]));
+ }
+ if (!m_utf8Infos.emplace(value, index).second)
+ {
+ OSL_ASSERT(false);
+ }
+ return index;
+}
+
+sal_uInt16 ClassFile::addClassInfo(OString const & type) {
+ sal_uInt16 nameIndex = addUtf8Info(type);
+ std::map< sal_uInt16, sal_uInt16 >::iterator i(
+ m_classInfos.find(nameIndex));
+ if (i != m_classInfos.end()) {
+ return i->second;
+ }
+ sal_uInt16 index = nextConstantPoolIndex(1);
+ appendU1(m_constantPool, 7);
+ appendU2(m_constantPool, nameIndex);
+ if (!m_classInfos.emplace(nameIndex, index).second)
+ {
+ OSL_ASSERT(false);
+ }
+ return index;
+}
+
+sal_uInt16 ClassFile::addStringInfo(OString const & value) {
+ sal_uInt16 stringIndex = addUtf8Info(value);
+ std::map< sal_uInt16, sal_uInt16 >::iterator i(
+ m_stringInfos.find(stringIndex));
+ if (i != m_stringInfos.end()) {
+ return i->second;
+ }
+ sal_uInt16 index = nextConstantPoolIndex(1);
+ appendU1(m_constantPool, 8);
+ appendU2(m_constantPool, stringIndex);
+ if (!m_stringInfos.emplace(stringIndex, index).second)
+ {
+ OSL_ASSERT(false);
+ }
+ return index;
+}
+
+sal_uInt16 ClassFile::addFieldrefInfo(
+ OString const & type, OString const & name,
+ OString const & descriptor)
+{
+ sal_uInt16 classIndex = addClassInfo(type);
+ sal_uInt16 nameAndTypeIndex = addNameAndTypeInfo(name, descriptor);
+ sal_uInt32 key = (static_cast< sal_uInt32 >(classIndex) << 16)
+ | nameAndTypeIndex;
+ std::map< sal_uInt32, sal_uInt16 >::iterator i(m_fieldrefInfos.find(key));
+ if (i != m_fieldrefInfos.end()) {
+ return i->second;
+ }
+ sal_uInt16 index = nextConstantPoolIndex(1);
+ appendU1(m_constantPool, 9);
+ appendU2(m_constantPool, classIndex);
+ appendU2(m_constantPool, nameAndTypeIndex);
+ if (!m_fieldrefInfos.emplace(key, index).second)
+ {
+ OSL_ASSERT(false);
+ }
+ return index;
+}
+
+sal_uInt16 ClassFile::addMethodrefInfo(
+ OString const & type, OString const & name,
+ OString const & descriptor)
+{
+ sal_uInt16 classIndex = addClassInfo(type);
+ sal_uInt16 nameAndTypeIndex = addNameAndTypeInfo(name, descriptor);
+ sal_uInt32 key = (static_cast< sal_uInt32 >(classIndex) << 16)
+ | nameAndTypeIndex;
+ std::map< sal_uInt32, sal_uInt16 >::iterator i(m_methodrefInfos.find(key));
+ if (i != m_methodrefInfos.end()) {
+ return i->second;
+ }
+ sal_uInt16 index = nextConstantPoolIndex(1);
+ appendU1(m_constantPool, 10);
+ appendU2(m_constantPool, classIndex);
+ appendU2(m_constantPool, nameAndTypeIndex);
+ if (!m_methodrefInfos.emplace(key, index).second)
+ {
+ OSL_ASSERT(false);
+ }
+ return index;
+}
+
+sal_uInt16 ClassFile::addInterfaceMethodrefInfo(
+ OString const & type, OString const & name,
+ OString const & descriptor)
+{
+ sal_uInt16 classIndex = addClassInfo(type);
+ sal_uInt16 nameAndTypeIndex = addNameAndTypeInfo(name, descriptor);
+ sal_uInt32 key = (static_cast< sal_uInt32 >(classIndex) << 16)
+ | nameAndTypeIndex;
+ std::map< sal_uInt32, sal_uInt16 >::iterator i(
+ m_interfaceMethodrefInfos.find(key));
+ if (i != m_interfaceMethodrefInfos.end()) {
+ return i->second;
+ }
+ sal_uInt16 index = nextConstantPoolIndex(1);
+ appendU1(m_constantPool, 11);
+ appendU2(m_constantPool, classIndex);
+ appendU2(m_constantPool, nameAndTypeIndex);
+ if (!m_interfaceMethodrefInfos.emplace(key, index).second)
+ {
+ OSL_ASSERT(false);
+ }
+ return index;
+}
+
+sal_uInt16 ClassFile::addNameAndTypeInfo(
+ OString const & name, OString const & descriptor)
+{
+ sal_uInt16 nameIndex = addUtf8Info(name);
+ sal_uInt16 descriptorIndex = addUtf8Info(descriptor);
+ sal_uInt32 key = (static_cast< sal_uInt32 >(nameIndex) << 16)
+ | descriptorIndex;
+ std::map< sal_uInt32, sal_uInt16 >::iterator i(
+ m_nameAndTypeInfos.find(key));
+ if (i != m_nameAndTypeInfos.end()) {
+ return i->second;
+ }
+ sal_uInt16 index = nextConstantPoolIndex(1);
+ appendU1(m_constantPool, 12);
+ appendU2(m_constantPool, nameIndex);
+ appendU2(m_constantPool, descriptorIndex);
+ if (!m_nameAndTypeInfos.emplace(key, index).second)
+ {
+ OSL_ASSERT(false);
+ }
+ return index;
+}
+
+void ClassFile::appendSignatureAttribute(
+ std::vector< unsigned char > & stream, OString const & signature)
+{
+ if (!signature.isEmpty()) {
+ appendU2(stream, addUtf8Info("Signature"));
+ appendU4(stream, 2);
+ appendU2(stream, addUtf8Info(signature));
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/codemaker/source/javamaker/classfile.hxx b/codemaker/source/javamaker/classfile.hxx
new file mode 100644
index 000000000..ebfef0782
--- /dev/null
+++ b/codemaker/source/javamaker/classfile.hxx
@@ -0,0 +1,239 @@
+/* -*- 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 <codemaker/unotype.hxx>
+#include <sal/types.h>
+
+#include <map>
+#include <memory>
+#include <utility>
+#include <vector>
+
+class FileStream;
+
+namespace codemaker::javamaker {
+
+class ClassFile {
+public:
+ enum AccessFlags {
+ ACC_PUBLIC = 0x0001,
+ ACC_PRIVATE = 0x0002,
+ ACC_STATIC = 0x0008,
+ ACC_FINAL = 0x0010,
+ ACC_SUPER = 0x0020,
+ ACC_VARARGS = 0x0080,
+ ACC_INTERFACE = 0x0200,
+ ACC_ABSTRACT = 0x0400,
+ ACC_SYNTHETIC = 0x1000
+ };
+
+ class Code {
+ public:
+ typedef std::vector< unsigned char >::size_type Branch;
+ typedef std::vector< unsigned char >::size_type Position;
+
+ ~Code();
+
+ void instrAastore();
+ void instrAconstNull();
+ void instrAnewarray(rtl::OString const & type);
+ void instrAreturn();
+ void instrAthrow();
+ void instrCheckcast(rtl::OString const & type);
+ void instrDup();
+
+ void instrGetstatic(
+ rtl::OString const & type, rtl::OString const & name,
+ rtl::OString const & descriptor);
+
+ Branch instrIfAcmpne();
+ Branch instrIfeq();
+ Branch instrIfnull();
+
+ void instrInstanceof(rtl::OString const & type);
+
+ void instrInvokeinterface(
+ rtl::OString const & type, rtl::OString const & name,
+ rtl::OString const & descriptor, sal_uInt8 args);
+
+ void instrInvokespecial(
+ rtl::OString const & type, rtl::OString const & name,
+ rtl::OString const & descriptor);
+
+ void instrInvokestatic(
+ rtl::OString const & type, rtl::OString const & name,
+ rtl::OString const & descriptor);
+
+ void instrInvokevirtual(
+ rtl::OString const & type, rtl::OString const & name,
+ rtl::OString const & descriptor);
+
+ void instrLookupswitch(
+ Code const * defaultBlock,
+ std::vector< std::pair< sal_Int32, Code * > > const & blocks);
+
+ void instrNew(rtl::OString const & type);
+ void instrNewarray(codemaker::UnoType::Sort sort);
+ void instrPop();
+
+ void instrPutfield(
+ rtl::OString const & type, rtl::OString const & name,
+ rtl::OString const & descriptor);
+
+ void instrPutstatic(
+ rtl::OString const & type, rtl::OString const & name,
+ rtl::OString const & descriptor);
+
+ void instrReturn();
+ void instrSwap();
+
+ void instrTableswitch(
+ Code const * defaultBlock, sal_Int32 low,
+ std::vector< std::unique_ptr<Code> > const & blocks);
+
+ void loadIntegerConstant(sal_Int32 value);
+ void loadStringConstant(rtl::OString const & value);
+ void loadLocalInteger(sal_uInt16 index);
+ void loadLocalLong(sal_uInt16 index);
+ void loadLocalFloat(sal_uInt16 index);
+ void loadLocalDouble(sal_uInt16 index);
+ void loadLocalReference(sal_uInt16 index);
+ void storeLocalReference(sal_uInt16 index);
+ void branchHere(Branch branch);
+
+ void addException(
+ Position start, Position end, Position handler,
+ rtl::OString const & type);
+
+ void setMaxStackAndLocals(sal_uInt16 maxStack, sal_uInt16 maxLocals)
+ { m_maxStack = maxStack; m_maxLocals = maxLocals; }
+
+ Position getPosition() const;
+
+ private:
+ Code(Code const &) = delete;
+ Code& operator =(const Code&) = delete;
+
+ explicit Code(ClassFile & classFile);
+
+ void ldc(sal_uInt16 index);
+
+ void accessLocal(
+ sal_uInt16 index, sal_uInt8 fastOp, sal_uInt8 normalOp);
+
+ ClassFile & m_classFile;
+ sal_uInt16 m_maxStack;
+ sal_uInt16 m_maxLocals;
+ std::vector< unsigned char > m_code;
+ sal_uInt16 m_exceptionTableLength;
+ std::vector< unsigned char > m_exceptionTable;
+
+ friend class ClassFile;
+ };
+
+ ClassFile(
+ AccessFlags accessFlags, rtl::OString const & thisClass,
+ rtl::OString const & superClass, rtl::OString const & signature);
+
+ ~ClassFile();
+
+ std::unique_ptr<Code> newCode();
+
+ sal_uInt16 addIntegerInfo(sal_Int32 value);
+ sal_uInt16 addFloatInfo(float value);
+ sal_uInt16 addLongInfo(sal_Int64 value);
+ sal_uInt16 addDoubleInfo(double value);
+
+ void addInterface(rtl::OString const & interface);
+
+ void addField(
+ AccessFlags accessFlags, rtl::OString const & name,
+ rtl::OString const & descriptor, sal_uInt16 constantValueIndex,
+ rtl::OString const & signature);
+
+ void addMethod(
+ AccessFlags accessFlags, rtl::OString const & name,
+ rtl::OString const & descriptor, Code const * code,
+ std::vector< rtl::OString > const & exceptions,
+ rtl::OString const & signature);
+
+ void write(FileStream & file) const; //TODO
+
+private:
+ typedef std::map< rtl::OString, sal_uInt16 > Map;
+
+ ClassFile(ClassFile const &) = delete;
+ ClassFile& operator =(const ClassFile&) = delete;
+
+ sal_uInt16 nextConstantPoolIndex(sal_uInt16 width);
+ sal_uInt16 addUtf8Info(rtl::OString const & value);
+ sal_uInt16 addClassInfo(rtl::OString const & type);
+ sal_uInt16 addStringInfo(rtl::OString const & value);
+
+ sal_uInt16 addFieldrefInfo(
+ rtl::OString const & type, rtl::OString const & name,
+ rtl::OString const & descriptor);
+
+ sal_uInt16 addMethodrefInfo(
+ rtl::OString const & type, rtl::OString const & name,
+ rtl::OString const & descriptor);
+
+ sal_uInt16 addInterfaceMethodrefInfo(
+ rtl::OString const & type, rtl::OString const & name,
+ rtl::OString const & descriptor);
+
+ sal_uInt16 addNameAndTypeInfo(
+ rtl::OString const & name, rtl::OString const & descriptor);
+
+ void appendSignatureAttribute(
+ std::vector< unsigned char > & stream, rtl::OString const & signature);
+
+ sal_uInt16 m_constantPoolCount;
+ std::vector< unsigned char > m_constantPool;
+ std::map< rtl::OString, sal_uInt16 > m_utf8Infos;
+ std::map< sal_Int32, sal_uInt16 > m_integerInfos;
+ std::map< sal_Int64, sal_uInt16 > m_longInfos;
+ std::map< float, sal_uInt16 > m_floatInfos;
+ std::map< double, sal_uInt16 > m_doubleInfos;
+ std::map< sal_uInt16, sal_uInt16 > m_classInfos;
+ std::map< sal_uInt16, sal_uInt16 > m_stringInfos;
+ std::map< sal_uInt32, sal_uInt16 > m_fieldrefInfos;
+ std::map< sal_uInt32, sal_uInt16 > m_methodrefInfos;
+ std::map< sal_uInt32, sal_uInt16 > m_interfaceMethodrefInfos;
+ std::map< sal_uInt32, sal_uInt16 > m_nameAndTypeInfos;
+ AccessFlags m_accessFlags;
+ sal_uInt16 m_thisClass;
+ sal_uInt16 m_superClass;
+ sal_uInt16 m_interfacesCount;
+ std::vector< unsigned char > m_interfaces;
+ sal_uInt16 m_fieldsCount;
+ std::vector< unsigned char > m_fields;
+ sal_uInt16 m_methodsCount;
+ std::vector< unsigned char > m_methods;
+ sal_uInt16 m_attributesCount;
+ std::vector< unsigned char > m_attributes;
+
+ friend class Code;
+};
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/codemaker/source/javamaker/javamaker.cxx b/codemaker/source/javamaker/javamaker.cxx
new file mode 100644
index 000000000..ee376c8cc
--- /dev/null
+++ b/codemaker/source/javamaker/javamaker.cxx
@@ -0,0 +1,98 @@
+/* -*- 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 <cstdlib>
+#include <cstring>
+#include <iostream>
+#include <vector>
+
+#include <codemaker/generatedtypeset.hxx>
+#include <codemaker/typemanager.hxx>
+#include <rtl/ref.hxx>
+#include <rtl/string.hxx>
+#include <rtl/ustring.hxx>
+#include <sal/main.h>
+#include <sal/types.h>
+#include <unoidl/unoidl.hxx>
+#include <o3tl/string_view.hxx>
+
+#include "javaoptions.hxx"
+#include "javatype.hxx"
+
+// coverity[tainted_data] - this is a build time tool
+SAL_IMPLEMENT_MAIN_WITH_ARGS(argc, argv) {
+ JavaOptions options;
+ try {
+ if (!options.initOptions(argc, argv)) {
+ return EXIT_FAILURE;
+ }
+
+ rtl::Reference typeMgr(new TypeManager);
+ for (const OString& i : options.getExtraInputFiles())
+ {
+ typeMgr->loadProvider(convertToFileUrl(i), false);
+ }
+ for (const OString& i : options.getInputFiles())
+ {
+ typeMgr->loadProvider(convertToFileUrl(i), true);
+ }
+ codemaker::GeneratedTypeSet generated;
+ if (options.isValid("-T")) {
+ OUString names(b2u(options.getOption("-T")));
+ for (sal_Int32 i = 0; i != -1;) {
+ std::u16string_view name(o3tl::getToken(names, 0, ';', i));
+ if (!name.empty()) {
+ produce(
+ OUString(name == u"*"
+ ? u""
+ : o3tl::ends_with(name, u".*")
+ ? name.substr(0, name.size() - std::strlen(".*"))
+ : name),
+ typeMgr, generated, options);
+ }
+ }
+ } else {
+ produce("", typeMgr, generated, options);
+ }
+ }
+ catch (CannotDumpException & e) {
+ std::cerr << "ERROR: " << e.getMessage() << '\n';
+ return EXIT_FAILURE;
+ } catch (unoidl::NoSuchFileException & e) {
+ std::cerr << "ERROR: No such file <" << e.getUri() << ">\n";
+ return EXIT_FAILURE;
+ } catch (unoidl::FileFormatException & e) {
+ std::cerr
+ << "ERROR: Bad format of <" << e.getUri() << ">, \""
+ << e.getDetail() << "\"\n";
+ return EXIT_FAILURE;
+ } catch (IllegalArgument & e) {
+ std::cerr << "Illegal option " << e.m_message << '\n';
+ return EXIT_FAILURE;
+ } catch (std::exception & e) {
+ std::cerr << "Failure " << e.what() << '\n';
+ return EXIT_FAILURE;
+ }
+
+ return EXIT_SUCCESS;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/codemaker/source/javamaker/javaoptions.cxx b/codemaker/source/javamaker/javaoptions.cxx
new file mode 100644
index 000000000..e0e51c973
--- /dev/null
+++ b/codemaker/source/javamaker/javaoptions.cxx
@@ -0,0 +1,249 @@
+/* -*- 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 <string.h>
+#include "javaoptions.hxx"
+#include <osl/process.h>
+#include <osl/thread.h>
+
+
+#ifdef SAL_UNX
+#define SEPARATOR '/'
+#else
+#define SEPARATOR '\\'
+#endif
+
+bool JavaOptions::initOptions(int ac, char* av[], bool bCmdFile)
+{
+ bool ret = true;
+ int i=0;
+
+ if (!bCmdFile)
+ {
+ bCmdFile = true;
+
+ OString name(av[0]);
+ sal_Int32 index = name.lastIndexOf(SEPARATOR);
+ m_program = name.copy(index > 0 ? index+1 : 0);
+
+ if (ac < 2)
+ {
+ fprintf(stderr, "%s", prepareHelp().getStr());
+ ret = false;
+ }
+
+ i = 1;
+ }
+
+ char *s=nullptr;
+ for( ; i < ac; i++)
+ {
+ if (av[i][0] == '-')
+ {
+ switch (av[i][1])
+ {
+ case 'O':
+ if (av[i][2] == '\0')
+ {
+ if (i < ac - 1 && av[i+1][0] != '-')
+ {
+ i++;
+ s = av[i];
+ } else
+ {
+ OString tmp("'-O', please check");
+ if (i <= ac - 1)
+ {
+ tmp += OString::Concat(" your input '") + av[i+1] + "'";
+ }
+
+ throw IllegalArgument(tmp);
+ }
+ } else
+ {
+ s = av[i] + 2;
+ }
+
+ m_options["-O"] = OString(s);
+ break;
+ case 'n':
+ if (av[i][2] != 'D' || av[i][3] != '\0')
+ {
+ OString tmp(OString::Concat("'-nD', please check your input '") + av[i] + "'");
+ throw IllegalArgument(tmp);
+ }
+
+ m_options["-nD"] = OString();
+ break;
+ case 'T':
+ if (av[i][2] == '\0')
+ {
+ if (i < ac - 1 && av[i+1][0] != '-')
+ {
+ i++;
+ s = av[i];
+ } else
+ {
+ OString tmp("'-T', please check");
+ if (i <= ac - 1)
+ {
+ tmp += OString::Concat(" your input '") + av[i+1] + "'";
+ }
+
+ throw IllegalArgument(tmp);
+ }
+ } else
+ {
+ s = av[i] + 2;
+ }
+
+ if (m_options.count("-T") > 0)
+ {
+ OString tmp = m_options["-T"] + ";" + s;
+ m_options["-T"] = tmp;
+ } else
+ {
+ m_options["-T"] = OString(s);
+ }
+ break;
+ case 'G':
+ if (av[i][2] == 'c')
+ {
+ if (av[i][3] != '\0')
+ {
+ OString tmp("'-Gc', please check");
+ if (i <= ac - 1)
+ {
+ tmp += OString::Concat(" your input '") + av[i] + "'";
+ }
+
+ throw IllegalArgument(tmp);
+ }
+
+ m_options["-Gc"] = OString();
+ break;
+ } else if (av[i][2] != '\0')
+ {
+ OString tmp("'-G', please check");
+ if (i <= ac - 1)
+ {
+ tmp += OString::Concat(" your input '") + av[i] + "'";
+ }
+
+ throw IllegalArgument(tmp);
+ }
+
+ m_options["-G"] = OString();
+ break;
+ case 'X': // support for eXtra type rdbs
+ {
+ if (av[i][2] == '\0')
+ {
+ if (i < ac - 1 && av[i+1][0] != '-')
+ {
+ i++;
+ s = av[i];
+ } else
+ {
+ OString tmp("'-X', please check");
+ if (i <= ac - 1)
+ {
+ tmp += OString::Concat(" your input '") + av[i+1] + "'";
+ }
+
+ throw IllegalArgument(tmp);
+ }
+ } else
+ {
+ s = av[i] + 2;
+ }
+
+ m_extra_input_files.emplace_back(s );
+ break;
+ }
+
+ default:
+ throw IllegalArgument(OString::Concat("the option is unknown") + av[i]);
+ }
+ } else
+ {
+ if (av[i][0] == '@')
+ {
+ FILE* cmdFile = fopen(av[i]+1, "r");
+ if( cmdFile == nullptr )
+ {
+ fprintf(stderr, "%s", prepareHelp().getStr());
+ ret = false;
+ } else
+ {
+ int rargc=0;
+ char* rargv[512];
+ char buffer[512];
+
+ while (fscanf(cmdFile, "%511s", buffer) != EOF && rargc < 512)
+ {
+ rargv[rargc]= strdup(buffer);
+ rargc++;
+ }
+ fclose(cmdFile);
+
+ ret = initOptions(rargc, rargv, bCmdFile);
+
+ for (int j=0; j < rargc; j++)
+ {
+ free(rargv[j]);
+ }
+ }
+ } else
+ {
+ m_inputFiles.emplace_back(av[i]);
+ }
+ }
+ }
+
+ return ret;
+}
+
+OString JavaOptions::prepareHelp()
+{
+ OString help = "\nusing: " +
+ m_program + " [-options] file_1 ... file_n -Xfile_n+1 -Xfile_n+2\nOptions:\n"
+ " -O<path> = path describes the root directory for the generated output.\n"
+ " The output directory tree is generated under this directory.\n"
+ " -T<name> = name specifies a type or a list of types. The output for this\n"
+ " [t1;...] type and all dependent types are generated. If no '-T' option is\n"
+ " specified, then output for all types is generated.\n"
+ " Example: 'com.sun.star.uno.XInterface' is a valid type.\n"
+ " -nD = no dependent types are generated.\n"
+ " -G = generate only target files which does not exists.\n"
+ " -Gc = generate only target files which content will be changed.\n"
+ " -X<file> = extra types which will not be taken into account for generation.\n\n" +
+ prepareVersion();
+
+ return help;
+}
+
+OString JavaOptions::prepareVersion() const
+{
+ return m_program + " Version 2.0\n\n";
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/codemaker/source/javamaker/javaoptions.hxx b/codemaker/source/javamaker/javaoptions.hxx
new file mode 100644
index 000000000..5e6161c04
--- /dev/null
+++ b/codemaker/source/javamaker/javaoptions.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 .
+ */
+
+#pragma once
+
+#include <codemaker/options.hxx>
+
+class JavaOptions : public Options
+{
+public:
+ JavaOptions()
+ : Options()
+ {
+ }
+
+ bool initOptions(int ac, char* av[], bool bCmdFile = false) override;
+
+ OString prepareHelp() override;
+
+ OString prepareVersion() const;
+
+protected:
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/codemaker/source/javamaker/javatype.cxx b/codemaker/source/javamaker/javatype.cxx
new file mode 100644
index 000000000..3db9572e5
--- /dev/null
+++ b/codemaker/source/javamaker/javatype.cxx
@@ -0,0 +1,2539 @@
+/* -*- 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 <cassert>
+#include <cstdlib>
+#include <map>
+#include <memory>
+#include <set>
+#include <string_view>
+#include <utility>
+#include <vector>
+
+#include <codemaker/codemaker.hxx>
+#include <codemaker/exceptiontree.hxx>
+#include <codemaker/generatedtypeset.hxx>
+#include <codemaker/global.hxx>
+#include <codemaker/options.hxx>
+#include <codemaker/typemanager.hxx>
+#include <codemaker/unotype.hxx>
+#include <codemaker/commonjava.hxx>
+#include <rtl/ref.hxx>
+#include <rtl/strbuf.hxx>
+#include <rtl/string.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <rtl/ustring.hxx>
+#include <sal/types.h>
+#include <unoidl/unoidl.hxx>
+#include <o3tl/string_view.hxx>
+
+#include "classfile.hxx"
+#include "javaoptions.hxx"
+#include "javatype.hxx"
+
+using codemaker::javamaker::ClassFile;
+
+namespace {
+
+void appendUnoName(
+ rtl::Reference< TypeManager > const & manager, std::u16string_view nucleus,
+ sal_Int32 rank, std::vector< OUString > const & arguments,
+ OUStringBuffer * buffer)
+{
+ assert(manager.is());
+ assert(rank >= 0);
+ assert(buffer != nullptr);
+ for (sal_Int32 i = 0; i != rank; ++i) {
+ buffer->append("[]");
+ }
+ buffer->append(nucleus);
+ if (arguments.empty())
+ return;
+
+ buffer->append('<');
+ for (std::vector< OUString >::const_iterator i(arguments.begin());
+ i != arguments.end(); ++i)
+ {
+ if (i != arguments.begin()) {
+ buffer->append(',');
+ }
+ OUString n;
+ sal_Int32 k;
+ std::vector< OUString > args;
+ manager->decompose(*i, false, &n, &k, &args, nullptr);
+ appendUnoName(manager, n, k, args, buffer);
+ }
+ buffer->append('>');
+}
+
+// Translate the name of a UNOIDL entity (enum type, plain struct type,
+// polymorphic struct type template, or interface type, decomposed into nucleus,
+// sequence rank, and template arguments) into a core UNO type name:
+OUString createUnoName(
+ rtl::Reference< TypeManager > const & manager, std::u16string_view nucleus,
+ sal_Int32 rank, std::vector< OUString > const & arguments)
+{
+ OUStringBuffer buf(256);
+ appendUnoName(manager, nucleus, rank, arguments, &buf);
+ return buf.makeStringAndClear();
+}
+
+enum SpecialType {
+ SPECIAL_TYPE_NONE,
+ SPECIAL_TYPE_ANY,
+ SPECIAL_TYPE_UNSIGNED,
+ SPECIAL_TYPE_INTERFACE
+};
+
+bool isSpecialType(SpecialType special) {
+ return special >= SPECIAL_TYPE_UNSIGNED;
+}
+
+OString translateUnoidlEntityNameToJavaFullyQualifiedName(
+ std::u16string_view name, std::string_view prefix)
+{
+ assert(!o3tl::starts_with(name, u"[]"));
+ assert(name.find('<') == std::string_view::npos);
+ size_t i = name.rfind('.');
+ if (i == std::string_view::npos)
+ i = 0;
+ else
+ ++i;
+ return codemaker::convertString(OUString(name.substr(0, i))).replace('.', '/')
+ + codemaker::java::translateUnoToJavaIdentifier(
+ codemaker::convertString(OUString(name.substr(i))), prefix);
+}
+
+struct PolymorphicUnoType {
+ PolymorphicUnoType(): kind(KIND_NONE) {}
+
+ enum Kind { KIND_NONE, KIND_STRUCT, KIND_SEQUENCE };
+ Kind kind;
+ OUString name;
+};
+
+SpecialType translateUnoTypeToDescriptor(
+ rtl::Reference< TypeManager > const & manager, std::u16string_view type,
+ bool array, bool classType, std::set<OUString> * dependencies,
+ OStringBuffer * descriptor, OStringBuffer * signature,
+ bool * needsSignature, PolymorphicUnoType * polymorphicUnoType);
+
+SpecialType translateUnoTypeToDescriptor(
+ rtl::Reference< TypeManager > const & manager,
+ codemaker::UnoType::Sort sort, OUString const & nucleus, sal_Int32 rank,
+ std::vector< OUString > const & arguments, bool array, bool classType,
+ std::set<OUString> * dependencies, OStringBuffer * descriptor,
+ OStringBuffer * signature, bool * needsSignature,
+ PolymorphicUnoType * polymorphicUnoType)
+{
+ assert(rank >= 0);
+ assert((signature == nullptr) == (needsSignature == nullptr));
+ assert(
+ arguments.empty()
+ == (sort
+ != codemaker::UnoType::Sort::InstantiatedPolymorphicStruct));
+ if (rank > 0xFF - (array ? 1 : 0)) {
+ throw CannotDumpException(
+ "Too many array dimensions for Java class file format");
+ }
+ if (array) {
+ ++rank;
+ }
+ for (sal_Int32 i = 0; i != rank; ++i) {
+ if (descriptor != nullptr) {
+ descriptor->append('[');
+ }
+ if (signature != nullptr) {
+ signature->append('[');
+ }
+ }
+ if (polymorphicUnoType != nullptr) {
+ if (sort
+ == codemaker::UnoType::Sort::InstantiatedPolymorphicStruct)
+ {
+ polymorphicUnoType->kind = rank == 0
+ ? PolymorphicUnoType::KIND_STRUCT
+ : PolymorphicUnoType::KIND_SEQUENCE;
+ polymorphicUnoType->name = createUnoName(
+ manager, nucleus, rank, arguments);
+ } else {
+ polymorphicUnoType->kind = PolymorphicUnoType::KIND_NONE;
+ }
+ }
+ switch (sort) {
+ case codemaker::UnoType::Sort::Void:
+ case codemaker::UnoType::Sort::Boolean:
+ case codemaker::UnoType::Sort::Byte:
+ case codemaker::UnoType::Sort::Short:
+ case codemaker::UnoType::Sort::UnsignedShort:
+ case codemaker::UnoType::Sort::Long:
+ case codemaker::UnoType::Sort::UnsignedLong:
+ case codemaker::UnoType::Sort::Hyper:
+ case codemaker::UnoType::Sort::UnsignedHyper:
+ case codemaker::UnoType::Sort::Float:
+ case codemaker::UnoType::Sort::Double:
+ case codemaker::UnoType::Sort::Char:
+ case codemaker::UnoType::Sort::String:
+ case codemaker::UnoType::Sort::Type:
+ case codemaker::UnoType::Sort::Any:
+ {
+ static char const * const
+ simpleTypeDescriptors[static_cast<int>(codemaker::UnoType::Sort::Any) + 1][2] = {
+ { "V", "Ljava/lang/Void;" },
+ { "Z", "Ljava/lang/Boolean;" },
+ { "B", "Ljava/lang/Byte;" },
+ { "S", "Ljava/lang/Short;" },
+ { "S", "Ljava/lang/Short;" },
+ { "I", "Ljava/lang/Integer;" },
+ { "I", "Ljava/lang/Integer;" },
+ { "J", "Ljava/lang/Long;" },
+ { "J", "Ljava/lang/Long;" },
+ { "F", "Ljava/lang/Float;" },
+ { "D", "Ljava/lang/Double;" },
+ { "C", "Ljava/lang/Character;" },
+ { "Ljava/lang/String;", "Ljava/lang/String;" },
+ { "Lcom/sun/star/uno/Type;", "Lcom/sun/star/uno/Type;" },
+ { "Ljava/lang/Object;", "Ljava/lang/Object;" } };
+ char const * s
+ = simpleTypeDescriptors[static_cast<int>(sort)][rank == 0 && classType];
+ if (descriptor != nullptr) {
+ descriptor->append(s);
+ }
+ if (signature != nullptr) {
+ signature->append(s);
+ }
+ static SpecialType const
+ simpleTypeSpecials[static_cast<int>(codemaker::UnoType::Sort::Any) + 1] = {
+ SPECIAL_TYPE_NONE, SPECIAL_TYPE_NONE, SPECIAL_TYPE_NONE,
+ SPECIAL_TYPE_NONE, SPECIAL_TYPE_UNSIGNED, SPECIAL_TYPE_NONE,
+ SPECIAL_TYPE_UNSIGNED, SPECIAL_TYPE_NONE, SPECIAL_TYPE_UNSIGNED,
+ SPECIAL_TYPE_NONE, SPECIAL_TYPE_NONE, SPECIAL_TYPE_NONE,
+ SPECIAL_TYPE_NONE, SPECIAL_TYPE_NONE, SPECIAL_TYPE_ANY };
+ return simpleTypeSpecials[static_cast<int>(sort)];
+ }
+ case codemaker::UnoType::Sort::Interface:
+ if (nucleus == "com.sun.star.uno.XInterface") {
+ if (descriptor != nullptr) {
+ descriptor->append("Ljava/lang/Object;");
+ }
+ if (signature != nullptr) {
+ signature->append("Ljava/lang/Object;");
+ }
+ return SPECIAL_TYPE_INTERFACE;
+ }
+ [[fallthrough]];
+ case codemaker::UnoType::Sort::Sequence:
+ case codemaker::UnoType::Sort::Enum:
+ case codemaker::UnoType::Sort::PlainStruct:
+ case codemaker::UnoType::Sort::InstantiatedPolymorphicStruct:
+ if (dependencies != nullptr) {
+ dependencies->insert(nucleus);
+ }
+ if (descriptor != nullptr) {
+ descriptor->append(
+ "L" + codemaker::convertString(nucleus).replace('.', '/')
+ + ";");
+ }
+ if (signature != nullptr) {
+ signature->append(
+ "L" + codemaker::convertString(nucleus).replace('.', '/'));
+ if (!arguments.empty()) {
+ signature->append('<');
+ for (const OUString& arg : arguments)
+ {
+ translateUnoTypeToDescriptor(
+ manager, arg, false, true, dependencies, nullptr, signature,
+ needsSignature, nullptr);
+ }
+ signature->append('>');
+ *needsSignature = true;
+ }
+ signature->append(';');
+ }
+ return SPECIAL_TYPE_NONE;
+ default:
+ throw CannotDumpException(
+ "unexpected nucleus \"" + nucleus
+ + "\" in call to translateUnoTypeToDescriptor");
+ }
+}
+
+SpecialType translateUnoTypeToDescriptor(
+ rtl::Reference< TypeManager > const & manager, std::u16string_view type,
+ bool array, bool classType, std::set<OUString> * dependencies,
+ OStringBuffer * descriptor, OStringBuffer * signature,
+ bool * needsSignature, PolymorphicUnoType * polymorphicUnoType)
+{
+ assert(manager.is());
+ OUString nucleus;
+ sal_Int32 rank;
+ std::vector< OUString > args;
+ codemaker::UnoType::Sort sort = manager->decompose(
+ type, true, &nucleus, &rank, &args, nullptr);
+ return translateUnoTypeToDescriptor(
+ manager, sort, nucleus, rank, args, array, classType, dependencies,
+ descriptor, signature, needsSignature, polymorphicUnoType);
+}
+
+SpecialType getFieldDescriptor(
+ rtl::Reference< TypeManager > const & manager, std::set<OUString> * dependencies,
+ std::u16string_view type, OString * descriptor, OString * signature,
+ PolymorphicUnoType * polymorphicUnoType)
+{
+ assert(descriptor != nullptr);
+ OStringBuffer desc(64);
+ OStringBuffer sig(64);
+ bool needsSig = false;
+ SpecialType specialType = translateUnoTypeToDescriptor(
+ manager, type, false, false, dependencies, &desc, &sig, &needsSig,
+ polymorphicUnoType);
+ *descriptor = desc.makeStringAndClear();
+ if (signature != nullptr) {
+ if (needsSig) {
+ *signature = sig.makeStringAndClear();
+ } else {
+ signature->clear();
+ }
+ }
+ return specialType;
+}
+
+class MethodDescriptor {
+public:
+ MethodDescriptor(
+ rtl::Reference< TypeManager > manager,
+ std::set<OUString> * dependencies, std::u16string_view returnType,
+ SpecialType * specialReturnType,
+ PolymorphicUnoType * polymorphicUnoType);
+
+ SpecialType addParameter(
+ std::u16string_view type, bool array, bool dependency,
+ PolymorphicUnoType * polymorphicUnoType);
+
+ void addTypeParameter(OUString const & name);
+
+ OString getDescriptor() const;
+
+ OString getSignature() const { return m_needsSignature ? m_signatureStart + m_signatureEnd : OString();}
+
+private:
+ rtl::Reference< TypeManager > m_manager;
+ std::set<OUString> * m_dependencies;
+ OStringBuffer m_descriptorStart{16*1024};
+ OString m_descriptorEnd;
+ OStringBuffer m_signatureStart{16*1024};
+ OString m_signatureEnd;
+ bool m_needsSignature;
+};
+
+MethodDescriptor::MethodDescriptor(
+ rtl::Reference< TypeManager > manager, std::set<OUString> * dependencies,
+ std::u16string_view returnType, SpecialType * specialReturnType,
+ PolymorphicUnoType * polymorphicUnoType):
+ m_manager(std::move(manager)), m_dependencies(dependencies), m_needsSignature(false)
+{
+ assert(dependencies != nullptr);
+ m_descriptorStart.append('(');
+ m_signatureStart.append('(');
+ OStringBuffer descEnd(128);
+ descEnd.append(')');
+ OStringBuffer sigEnd(128);
+ sigEnd.append(')');
+ SpecialType special = translateUnoTypeToDescriptor(
+ m_manager, returnType, false, false, m_dependencies, &descEnd, &sigEnd,
+ &m_needsSignature, polymorphicUnoType);
+ m_descriptorEnd = descEnd.makeStringAndClear();
+ m_signatureEnd = sigEnd.makeStringAndClear();
+ if (specialReturnType != nullptr) {
+ *specialReturnType = special;
+ }
+}
+
+SpecialType MethodDescriptor::addParameter(
+ std::u16string_view type, bool array, bool dependency,
+ PolymorphicUnoType * polymorphicUnoType)
+{
+ return translateUnoTypeToDescriptor(
+ m_manager, type, array, false, dependency ? m_dependencies : nullptr,
+ &m_descriptorStart, &m_signatureStart, &m_needsSignature,
+ polymorphicUnoType);
+}
+
+void MethodDescriptor::addTypeParameter(OUString const & name) {
+ m_descriptorStart.append("Ljava/lang/Object;");
+ m_signatureStart.append("T" + codemaker::convertString(name) + ";");
+ m_needsSignature = true;
+}
+
+OString MethodDescriptor::getDescriptor() const {
+ return m_descriptorStart + m_descriptorEnd;
+}
+
+
+class TypeInfo {
+public:
+ enum Kind { KIND_MEMBER, KIND_ATTRIBUTE, KIND_METHOD, KIND_PARAMETER };
+
+ // Same values as in com/sun/star/lib/uno/typeinfo/TypeInfo.java:
+ enum Flags {
+ FLAG_READONLY = 0x008, FLAG_BOUND = 0x100
+ };
+
+ // KIND_MEMBER:
+ TypeInfo(
+ OString name, SpecialType specialType, sal_Int32 index,
+ PolymorphicUnoType const & polymorphicUnoType,
+ sal_Int32 typeParameterIndex);
+
+ // KIND_ATTRIBUTE/METHOD:
+ TypeInfo(
+ Kind kind, OString name, SpecialType specialType, Flags flags,
+ sal_Int32 index, PolymorphicUnoType polymorphicUnoType);
+
+ // KIND_PARAMETER:
+ TypeInfo(
+ OString parameterName, SpecialType specialType,
+ bool inParameter, bool outParameter, OString methodName,
+ sal_Int32 index, PolymorphicUnoType polymorphicUnoType);
+
+ sal_uInt16 generateCode(ClassFile::Code & code, std::set<OUString> * dependencies)
+ const;
+
+ void generatePolymorphicUnoTypeCode(
+ ClassFile::Code & code, std::set<OUString> * dependencies) const;
+
+private:
+ Kind m_kind;
+ OString m_name;
+ sal_Int32 m_flags;
+ sal_Int32 m_index;
+ OString m_methodName;
+ PolymorphicUnoType m_polymorphicUnoType;
+ sal_Int32 m_typeParameterIndex;
+};
+
+sal_Int32 translateSpecialTypeFlags(
+ SpecialType specialType, bool inParameter, bool outParameter)
+{
+ static sal_Int32 const specialTypeFlags[SPECIAL_TYPE_INTERFACE + 1] = {
+ 0, 0x0040 /* ANY */, 0x0004 /* UNSIGNED */, 0x0080 /* INTERFACE */ };
+ sal_Int32 flags = specialTypeFlags[specialType];
+ if (inParameter) {
+ flags |= 0x0001; /* IN */
+ }
+ if (outParameter) {
+ flags |= 0x0002; /* OUT */
+ }
+ return flags;
+}
+
+TypeInfo::TypeInfo(
+ OString name, SpecialType specialType, sal_Int32 index,
+ PolymorphicUnoType const & polymorphicUnoType,
+ sal_Int32 typeParameterIndex):
+ m_kind(KIND_MEMBER), m_name(std::move(name)),
+ m_flags(translateSpecialTypeFlags(specialType, false, false)),
+ m_index(index), m_polymorphicUnoType(polymorphicUnoType),
+ m_typeParameterIndex(typeParameterIndex)
+{
+ assert(
+ polymorphicUnoType.kind == PolymorphicUnoType::KIND_NONE
+ ? typeParameterIndex >= -1 : typeParameterIndex == -1);
+}
+
+TypeInfo::TypeInfo(
+ Kind kind, OString name, SpecialType specialType, Flags flags,
+ sal_Int32 index, PolymorphicUnoType polymorphicUnoType):
+ m_kind(kind), m_name(std::move(name)),
+ m_flags(flags | translateSpecialTypeFlags(specialType, false, false)),
+ m_index(index), m_polymorphicUnoType(std::move(polymorphicUnoType)),
+ m_typeParameterIndex(0)
+{
+ assert(kind == KIND_ATTRIBUTE || kind == KIND_METHOD);
+}
+
+TypeInfo::TypeInfo(
+ OString parameterName, SpecialType specialType, bool inParameter,
+ bool outParameter, OString methodName, sal_Int32 index,
+ PolymorphicUnoType polymorphicUnoType):
+ m_kind(KIND_PARAMETER), m_name(std::move(parameterName)),
+ m_flags(translateSpecialTypeFlags(specialType, inParameter, outParameter)),
+ m_index(index), m_methodName(std::move(methodName)),
+ m_polymorphicUnoType(std::move(polymorphicUnoType)),
+ m_typeParameterIndex(0)
+{}
+
+sal_uInt16 TypeInfo::generateCode(
+ ClassFile::Code & code, std::set<OUString> * dependencies) const
+{
+ switch (m_kind) {
+ case KIND_MEMBER:
+ code.instrNew("com/sun/star/lib/uno/typeinfo/MemberTypeInfo");
+ code.instrDup();
+ code.loadStringConstant(m_name);
+ code.loadIntegerConstant(m_index);
+ code.loadIntegerConstant(m_flags);
+ if (m_polymorphicUnoType.kind != PolymorphicUnoType::KIND_NONE) {
+ generatePolymorphicUnoTypeCode(code, dependencies);
+ code.loadIntegerConstant(m_typeParameterIndex);
+ code.instrInvokespecial(
+ "com/sun/star/lib/uno/typeinfo/MemberTypeInfo", "<init>",
+ "(Ljava/lang/String;IILcom/sun/star/uno/Type;I)V");
+ return 8;
+ } else if (m_typeParameterIndex >= 0) {
+ code.instrAconstNull();
+ code.loadIntegerConstant(m_typeParameterIndex);
+ code.instrInvokespecial(
+ "com/sun/star/lib/uno/typeinfo/MemberTypeInfo", "<init>",
+ "(Ljava/lang/String;IILcom/sun/star/uno/Type;I)V");
+ return 6;
+ } else {
+ code.instrInvokespecial(
+ "com/sun/star/lib/uno/typeinfo/MemberTypeInfo", "<init>",
+ "(Ljava/lang/String;II)V");
+ return 4;
+ }
+ case KIND_ATTRIBUTE:
+ code.instrNew("com/sun/star/lib/uno/typeinfo/AttributeTypeInfo");
+ code.instrDup();
+ code.loadStringConstant(m_name);
+ code.loadIntegerConstant(m_index);
+ code.loadIntegerConstant(m_flags);
+ if (m_polymorphicUnoType.kind != PolymorphicUnoType::KIND_NONE) {
+ generatePolymorphicUnoTypeCode(code, dependencies);
+ code.instrInvokespecial(
+ "com/sun/star/lib/uno/typeinfo/AttributeTypeInfo", "<init>",
+ "(Ljava/lang/String;IILcom/sun/star/uno/Type;)V");
+ return 8;
+ } else {
+ code.instrInvokespecial(
+ "com/sun/star/lib/uno/typeinfo/AttributeTypeInfo", "<init>",
+ "(Ljava/lang/String;II)V");
+ return 4;
+ }
+ case KIND_METHOD:
+ code.instrNew("com/sun/star/lib/uno/typeinfo/MethodTypeInfo");
+ code.instrDup();
+ code.loadStringConstant(m_name);
+ code.loadIntegerConstant(m_index);
+ code.loadIntegerConstant(m_flags);
+ if (m_polymorphicUnoType.kind != PolymorphicUnoType::KIND_NONE) {
+ generatePolymorphicUnoTypeCode(code, dependencies);
+ code.instrInvokespecial(
+ "com/sun/star/lib/uno/typeinfo/MethodTypeInfo", "<init>",
+ "(Ljava/lang/String;IILcom/sun/star/uno/Type;)V");
+ return 8;
+ } else {
+ code.instrInvokespecial(
+ "com/sun/star/lib/uno/typeinfo/MethodTypeInfo", "<init>",
+ "(Ljava/lang/String;II)V");
+ return 4;
+ }
+ case KIND_PARAMETER:
+ code.instrNew("com/sun/star/lib/uno/typeinfo/ParameterTypeInfo");
+ code.instrDup();
+ code.loadStringConstant(m_name);
+ code.loadStringConstant(m_methodName);
+ code.loadIntegerConstant(m_index);
+ code.loadIntegerConstant(m_flags);
+ if (m_polymorphicUnoType.kind != PolymorphicUnoType::KIND_NONE) {
+ generatePolymorphicUnoTypeCode(code, dependencies);
+ code.instrInvokespecial(
+ "com/sun/star/lib/uno/typeinfo/ParameterTypeInfo", "<init>",
+ ("(Ljava/lang/String;Ljava/lang/String;II"
+ "Lcom/sun/star/uno/Type;)V"));
+ return 9;
+ } else {
+ code.instrInvokespecial(
+ "com/sun/star/lib/uno/typeinfo/ParameterTypeInfo", "<init>",
+ "(Ljava/lang/String;Ljava/lang/String;II)V");
+ return 5;
+ }
+ default:
+ assert(false);
+ return 0;
+ }
+}
+
+void TypeInfo::generatePolymorphicUnoTypeCode(
+ ClassFile::Code & code, std::set<OUString> * dependencies) const
+{
+ assert(dependencies != nullptr);
+ assert(m_polymorphicUnoType.kind != PolymorphicUnoType::KIND_NONE);
+ code.instrNew("com/sun/star/uno/Type");
+ code.instrDup();
+ code.loadStringConstant(
+ codemaker::convertString(m_polymorphicUnoType.name));
+ if (m_polymorphicUnoType.kind == PolymorphicUnoType::KIND_STRUCT) {
+ code.instrGetstatic(
+ "com/sun/star/uno/TypeClass", "STRUCT",
+ "Lcom/sun/star/uno/TypeClass;");
+ } else {
+ code.instrGetstatic(
+ "com/sun/star/uno/TypeClass", "SEQUENCE",
+ "Lcom/sun/star/uno/TypeClass;");
+ }
+ dependencies->insert("com.sun.star.uno.TypeClass");
+ code.instrInvokespecial(
+ "com/sun/star/uno/Type", "<init>",
+ "(Ljava/lang/String;Lcom/sun/star/uno/TypeClass;)V");
+}
+
+void writeClassFile(
+ JavaOptions const & options, OString const & type,
+ ClassFile const & classFile)
+{
+ OString path;
+ if (options.isValid("-O")) {
+ path = options.getOption("-O");
+ }
+ OString filename(createFileNameFromType(path, type, ".class"));
+ bool bCheck = false;
+ if (fileExists(filename)) {
+ if (options.isValid("-G")) {
+ return;
+ }
+ bCheck = options.isValid("-Gc");
+ }
+ FileStream tempfile;
+ tempfile.createTempFile(getTempDir(filename));
+ if (!tempfile.isValid()) {
+ throw CannotDumpException(
+ "Cannot create temporary file for " + b2u(filename));
+ }
+ OString tempname(tempfile.getName());
+ try {
+ classFile.write(tempfile);
+ } catch (...) {
+ // Remove existing file for consistency:
+ if (fileExists(filename)) {
+ removeTypeFile(filename);
+ }
+ tempfile.close();
+ removeTypeFile(tempname);
+ throw;
+ }
+ tempfile.close();
+ if (!makeValidTypeFile(filename, tempname, bCheck)) {
+ throw CannotDumpException(
+ "Cannot create " + b2u(filename) + " from temporary file "
+ + b2u(tempname));
+ }
+}
+
+void addTypeInfo(
+ OString const & className, std::vector< TypeInfo > const & typeInfo,
+ std::set<OUString> * dependencies, ClassFile * classFile)
+{
+ assert(classFile != nullptr);
+ std::vector< TypeInfo >::size_type typeInfos = typeInfo.size();
+ if (typeInfos > SAL_MAX_INT32) {
+ throw CannotDumpException(
+ "UNOTYPEINFO array too big for Java class file format");
+ }
+ if (typeInfos == 0)
+ return;
+
+ classFile->addField(
+ static_cast< ClassFile::AccessFlags >(
+ ClassFile::ACC_PUBLIC | ClassFile::ACC_STATIC
+ | ClassFile::ACC_FINAL),
+ "UNOTYPEINFO", "[Lcom/sun/star/lib/uno/typeinfo/TypeInfo;",
+ 0, "");
+ std::unique_ptr< ClassFile::Code > code(classFile->newCode());
+ code->loadIntegerConstant(static_cast< sal_Int32 >(typeInfos));
+ code->instrAnewarray("com/sun/star/lib/uno/typeinfo/TypeInfo");
+ sal_Int32 index = 0;
+ sal_uInt16 stack = 0;
+ for (const TypeInfo& ti : typeInfo)
+ {
+ code->instrDup();
+ code->loadIntegerConstant(index++);
+ stack = std::max(stack, ti.generateCode(*code, dependencies));
+ code->instrAastore();
+ }
+ code->instrPutstatic(
+ className, "UNOTYPEINFO",
+ "[Lcom/sun/star/lib/uno/typeinfo/TypeInfo;");
+ code->instrReturn();
+ if (stack > SAL_MAX_UINT16 - 4) {
+ throw CannotDumpException(
+ "Stack too big for Java class file format");
+ }
+ code->setMaxStackAndLocals(static_cast< sal_uInt16 >(stack + 4), 0);
+ classFile->addMethod(
+ static_cast< ClassFile::AccessFlags >(
+ ClassFile::ACC_PRIVATE | ClassFile::ACC_STATIC),
+ "<clinit>", "()V", code.get(), std::vector< OString >(), "");
+}
+
+void handleEnumType(
+ const OUString& name, rtl::Reference< unoidl::EnumTypeEntity > const & entity,
+ JavaOptions const & options)
+{
+ assert(entity.is());
+ OString className(codemaker::convertString(name).replace('.', '/'));
+ std::unique_ptr< ClassFile > cf(
+ new ClassFile(
+ static_cast< ClassFile::AccessFlags >(
+ ClassFile::ACC_PUBLIC | ClassFile::ACC_FINAL
+ | ClassFile::ACC_SUPER),
+ className, "com/sun/star/uno/Enum", ""));
+ OString classDescriptor("L" + className + ";");
+ for (const unoidl::EnumTypeEntity::Member& member : entity->getMembers())
+ {
+ OString fieldName(codemaker::convertString(member.name));
+ cf->addField(
+ static_cast< ClassFile::AccessFlags >(
+ ClassFile::ACC_PUBLIC | ClassFile::ACC_STATIC
+ | ClassFile::ACC_FINAL),
+ fieldName, classDescriptor, 0, OString());
+ cf->addField(
+ static_cast< ClassFile::AccessFlags >(
+ ClassFile::ACC_PUBLIC | ClassFile::ACC_STATIC
+ | ClassFile::ACC_FINAL),
+ fieldName + "_value", "I",
+ cf->addIntegerInfo(member.value), "");
+ }
+ std::unique_ptr< ClassFile::Code > code(cf->newCode());
+ code->loadLocalReference(0);
+ code->loadLocalInteger(1);
+ code->instrInvokespecial("com/sun/star/uno/Enum", "<init>", "(I)V");
+ code->instrReturn();
+ code->setMaxStackAndLocals(2, 2);
+ cf->addMethod(
+ ClassFile::ACC_PRIVATE,
+ "<init>", "(I)V", code.get(),
+ std::vector< OString >(), "");
+ code = cf->newCode();
+ code->instrGetstatic(
+ className,
+ codemaker::convertString(entity->getMembers()[0].name),
+ classDescriptor);
+ code->instrAreturn();
+ code->setMaxStackAndLocals(1, 0);
+ cf->addMethod(
+ static_cast< ClassFile::AccessFlags >(
+ ClassFile::ACC_PUBLIC | ClassFile::ACC_STATIC),
+ "getDefault", "()" + classDescriptor,
+ code.get(), std::vector< OString >(), "");
+ code = cf->newCode();
+ code->loadLocalInteger(0);
+ std::map< sal_Int32, OString > map;
+ sal_Int32 min = SAL_MAX_INT32;
+ sal_Int32 max = SAL_MIN_INT32;
+ for (const unoidl::EnumTypeEntity::Member& member : entity->getMembers())
+ {
+ min = std::min(min, member.value);
+ max = std::max(max, member.value);
+ map.emplace(member.value, codemaker::convertString(member.name));
+ }
+ sal_uInt64 size = static_cast< sal_uInt64 >(map.size());
+ if ((static_cast< sal_uInt64 >(max) - static_cast< sal_uInt64 >(min)
+ <= 2 * size)
+ || size > SAL_MAX_INT32)
+ {
+ std::unique_ptr< ClassFile::Code > defCode(cf->newCode());
+ defCode->instrAconstNull();
+ defCode->instrAreturn();
+ std::vector< std::unique_ptr<ClassFile::Code> > blocks;
+ //FIXME: pointers contained in blocks may leak
+ sal_Int32 last = SAL_MAX_INT32;
+ for (const auto& pair : map)
+ {
+ sal_Int32 value = pair.first;
+ if (last != SAL_MAX_INT32) {
+ for (sal_Int32 j = last + 1; j < value; ++j) {
+ blocks.push_back(nullptr);
+ }
+ }
+ last = value;
+ std::unique_ptr< ClassFile::Code > blockCode(cf->newCode());
+ blockCode->instrGetstatic(className, pair.second, classDescriptor);
+ blockCode->instrAreturn();
+ blocks.push_back(std::move(blockCode));
+ }
+ code->instrTableswitch(defCode.get(), min, blocks);
+ } else{
+ std::unique_ptr< ClassFile::Code > defCode(cf->newCode());
+ defCode->instrAconstNull();
+ defCode->instrAreturn();
+ std::vector< std::pair< sal_Int32, ClassFile::Code * > > blocks;
+ //FIXME: pointers contained in blocks may leak
+ for (const auto& pair : map )
+ {
+ std::unique_ptr< ClassFile::Code > blockCode(cf->newCode());
+ blockCode->instrGetstatic(className, pair.second, classDescriptor);
+ blockCode->instrAreturn();
+ blocks.emplace_back(pair.first, blockCode.release());
+ }
+ code->instrLookupswitch(defCode.get(), blocks);
+ for (const std::pair< sal_Int32, ClassFile::Code * >& pair : blocks)
+ {
+ delete pair.second;
+ }
+ }
+ code->setMaxStackAndLocals(1, 1);
+ cf->addMethod(
+ static_cast< ClassFile::AccessFlags >(
+ ClassFile::ACC_PUBLIC | ClassFile::ACC_STATIC),
+ "fromInt", "(I)" + classDescriptor, code.get(),
+ std::vector< OString >(), "");
+ code = cf->newCode();
+ for (const unoidl::EnumTypeEntity::Member& member : entity->getMembers())
+ {
+ code->instrNew(className);
+ code->instrDup();
+ code->loadIntegerConstant(member.value);
+ code->instrInvokespecial(className, "<init>", "(I)V");
+ code->instrPutstatic(
+ className, codemaker::convertString(member.name), classDescriptor);
+ }
+ code->instrReturn();
+ code->setMaxStackAndLocals(3, 0);
+ cf->addMethod(
+ static_cast< ClassFile::AccessFlags >(
+ ClassFile::ACC_PRIVATE | ClassFile::ACC_STATIC),
+ "<clinit>", "()V", code.get(), std::vector< OString >(), "");
+ writeClassFile(options, className, *cf);
+}
+
+void addField(
+ rtl::Reference< TypeManager > const & manager, std::set<OUString> * dependencies,
+ ClassFile * classFile, std::vector< TypeInfo > * typeInfo,
+ sal_Int32 typeParameterIndex, OUString const & type, OUString const & name,
+ sal_Int32 index)
+{
+ assert(classFile != nullptr);
+ assert(typeInfo != nullptr);
+ OString descriptor;
+ OString signature;
+ SpecialType specialType;
+ PolymorphicUnoType polymorphicUnoType;
+ if (typeParameterIndex >= 0) {
+ descriptor = "Ljava/lang/Object;";
+ signature = "T" + codemaker::convertString(type).replace('.', '/')
+ + ";";
+ specialType = SPECIAL_TYPE_NONE; //TODO: SPECIAL_TYPE_TYPE_PARAMETER?
+ } else {
+ specialType = getFieldDescriptor(
+ manager, dependencies, type, &descriptor, &signature,
+ &polymorphicUnoType);
+ }
+ classFile->addField(
+ ClassFile::ACC_PUBLIC, codemaker::convertString(name), descriptor, 0,
+ signature);
+ typeInfo->push_back(
+ TypeInfo(
+ codemaker::convertString(name), specialType, index,
+ polymorphicUnoType, typeParameterIndex));
+}
+
+sal_uInt16 addFieldInit(
+ rtl::Reference< TypeManager > const & manager, OString const & className,
+ OUString const & fieldName, bool typeParameter, std::u16string_view fieldType,
+ std::set<OUString> * dependencies, ClassFile::Code * code)
+{
+ assert(manager.is());
+ assert(code != nullptr);
+ if (typeParameter) {
+ return 0;
+ }
+ OString name(codemaker::convertString(fieldName));
+ OUString nucleus;
+ sal_Int32 rank;
+ std::vector< OUString > args;
+ rtl::Reference< unoidl::Entity > ent;
+ codemaker::UnoType::Sort sort = manager->decompose(
+ fieldType, true, &nucleus, &rank, &args, &ent);
+ if (rank == 0) {
+ switch (sort) {
+ case codemaker::UnoType::Sort::Boolean:
+ case codemaker::UnoType::Sort::Byte:
+ case codemaker::UnoType::Sort::Short:
+ case codemaker::UnoType::Sort::UnsignedShort:
+ case codemaker::UnoType::Sort::Long:
+ case codemaker::UnoType::Sort::UnsignedLong:
+ case codemaker::UnoType::Sort::Hyper:
+ case codemaker::UnoType::Sort::UnsignedHyper:
+ case codemaker::UnoType::Sort::Float:
+ case codemaker::UnoType::Sort::Double:
+ case codemaker::UnoType::Sort::Char:
+ case codemaker::UnoType::Sort::Interface:
+ return 0;
+ case codemaker::UnoType::Sort::String:
+ code->loadLocalReference(0);
+ code->loadStringConstant(OString());
+ code->instrPutfield(className, name, "Ljava/lang/String;");
+ return 2;
+ case codemaker::UnoType::Sort::Type:
+ code->loadLocalReference(0);
+ code->instrGetstatic(
+ "com/sun/star/uno/Type", "VOID", "Lcom/sun/star/uno/Type;");
+ code->instrPutfield(className, name, "Lcom/sun/star/uno/Type;");
+ return 2;
+ case codemaker::UnoType::Sort::Any:
+ code->loadLocalReference(0);
+ code->instrGetstatic(
+ "com/sun/star/uno/Any", "VOID", "Lcom/sun/star/uno/Any;");
+ code->instrPutfield(className, name, "Ljava/lang/Object;");
+ return 2;
+ case codemaker::UnoType::Sort::Enum:
+ {
+ rtl::Reference< unoidl::EnumTypeEntity > ent2(
+ dynamic_cast< unoidl::EnumTypeEntity * >(ent.get()));
+ assert(ent2.is());
+ code->loadLocalReference(0);
+ OStringBuffer descBuf(128);
+ translateUnoTypeToDescriptor(
+ manager, sort, nucleus, 0, std::vector< OUString >(), false,
+ false, dependencies, &descBuf, nullptr, nullptr, nullptr);
+ OString desc(descBuf.makeStringAndClear());
+ code->instrGetstatic(
+ codemaker::convertString(nucleus).replace('.', '/'),
+ codemaker::convertString(ent2->getMembers()[0].name), desc);
+ code->instrPutfield(className, name, desc);
+ return 2;
+ }
+ case codemaker::UnoType::Sort::PlainStruct:
+ case codemaker::UnoType::Sort::InstantiatedPolymorphicStruct:
+ {
+ code->loadLocalReference(0);
+ code->instrNew(
+ codemaker::convertString(nucleus).replace('.', '/'));
+ code->instrDup();
+ code->instrInvokespecial(
+ codemaker::convertString(nucleus).replace('.', '/'),
+ "<init>", "()V");
+ OStringBuffer desc(128);
+ translateUnoTypeToDescriptor(
+ manager, sort, nucleus, 0, args, false, false, dependencies,
+ &desc, nullptr, nullptr, nullptr);
+ code->instrPutfield(className, name, desc.makeStringAndClear());
+ return 3;
+ }
+ case codemaker::UnoType::Sort::Sequence:
+ case codemaker::UnoType::Sort::Typedef:
+ for (;;) std::abort(); // this cannot happen
+ default:
+ throw CannotDumpException(
+ OUString::Concat("unexpected entity \"") + fieldType
+ + "\" in call to addFieldInit");
+ }
+ }
+ code->loadLocalReference(0);
+ code->loadIntegerConstant(0);
+ if (rank == 1) {
+ if (sort >= codemaker::UnoType::Sort::Boolean
+ && sort <= codemaker::UnoType::Sort::Char)
+ {
+ code->instrNewarray(sort);
+ } else {
+ code->instrAnewarray(
+ codemaker::java::translateUnoToJavaType(
+ sort, codemaker::convertString(nucleus).replace('.', '/'),
+ false));
+ }
+ } else {
+ OStringBuffer desc(128);
+ translateUnoTypeToDescriptor(
+ manager, sort, nucleus, rank - 1, std::vector< OUString >(), false,
+ false, dependencies, &desc, nullptr, nullptr, nullptr);
+ code->instrAnewarray(desc.makeStringAndClear());
+ }
+ OStringBuffer desc(128);
+ translateUnoTypeToDescriptor(
+ manager, sort, nucleus, rank, std::vector< OUString >(), false, false,
+ dependencies, &desc, nullptr, nullptr, nullptr);
+ code->instrPutfield(className, name, desc.makeStringAndClear());
+ return 2;
+}
+
+sal_uInt16 addLoadLocal(
+ rtl::Reference< TypeManager > const & manager, ClassFile::Code * code,
+ sal_uInt16 * index, bool typeParameter, std::u16string_view type, bool any,
+ std::set<OUString> * dependencies)
+{
+ assert(manager.is());
+ assert(code != nullptr);
+ assert(index != nullptr);
+ assert(!(typeParameter && any));
+ assert(dependencies != nullptr);
+ sal_uInt16 stack = 1;
+ sal_uInt16 size = 1;
+ if (typeParameter) {
+ code->loadLocalReference(*index);
+ stack = size = 1;
+ } else {
+ OUString nucleus;
+ sal_Int32 rank;
+ std::vector< OUString > args;
+ codemaker::UnoType::Sort sort = manager->decompose(
+ type, true, &nucleus, &rank, &args, nullptr);
+ if (rank == 0) {
+ switch (sort) {
+ case codemaker::UnoType::Sort::Boolean:
+ if (any) {
+ code->instrNew("java/lang/Boolean");
+ code->instrDup();
+ code->loadLocalInteger(*index);
+ code->instrInvokespecial(
+ "java/lang/Boolean", "<init>", "(Z)V");
+ stack = 3;
+ } else {
+ code->loadLocalInteger(*index);
+ stack = 1;
+ }
+ size = 1;
+ break;
+ case codemaker::UnoType::Sort::Byte:
+ if (any) {
+ code->instrNew("java/lang/Byte");
+ code->instrDup();
+ code->loadLocalInteger(*index);
+ code->instrInvokespecial(
+ "java/lang/Byte", "<init>", "(B)V");
+ stack = 3;
+ } else {
+ code->loadLocalInteger(*index);
+ stack = 1;
+ }
+ size = 1;
+ break;
+ case codemaker::UnoType::Sort::Short:
+ if (any) {
+ code->instrNew("java/lang/Short");
+ code->instrDup();
+ code->loadLocalInteger(*index);
+ code->instrInvokespecial(
+ "java/lang/Short", "<init>", "(S)V");
+ stack = 3;
+ } else {
+ code->loadLocalInteger(*index);
+ stack = 1;
+ }
+ size = 1;
+ break;
+ case codemaker::UnoType::Sort::UnsignedShort:
+ if (any) {
+ code->instrNew("com/sun/star/uno/Any");
+ code->instrDup();
+ code->instrGetstatic(
+ "com/sun/star/uno/Type", "UNSIGNED_SHORT",
+ "Lcom/sun/star/uno/Type;");
+ code->instrNew("java/lang/Short");
+ code->instrDup();
+ code->loadLocalInteger(*index);
+ code->instrInvokespecial(
+ "java/lang/Short", "<init>", "(S)V");
+ code->instrInvokespecial(
+ "com/sun/star/uno/Any", "<init>",
+ "(Lcom/sun/star/uno/Type;Ljava/lang/Object;)V");
+ stack = 6;
+ } else {
+ code->loadLocalInteger(*index);
+ stack = 1;
+ }
+ size = 1;
+ break;
+ case codemaker::UnoType::Sort::Long:
+ if (any) {
+ code->instrNew("java/lang/Integer");
+ code->instrDup();
+ code->loadLocalInteger(*index);
+ code->instrInvokespecial(
+ "java/lang/Integer", "<init>", "(I)V");
+ stack = 3;
+ } else {
+ code->loadLocalInteger(*index);
+ stack = 1;
+ }
+ size = 1;
+ break;
+ case codemaker::UnoType::Sort::UnsignedLong:
+ if (any) {
+ code->instrNew("com/sun/star/uno/Any");
+ code->instrDup();
+ code->instrGetstatic(
+ "com/sun/star/uno/Type", "UNSIGNED_LONG",
+ "Lcom/sun/star/uno/Type;");
+ code->instrNew("java/lang/Integer");
+ code->instrDup();
+ code->loadLocalInteger(*index);
+ code->instrInvokespecial(
+ "java/lang/Integer", "<init>", "(I)V");
+ code->instrInvokespecial(
+ "com/sun/star/uno/Any", "<init>",
+ "(Lcom/sun/star/uno/Type;Ljava/lang/Object;)V");
+ stack = 6;
+ } else {
+ code->loadLocalInteger(*index);
+ stack = 1;
+ }
+ size = 1;
+ break;
+ case codemaker::UnoType::Sort::Hyper:
+ if (any) {
+ code->instrNew("java/lang/Long");
+ code->instrDup();
+ code->loadLocalLong(*index);
+ code->instrInvokespecial(
+ "java/lang/Long", "<init>", "(J)V");
+ stack = 4;
+ } else {
+ code->loadLocalLong(*index);
+ stack = 2;
+ }
+ size = 2;
+ break;
+ case codemaker::UnoType::Sort::UnsignedHyper:
+ if (any) {
+ code->instrNew("com/sun/star/uno/Any");
+ code->instrDup();
+ code->instrGetstatic(
+ "com/sun/star/uno/Type", "UNSIGNED_HYPER",
+ "Lcom/sun/star/uno/Type;");
+ code->instrNew("java/lang/Long");
+ code->instrDup();
+ code->loadLocalLong(*index);
+ code->instrInvokespecial(
+ "java/lang/Long", "<init>", "(J)V");
+ code->instrInvokespecial(
+ "com/sun/star/uno/Any", "<init>",
+ "(Lcom/sun/star/uno/Type;Ljava/lang/Object;)V");
+ stack = 7;
+ } else {
+ code->loadLocalLong(*index);
+ stack = 2;
+ }
+ size = 2;
+ break;
+ case codemaker::UnoType::Sort::Float:
+ if (any) {
+ code->instrNew("java/lang/Float");
+ code->instrDup();
+ code->loadLocalFloat(*index);
+ code->instrInvokespecial(
+ "java/lang/Float", "<init>", "(F)V");
+ stack = 3;
+ } else {
+ code->loadLocalFloat(*index);
+ stack = 1;
+ }
+ size = 1;
+ break;
+ case codemaker::UnoType::Sort::Double:
+ if (any) {
+ code->instrNew("java/lang/Double");
+ code->instrDup();
+ code->loadLocalDouble(*index);
+ code->instrInvokespecial(
+ "java/lang/Double", "<init>", "(D)V");
+ stack = 4;
+ } else {
+ code->loadLocalDouble(*index);
+ stack = 2;
+ }
+ size = 2;
+ break;
+ case codemaker::UnoType::Sort::Char:
+ if (any) {
+ code->instrNew("java/lang/Character");
+ code->instrDup();
+ code->loadLocalInteger(*index);
+ code->instrInvokespecial(
+ "java/lang/Character", "<init>", "(C)V");
+ stack = 3;
+ } else {
+ code->loadLocalInteger(*index);
+ stack = 1;
+ }
+ size = 1;
+ break;
+ case codemaker::UnoType::Sort::String:
+ case codemaker::UnoType::Sort::Type:
+ case codemaker::UnoType::Sort::Any:
+ code->loadLocalReference(*index);
+ stack = size = 1;
+ break;
+ case codemaker::UnoType::Sort::Enum:
+ // Assuming that no Java types are derived from Java types that
+ // are directly derived from com.sun.star.uno.Enum:
+ code->loadLocalReference(*index);
+ stack = size = 1;
+ break;
+ case codemaker::UnoType::Sort::PlainStruct:
+ case codemaker::UnoType::Sort::InstantiatedPolymorphicStruct:
+ if (any) {
+ code->instrNew("com/sun/star/uno/Any");
+ code->instrDup();
+ code->instrNew("com/sun/star/uno/Type");
+ code->instrDup();
+ code->loadStringConstant(
+ codemaker::convertString(
+ createUnoName(manager, nucleus, rank, args)));
+ code->instrGetstatic(
+ "com/sun/star/uno/TypeClass", "STRUCT",
+ "Lcom/sun/star/uno/TypeClass;");
+ dependencies->insert("com.sun.star.uno.TypeClass");
+ code->instrInvokespecial(
+ "com/sun/star/uno/Type", "<init>",
+ "(Ljava/lang/String;Lcom/sun/star/uno/TypeClass;)V");
+ code->loadLocalReference(*index);
+ code->instrInvokespecial(
+ "com/sun/star/uno/Any", "<init>",
+ "(Lcom/sun/star/uno/Type;Ljava/lang/Object;)V");
+ stack = 6;
+ } else {
+ code->loadLocalReference(*index);
+ stack = 1;
+ }
+ size = 1;
+ break;
+ case codemaker::UnoType::Sort::Interface:
+ if (any && nucleus != "com.sun.star.uno.XInterface") {
+ code->instrNew("com/sun/star/uno/Any");
+ code->instrDup();
+ code->instrNew("com/sun/star/uno/Type");
+ code->instrDup();
+ code->loadStringConstant(codemaker::convertString(nucleus));
+ code->instrGetstatic(
+ "com/sun/star/uno/TypeClass", "INTERFACE",
+ "Lcom/sun/star/uno/TypeClass;");
+ dependencies->insert("com.sun.star.uno.TypeClass");
+ code->instrInvokespecial(
+ "com/sun/star/uno/Type", "<init>",
+ "(Ljava/lang/String;Lcom/sun/star/uno/TypeClass;)V");
+ code->loadLocalReference(*index);
+ code->instrInvokespecial(
+ "com/sun/star/uno/Any", "<init>",
+ "(Lcom/sun/star/uno/Type;Ljava/lang/Object;)V");
+ stack = 6;
+ } else {
+ code->loadLocalReference(*index);
+ stack = 1;
+ }
+ size = 1;
+ break;
+ case codemaker::UnoType::Sort::Sequence:
+ case codemaker::UnoType::Sort::Typedef:
+ for (;;) std::abort(); // this cannot happen
+ default:
+ throw CannotDumpException(
+ OUString::Concat("unexpected entity \"") + type
+ + "\" in call to addLoadLocal");
+ }
+ } else {
+ bool bWrap = false;
+ if (any) {
+ switch (sort) {
+ case codemaker::UnoType::Sort::Boolean:
+ case codemaker::UnoType::Sort::Byte:
+ case codemaker::UnoType::Sort::Short:
+ case codemaker::UnoType::Sort::Long:
+ case codemaker::UnoType::Sort::Hyper:
+ case codemaker::UnoType::Sort::Float:
+ case codemaker::UnoType::Sort::Double:
+ case codemaker::UnoType::Sort::Char:
+ case codemaker::UnoType::Sort::String:
+ case codemaker::UnoType::Sort::Type:
+ // assuming that no Java types are derived from
+ // com.sun.star.uno.Type
+ case codemaker::UnoType::Sort::Enum:
+ // assuming that no Java types are derived from Java
+ // types that are directly derived from
+ // com.sun.star.uno.Enum
+ break;
+ case codemaker::UnoType::Sort::UnsignedShort:
+ case codemaker::UnoType::Sort::UnsignedLong:
+ case codemaker::UnoType::Sort::UnsignedHyper:
+ case codemaker::UnoType::Sort::Any:
+ case codemaker::UnoType::Sort::PlainStruct:
+ case codemaker::UnoType::Sort::InstantiatedPolymorphicStruct:
+ case codemaker::UnoType::Sort::Interface:
+ bWrap = true;
+ break;
+ case codemaker::UnoType::Sort::Sequence:
+ case codemaker::UnoType::Sort::Typedef:
+ for (;;) std::abort(); // this cannot happen
+ default:
+ throw CannotDumpException(
+ OUString::Concat("unexpected entity \"") + type
+ + "\" in call to addLoadLocal");
+ }
+ }
+ if (bWrap) {
+ code->instrNew("com/sun/star/uno/Any");
+ code->instrDup();
+ code->instrNew("com/sun/star/uno/Type");
+ code->instrDup();
+ code->loadStringConstant(
+ codemaker::convertString(
+ createUnoName(manager, nucleus, rank, args)));
+ code->instrInvokespecial(
+ "com/sun/star/uno/Type", "<init>", "(Ljava/lang/String;)V");
+ code->loadLocalReference(*index);
+ code->instrInvokespecial(
+ "com/sun/star/uno/Any", "<init>",
+ "(Lcom/sun/star/uno/Type;Ljava/lang/Object;)V");
+ stack = 5;
+ } else {
+ code->loadLocalReference(*index);
+ stack = 1;
+ }
+ size = 1;
+ }
+ }
+ if (*index > SAL_MAX_UINT16 - size) {
+ throw CannotDumpException(
+ "Too many local variables for Java class file format");
+ }
+ *index = *index + size;
+ return stack;
+}
+
+sal_uInt16 addDirectArgument(
+ rtl::Reference< TypeManager > const & manager, std::set<OUString> * dependencies,
+ MethodDescriptor * methodDescriptor, ClassFile::Code * code,
+ sal_uInt16 * index, OString const & className, OString const & fieldName,
+ bool typeParameter, OUString const & fieldType)
+{
+ assert(methodDescriptor != nullptr);
+ assert(code != nullptr);
+ OString desc;
+ if (typeParameter) {
+ methodDescriptor->addTypeParameter(fieldType);
+ desc = "Ljava/lang/Object;";
+ } else {
+ methodDescriptor->addParameter(fieldType, false, true, nullptr);
+ getFieldDescriptor(manager, dependencies, fieldType, &desc, nullptr, nullptr);
+ }
+ code->loadLocalReference(0);
+ sal_uInt16 stack = addLoadLocal(
+ manager, code, index, typeParameter, fieldType, false, dependencies);
+ code->instrPutfield(className, fieldName, desc);
+ return stack + 1;
+}
+
+void addPlainStructBaseArguments(
+ rtl::Reference< TypeManager > const & manager, std::set<OUString> * dependencies,
+ MethodDescriptor * methodDescriptor, ClassFile::Code * code,
+ OUString const & base, sal_uInt16 * index)
+{
+ assert(manager.is());
+ assert(methodDescriptor != nullptr);
+ rtl::Reference< unoidl::Entity > ent;
+ if (manager->getSort(base, &ent)
+ != codemaker::UnoType::Sort::PlainStruct)
+ {
+ throw CannotDumpException(
+ "unexpected entity \"" + base
+ + "\" in call to addPlainStructBaseArguments");
+ }
+ unoidl::PlainStructTypeEntity& ent2(dynamic_cast<unoidl::PlainStructTypeEntity&>(*ent));
+ if (!ent2.getDirectBase().isEmpty()) {
+ addPlainStructBaseArguments(
+ manager, dependencies, methodDescriptor, code,
+ ent2.getDirectBase(), index);
+ }
+ for (const unoidl::PlainStructTypeEntity::Member& member : ent2.getDirectMembers())
+ {
+ methodDescriptor->addParameter(member.type, false, true, nullptr);
+ addLoadLocal(manager, code, index, false, member.type, false, dependencies);
+ }
+}
+
+void handlePlainStructType(
+ const OUString& name,
+ rtl::Reference< unoidl::PlainStructTypeEntity > const & entity,
+ rtl::Reference< TypeManager > const & manager, JavaOptions const & options,
+ std::set<OUString> * dependencies)
+{
+ assert(entity.is());
+ assert(dependencies != nullptr);
+ OString className(codemaker::convertString(name).replace('.', '/'));
+ OString superClass;
+ if (entity->getDirectBase().isEmpty()) {
+ superClass = "java/lang/Object";
+ } else {
+ superClass = codemaker::convertString(entity->getDirectBase()).
+ replace('.', '/');
+ dependencies->insert(entity->getDirectBase());
+ }
+ std::unique_ptr< ClassFile > cf(
+ new ClassFile(
+ static_cast< ClassFile::AccessFlags >(
+ ClassFile::ACC_PUBLIC | ClassFile::ACC_SUPER),
+ className, superClass, ""));
+ std::vector< TypeInfo > typeInfo;
+ sal_Int32 index = 0;
+ for (const unoidl::PlainStructTypeEntity::Member& member : entity->getDirectMembers())
+ {
+ addField(
+ manager, dependencies, cf.get(), &typeInfo, -1, member.type, member.name,
+ index++);
+ }
+ std::unique_ptr< ClassFile::Code > code(cf->newCode());
+ code->loadLocalReference(0);
+ code->instrInvokespecial(superClass, "<init>", "()V");
+ sal_uInt16 stack = 0;
+ for (const unoidl::PlainStructTypeEntity::Member& member : entity->getDirectMembers())
+ {
+ stack = std::max(
+ stack,
+ addFieldInit(
+ manager, className, member.name, false, member.type, dependencies,
+ code.get()));
+ }
+ code->instrReturn();
+ code->setMaxStackAndLocals(stack + 1, 1);
+ cf->addMethod(
+ ClassFile::ACC_PUBLIC, "<init>", "()V", code.get(),
+ std::vector< OString >(), "");
+ MethodDescriptor desc(manager, dependencies, u"void", nullptr, nullptr);
+ code = cf->newCode();
+ code->loadLocalReference(0);
+ sal_uInt16 index2 = 1;
+ if (!entity->getDirectBase().isEmpty()) {
+ addPlainStructBaseArguments(
+ manager, dependencies, &desc, code.get(), entity->getDirectBase(),
+ &index2);
+ }
+ code->instrInvokespecial(superClass, "<init>", desc.getDescriptor());
+ sal_uInt16 maxSize = index2;
+ for (const unoidl::PlainStructTypeEntity::Member& member : entity->getDirectMembers())
+ {
+ maxSize = std::max(
+ maxSize,
+ addDirectArgument(
+ manager, dependencies, &desc, code.get(), &index2, className,
+ codemaker::convertString(member.name), false, member.type));
+ }
+ code->instrReturn();
+ code->setMaxStackAndLocals(maxSize, index2);
+ cf->addMethod(
+ ClassFile::ACC_PUBLIC, "<init>", desc.getDescriptor(), code.get(),
+ std::vector< OString >(), desc.getSignature());
+ addTypeInfo(className, typeInfo, dependencies, cf.get());
+ writeClassFile(options, className, *cf);
+}
+
+void handlePolyStructType(
+ const OUString& name,
+ rtl::Reference< unoidl::PolymorphicStructTypeTemplateEntity > const &
+ entity,
+ rtl::Reference< TypeManager > const & manager, JavaOptions const & options,
+ std::set<OUString> * dependencies)
+{
+ assert(entity.is());
+ OString className(codemaker::convertString(name).replace('.', '/'));
+ std::map< OUString, sal_Int32 > typeParameters;
+ OStringBuffer sig(128);
+ sig.append("<");
+ sal_Int32 index = 0;
+ for (const OUString& param : entity->getTypeParameters())
+ {
+ sig.append(codemaker::convertString(param) + ":Ljava/lang/Object;");
+ if (!typeParameters.emplace(param, index++).second)
+ {
+ throw CannotDumpException("Bad type information"); //TODO
+ }
+ }
+ sig.append(">Ljava/lang/Object;");
+ std::unique_ptr< ClassFile > cf(
+ new ClassFile(
+ static_cast< ClassFile::AccessFlags >(
+ ClassFile::ACC_PUBLIC | ClassFile::ACC_SUPER),
+ className, "java/lang/Object", sig.makeStringAndClear()));
+ std::vector< TypeInfo > typeInfo;
+ index = 0;
+ for (const unoidl::PolymorphicStructTypeTemplateEntity::Member& member : entity->getMembers())
+ {
+ sal_Int32 typeParameterIndex;
+ if (member.parameterized) {
+ std::map< OUString, sal_Int32 >::iterator it(
+ typeParameters.find(member.type));
+ if (it == typeParameters.end()) {
+ throw CannotDumpException("Bad type information"); //TODO
+ }
+ typeParameterIndex = it->second;
+ } else {
+ typeParameterIndex = -1;
+ }
+ addField(
+ manager, dependencies, cf.get(), &typeInfo, typeParameterIndex,
+ member.type, member.name, index++);
+ }
+ std::unique_ptr< ClassFile::Code > code(cf->newCode());
+ code->loadLocalReference(0);
+ code->instrInvokespecial("java/lang/Object", "<init>", "()V");
+ sal_uInt16 stack = 0;
+ for (const unoidl::PolymorphicStructTypeTemplateEntity::Member& member : entity->getMembers())
+ {
+ stack = std::max(
+ stack,
+ addFieldInit(
+ manager, className, member.name, member.parameterized, member.type,
+ dependencies, code.get()));
+ }
+ code->instrReturn();
+ code->setMaxStackAndLocals(stack + 1, 1);
+ cf->addMethod(
+ ClassFile::ACC_PUBLIC, "<init>", "()V", code.get(),
+ std::vector< OString >(), "");
+ MethodDescriptor desc(manager, dependencies, u"void", nullptr, nullptr);
+ code = cf->newCode();
+ code->loadLocalReference(0);
+ sal_uInt16 index2 = 1;
+ code->instrInvokespecial(
+ "java/lang/Object", "<init>", desc.getDescriptor());
+ sal_uInt16 maxSize = index2;
+ for (const unoidl::PolymorphicStructTypeTemplateEntity::Member& member : entity->getMembers())
+ {
+ maxSize = std::max(
+ maxSize,
+ addDirectArgument(
+ manager, dependencies, &desc, code.get(), &index2, className,
+ codemaker::convertString(member.name), member.parameterized, member.type));
+ }
+ code->instrReturn();
+ code->setMaxStackAndLocals(maxSize, index2);
+ cf->addMethod(
+ ClassFile::ACC_PUBLIC, "<init>", desc.getDescriptor(), code.get(),
+ std::vector< OString >(), desc.getSignature());
+ addTypeInfo(className, typeInfo, dependencies, cf.get());
+ writeClassFile(options, className, *cf);
+}
+
+void addExceptionBaseArguments(
+ rtl::Reference< TypeManager > const & manager, std::set<OUString> * dependencies,
+ MethodDescriptor * methodDescriptor, ClassFile::Code * code,
+ OUString const & base, sal_uInt16 * index)
+{
+ assert(manager.is());
+ assert(methodDescriptor != nullptr);
+ rtl::Reference< unoidl::Entity > ent;
+ if (manager->getSort(base, &ent) != codemaker::UnoType::Sort::Exception)
+ {
+ throw CannotDumpException(
+ "unexpected entity \"" + base
+ + "\" in call to addExceptionBaseArguments");
+ }
+ unoidl::ExceptionTypeEntity& ent2(dynamic_cast<unoidl::ExceptionTypeEntity&>(*ent));
+ bool baseException = base == "com.sun.star.uno.Exception";
+ if (!baseException) {
+ addExceptionBaseArguments(
+ manager, dependencies, methodDescriptor, code,
+ ent2.getDirectBase(), index);
+ }
+ for (std::vector< unoidl::ExceptionTypeEntity::Member >::const_iterator i(
+ ent2.getDirectMembers().begin());
+ i != ent2.getDirectMembers().end(); ++i)
+ {
+ if (!baseException || i != ent2.getDirectMembers().begin()) {
+ methodDescriptor->addParameter(i->type, false, true, nullptr);
+ addLoadLocal(
+ manager, code, index, false, i->type, false, dependencies);
+ }
+ }
+}
+
+void handleExceptionType(
+ const OUString& name, rtl::Reference< unoidl::ExceptionTypeEntity > const & entity,
+ rtl::Reference< TypeManager > const & manager, JavaOptions const & options,
+ std::set<OUString> * dependencies)
+{
+ assert(entity.is());
+ assert(dependencies != nullptr);
+ OString className(codemaker::convertString(name).replace('.', '/'));
+ bool baseException = false;
+ bool baseRuntimeException = false;
+ OString superClass;
+ if (className == "com/sun/star/uno/Exception") {
+ baseException = true;
+ superClass = "java/lang/Exception";
+ } else if (className == "com/sun/star/uno/RuntimeException") {
+ baseRuntimeException = true;
+ superClass = "java/lang/RuntimeException";
+ } else {
+ if (entity->getDirectBase().isEmpty()) {
+ throw CannotDumpException(
+ "Exception type \"" + name + "\" lacks base");
+ }
+ superClass = codemaker::convertString(entity->getDirectBase()).
+ replace('.', '/');
+ dependencies->insert(entity->getDirectBase());
+ }
+ std::unique_ptr< ClassFile > cf(
+ new ClassFile(
+ static_cast< ClassFile::AccessFlags >(
+ ClassFile::ACC_PUBLIC | ClassFile::ACC_SUPER),
+ className, superClass, ""));
+ std::vector< TypeInfo > typeInfo;
+ sal_Int32 index = 0;
+ if (baseRuntimeException) {
+ addField(
+ manager, dependencies, cf.get(), &typeInfo, -1,
+ "com.sun.star.uno.XInterface", "Context", index++);
+ }
+ for (std::vector< unoidl::ExceptionTypeEntity::Member >::const_iterator i(
+ entity->getDirectMembers().begin());
+ i != entity->getDirectMembers().end(); ++i)
+ {
+ if (!baseException || i != entity->getDirectMembers().begin()) {
+ addField(
+ manager, dependencies, cf.get(), &typeInfo, -1, i->type,
+ i->name, index++);
+ }
+ }
+
+ // create default constructor
+ std::unique_ptr< ClassFile::Code > code(cf->newCode());
+ code->loadLocalReference(0);
+ code->instrInvokespecial(superClass, "<init>", "()V");
+ sal_uInt16 stack = 0;
+ if (baseRuntimeException) {
+ stack = std::max(
+ stack,
+ addFieldInit(
+ manager, className, "Context", false,
+ u"com.sun.star.uno.XInterface", dependencies, code.get()));
+ }
+ for (std::vector< unoidl::ExceptionTypeEntity::Member >::const_iterator i(
+ entity->getDirectMembers().begin());
+ i != entity->getDirectMembers().end(); ++i)
+ {
+ if (!baseException || i != entity->getDirectMembers().begin()) {
+ stack = std::max(
+ stack,
+ addFieldInit(
+ manager, className, i->name, false, i->type, dependencies,
+ code.get()));
+ }
+ }
+ code->instrReturn();
+ code->setMaxStackAndLocals(stack + 1, 1);
+ cf->addMethod(
+ ClassFile::ACC_PUBLIC, "<init>", "()V", code.get(),
+ std::vector< OString >(), "");
+
+
+ // create (Throwable Cause) constructor
+ code = cf->newCode();
+ code->loadLocalReference(0);
+ code->loadLocalReference(1);
+ code->instrInvokespecial(superClass, "<init>", "(Ljava/lang/Throwable;)V");
+ stack = 0;
+ if (baseRuntimeException) {
+ stack = std::max(
+ stack,
+ addFieldInit(
+ manager, className, "Context", false,
+ u"com.sun.star.uno.XInterface", dependencies, code.get()));
+ }
+ for (std::vector< unoidl::ExceptionTypeEntity::Member >::const_iterator i(
+ entity->getDirectMembers().begin());
+ i != entity->getDirectMembers().end(); ++i)
+ {
+ if (!baseException || i != entity->getDirectMembers().begin()) {
+ stack = std::max(
+ stack,
+ addFieldInit(
+ manager, className, i->name, false, i->type, dependencies,
+ code.get()));
+ }
+ }
+ code->instrReturn();
+ code->setMaxStackAndLocals(stack + 2, 2);
+ cf->addMethod(
+ ClassFile::ACC_PUBLIC, "<init>", "(Ljava/lang/Throwable;)V", code.get(),
+ std::vector< OString >(), "");
+
+ // create (Throwable Cause, String Message) constructor
+ code = cf->newCode();
+ code->loadLocalReference(0);
+ if (baseException || baseRuntimeException) {
+ code->loadLocalReference(2);
+ code->loadLocalReference(1);
+ code->instrInvokespecial(superClass, "<init>", "(Ljava/lang/String;Ljava/lang/Throwable;)V");
+ } else {
+ code->loadLocalReference(1);
+ code->loadLocalReference(2);
+ code->instrInvokespecial(superClass, "<init>", "(Ljava/lang/Throwable;Ljava/lang/String;)V");
+ }
+ stack = 0;
+ if (baseRuntimeException) {
+ stack = std::max(
+ stack,
+ addFieldInit(
+ manager, className, "Context", false,
+ u"com.sun.star.uno.XInterface", dependencies, code.get()));
+ }
+ for (std::vector< unoidl::ExceptionTypeEntity::Member >::const_iterator i(
+ entity->getDirectMembers().begin());
+ i != entity->getDirectMembers().end(); ++i)
+ {
+ if (!baseException || i != entity->getDirectMembers().begin()) {
+ stack = std::max(
+ stack,
+ addFieldInit(
+ manager, className, i->name, false, i->type, dependencies,
+ code.get()));
+ }
+ }
+ code->instrReturn();
+ code->setMaxStackAndLocals(stack + 3, 3);
+ cf->addMethod(
+ ClassFile::ACC_PUBLIC, "<init>", "(Ljava/lang/Throwable;Ljava/lang/String;)V", code.get(),
+ std::vector< OString >(), "");
+
+ // create (String Message) constructor
+ code = cf->newCode();
+ code->loadLocalReference(0);
+ code->loadLocalReference(1);
+ code->instrInvokespecial(superClass, "<init>", "(Ljava/lang/String;)V");
+ stack = 0;
+ if (baseRuntimeException) {
+ stack = std::max(
+ stack,
+ addFieldInit(
+ manager, className, "Context", false,
+ u"com.sun.star.uno.XInterface", dependencies, code.get()));
+ }
+ for (std::vector< unoidl::ExceptionTypeEntity::Member >::const_iterator i(
+ entity->getDirectMembers().begin());
+ i != entity->getDirectMembers().end(); ++i)
+ {
+ if (!baseException || i != entity->getDirectMembers().begin()) {
+ stack = std::max(
+ stack,
+ addFieldInit(
+ manager, className, i->name, false, i->type, dependencies,
+ code.get()));
+ }
+ }
+ code->instrReturn();
+ code->setMaxStackAndLocals(stack + 2, 2);
+ cf->addMethod(
+ ClassFile::ACC_PUBLIC, "<init>", "(Ljava/lang/String;)V", code.get(),
+ std::vector< OString >(), "");
+
+
+ // create (String Message, Object Context, T1 m1, ..., Tn mn) constructor
+ MethodDescriptor desc1(manager, dependencies, u"void", nullptr, nullptr);
+ code = cf->newCode();
+ code->loadLocalReference(0);
+ sal_uInt16 index2 = 1;
+ code->loadLocalReference(index2++);
+ desc1.addParameter(u"string", false, true, nullptr);
+ if (!(baseException || baseRuntimeException)) {
+ addExceptionBaseArguments(
+ manager, dependencies, &desc1, code.get(), entity->getDirectBase(),
+ &index2);
+ }
+ code->instrInvokespecial(superClass, "<init>", desc1.getDescriptor());
+ sal_uInt16 maxSize = index2;
+ if (baseRuntimeException) {
+ maxSize = std::max(
+ maxSize,
+ addDirectArgument(
+ manager, dependencies, &desc1, code.get(), &index2, className,
+ "Context", false, "com.sun.star.uno.XInterface"));
+ }
+ for (std::vector< unoidl::ExceptionTypeEntity::Member >::const_iterator i(
+ entity->getDirectMembers().begin());
+ i != entity->getDirectMembers().end(); ++i)
+ {
+ if (!baseException || i != entity->getDirectMembers().begin()) {
+ maxSize = std::max(
+ maxSize,
+ addDirectArgument(
+ manager, dependencies, &desc1, code.get(), &index2,
+ className, codemaker::convertString(i->name), false,
+ i->type));
+ }
+ }
+ code->instrReturn();
+ code->setMaxStackAndLocals(maxSize, index2);
+ cf->addMethod(
+ ClassFile::ACC_PUBLIC, "<init>", desc1.getDescriptor(), code.get(),
+ std::vector< OString >(), desc1.getSignature());
+
+ // create (Throwable Cause, String Message, Object Context, T1 m1, ..., Tn mn) constructor
+ MethodDescriptor desc2(manager, dependencies, u"void", nullptr, nullptr);
+ code = cf->newCode();
+ code->loadLocalReference(0);
+ sal_uInt16 index3 = 3;
+ // Note that we hack in the java.lang.Throwable parameter further down,
+ // because MethodDescriptor does not know how to handle it.
+ desc2.addParameter(u"string", false, true, nullptr);
+ if (baseException || baseRuntimeException) {
+ code->loadLocalReference(2);
+ code->loadLocalReference(1);
+ code->instrInvokespecial(superClass, "<init>", "(Ljava/lang/String;Ljava/lang/Throwable;)V");
+ } else {
+ code->loadLocalReference(1);
+ code->loadLocalReference(2);
+ addExceptionBaseArguments(
+ manager, dependencies, &desc2, code.get(), entity->getDirectBase(),
+ &index3);
+ code->instrInvokespecial(superClass, "<init>", OString::Concat("(Ljava/lang/Throwable;") + desc2.getDescriptor().subView(1));
+ }
+ sal_uInt16 maxSize2 = index3;
+ if (baseRuntimeException) {
+ maxSize2 = std::max(
+ maxSize2,
+ addDirectArgument(
+ manager, dependencies, &desc2, code.get(), &index3, className,
+ "Context", false, "com.sun.star.uno.XInterface"));
+ }
+ for (std::vector< unoidl::ExceptionTypeEntity::Member >::const_iterator i(
+ entity->getDirectMembers().begin());
+ i != entity->getDirectMembers().end(); ++i)
+ {
+ if (!baseException || i != entity->getDirectMembers().begin()) {
+ maxSize2 = std::max(
+ maxSize2,
+ addDirectArgument(
+ manager, dependencies, &desc2, code.get(), &index3,
+ className, codemaker::convertString(i->name), false,
+ i->type));
+ }
+ }
+ code->instrReturn();
+ code->setMaxStackAndLocals(maxSize2, index3);
+ cf->addMethod(
+ ClassFile::ACC_PUBLIC, "<init>", OString::Concat("(Ljava/lang/Throwable;") + desc2.getDescriptor().subView(1), code.get(),
+ std::vector< OString >(), desc2.getSignature());
+
+ addTypeInfo(className, typeInfo, dependencies, cf.get());
+ writeClassFile(options, className, *cf);
+}
+
+void createExceptionsAttribute(
+ rtl::Reference< TypeManager > const & manager,
+ std::vector< OUString > const & exceptionTypes,
+ std::set<OUString> * dependencies, std::vector< OString > * exceptions,
+ codemaker::ExceptionTree * tree)
+{
+ assert(dependencies != nullptr);
+ assert(exceptions != nullptr);
+ for (const OUString& ex : exceptionTypes)
+ {
+ dependencies->insert(ex);
+ OString type(codemaker::convertString(ex).replace('.', '/'));
+ exceptions->push_back(type);
+ if (tree != nullptr) {
+ tree->add(type.replace('/', '.'), manager);
+ }
+ }
+}
+
+void handleInterfaceType(
+ const OUString& name, rtl::Reference< unoidl::InterfaceTypeEntity > const & entity,
+ rtl::Reference< TypeManager > const & manager, JavaOptions const & options,
+ std::set<OUString> * dependencies)
+{
+ assert(entity.is());
+ assert(dependencies != nullptr);
+ OString className(codemaker::convertString(name).replace('.', '/'));
+ std::unique_ptr< ClassFile > cf(
+ new ClassFile(
+ static_cast< ClassFile::AccessFlags >(
+ ClassFile::ACC_PUBLIC | ClassFile::ACC_INTERFACE
+ | ClassFile::ACC_ABSTRACT),
+ className, "java/lang/Object", ""));
+ for (const unoidl::AnnotatedReference& ar : entity->getDirectMandatoryBases())
+ {
+ dependencies->insert(ar.name);
+ cf->addInterface(codemaker::convertString(ar.name).replace('.', '/'));
+ }
+ // As a special case, let com.sun.star.lang.XEventListener extend
+ // java.util.EventListener ("A tagging interface that all event listener
+ // interfaces must extend"):
+ if (className == "com/sun/star/lang/XEventListener") {
+ cf->addInterface("java/util/EventListener");
+ }
+ std::vector< TypeInfo > typeInfo;
+ if (className != "com/sun/star/uno/XInterface") {
+ sal_Int32 index = 0;
+ for (const unoidl::InterfaceTypeEntity::Attribute& attr : entity->getDirectAttributes())
+ {
+ SpecialType specialType;
+ PolymorphicUnoType polymorphicUnoType;
+ MethodDescriptor gdesc(
+ manager, dependencies, attr.type, &specialType,
+ &polymorphicUnoType);
+ std::vector< OString > exc;
+ createExceptionsAttribute(
+ manager, attr.getExceptions, dependencies, &exc, nullptr);
+ OString attrName(codemaker::convertString(attr.name));
+ cf->addMethod(
+ static_cast< ClassFile::AccessFlags >(
+ ClassFile::ACC_PUBLIC | ClassFile::ACC_ABSTRACT),
+ "get" + attrName, gdesc.getDescriptor(), nullptr, exc,
+ gdesc.getSignature());
+ if (!attr.readOnly) {
+ MethodDescriptor sdesc(manager, dependencies, u"void", nullptr, nullptr);
+ sdesc.addParameter(attr.type, false, true, nullptr);
+ std::vector< OString > exc2;
+ createExceptionsAttribute(
+ manager, attr.setExceptions, dependencies, &exc2, nullptr);
+ cf->addMethod(
+ static_cast< ClassFile::AccessFlags >(
+ ClassFile::ACC_PUBLIC | ClassFile::ACC_ABSTRACT),
+ "set" + attrName, sdesc.getDescriptor(), nullptr, exc2,
+ sdesc.getSignature());
+ }
+ typeInfo.emplace_back(
+ TypeInfo::KIND_ATTRIBUTE, attrName, specialType,
+ static_cast< TypeInfo::Flags >(
+ (attr.readOnly ? TypeInfo::FLAG_READONLY : 0)
+ | (attr.bound ? TypeInfo::FLAG_BOUND : 0)),
+ index, polymorphicUnoType);
+ index += (attr.readOnly ? 1 : 2);
+ }
+ for (const unoidl::InterfaceTypeEntity::Method& method : entity->getDirectMethods())
+ {
+ OString methodName(codemaker::convertString(method.name));
+ SpecialType specialReturnType;
+ PolymorphicUnoType polymorphicUnoReturnType;
+ MethodDescriptor desc(
+ manager, dependencies, method.returnType, &specialReturnType,
+ &polymorphicUnoReturnType);
+ typeInfo.emplace_back(
+ TypeInfo::KIND_METHOD, methodName, specialReturnType,
+ static_cast< TypeInfo::Flags >(0), index++,
+ polymorphicUnoReturnType);
+ sal_Int32 paramIndex = 0;
+ for (const unoidl::InterfaceTypeEntity::Method::Parameter& param : method.parameters)
+ {
+ bool in = param.direction
+ != unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_OUT;
+ bool out = param.direction
+ != unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_IN;
+ PolymorphicUnoType polymorphicUnoType;
+ SpecialType specialType = desc.addParameter(
+ param.type, out, true, &polymorphicUnoType);
+ if (out || isSpecialType(specialType)
+ || polymorphicUnoType.kind != PolymorphicUnoType::KIND_NONE)
+ {
+ typeInfo.emplace_back(
+ codemaker::convertString(param.name), specialType, in,
+ out, methodName, paramIndex, polymorphicUnoType);
+ }
+ ++paramIndex;
+ }
+ std::vector< OString > exc2;
+ createExceptionsAttribute(
+ manager, method.exceptions, dependencies, &exc2, nullptr);
+ cf->addMethod(
+ static_cast< ClassFile::AccessFlags >(
+ ClassFile::ACC_PUBLIC | ClassFile::ACC_ABSTRACT),
+ methodName, desc.getDescriptor(), nullptr, exc2, desc.getSignature());
+ }
+ }
+ addTypeInfo(className, typeInfo, dependencies, cf.get());
+ writeClassFile(options, className, *cf);
+}
+
+void handleTypedef(
+ rtl::Reference< unoidl::TypedefEntity > const & entity,
+ rtl::Reference< TypeManager > const & manager, std::set<OUString> * dependencies)
+{
+ assert(entity.is());
+ assert(manager.is());
+ assert(dependencies != nullptr);
+ OUString nucleus;
+ switch (manager->decompose(entity->getType(), false, &nucleus, nullptr, nullptr, nullptr))
+ {
+ case codemaker::UnoType::Sort::Boolean:
+ case codemaker::UnoType::Sort::Byte:
+ case codemaker::UnoType::Sort::Short:
+ case codemaker::UnoType::Sort::UnsignedShort:
+ case codemaker::UnoType::Sort::Long:
+ case codemaker::UnoType::Sort::UnsignedLong:
+ case codemaker::UnoType::Sort::Hyper:
+ case codemaker::UnoType::Sort::UnsignedHyper:
+ case codemaker::UnoType::Sort::Float:
+ case codemaker::UnoType::Sort::Double:
+ case codemaker::UnoType::Sort::Char:
+ case codemaker::UnoType::Sort::String:
+ case codemaker::UnoType::Sort::Type:
+ case codemaker::UnoType::Sort::Any:
+ break;
+ case codemaker::UnoType::Sort::Enum:
+ case codemaker::UnoType::Sort::PlainStruct:
+ case codemaker::UnoType::Sort::Interface:
+ case codemaker::UnoType::Sort::Typedef:
+ dependencies->insert(nucleus);
+ break;
+ default:
+ assert(false); // this cannot happen
+ }
+}
+
+void handleConstantGroup(
+ const OUString& name, rtl::Reference< unoidl::ConstantGroupEntity > const & entity,
+ rtl::Reference< TypeManager > const & manager, JavaOptions const & options,
+ std::set<OUString> * dependencies)
+{
+ assert(entity.is());
+ OString className(codemaker::convertString(name).replace('.', '/'));
+ std::unique_ptr< ClassFile > cf(
+ new ClassFile(
+ static_cast< ClassFile::AccessFlags >(
+ ClassFile::ACC_PUBLIC | ClassFile::ACC_INTERFACE
+ | ClassFile::ACC_ABSTRACT),
+ className, "java/lang/Object", ""));
+ for (const unoidl::ConstantGroupEntity::Member& member : entity->getMembers())
+ {
+ OUString type;
+ sal_uInt16 valueIndex = sal_uInt16(); // avoid false warnings
+ switch (member.value.type) {
+ case unoidl::ConstantValue::TYPE_BOOLEAN:
+ type = "boolean";
+ valueIndex = cf->addIntegerInfo(sal_Int32(member.value.booleanValue));
+ break;
+ case unoidl::ConstantValue::TYPE_BYTE:
+ type = "byte";
+ valueIndex = cf->addIntegerInfo(member.value.byteValue);
+ break;
+ case unoidl::ConstantValue::TYPE_SHORT:
+ type = "short";
+ valueIndex = cf->addIntegerInfo(member.value.shortValue);
+ break;
+ case unoidl::ConstantValue::TYPE_UNSIGNED_SHORT:
+ type = "unsigned short";
+ valueIndex = cf->addIntegerInfo(member.value.unsignedShortValue);
+ break;
+ case unoidl::ConstantValue::TYPE_LONG:
+ type = "long";
+ valueIndex = cf->addIntegerInfo(member.value.longValue);
+ break;
+ case unoidl::ConstantValue::TYPE_UNSIGNED_LONG:
+ type = "unsigned long";
+ valueIndex = cf->addIntegerInfo(
+ static_cast< sal_Int32 >(member.value.unsignedLongValue));
+ break;
+ case unoidl::ConstantValue::TYPE_HYPER:
+ type = "hyper";
+ valueIndex = cf->addLongInfo(member.value.hyperValue);
+ break;
+ case unoidl::ConstantValue::TYPE_UNSIGNED_HYPER:
+ type = "unsigned hyper";
+ valueIndex = cf->addLongInfo(
+ static_cast< sal_Int64 >(member.value.unsignedHyperValue));
+ break;
+ case unoidl::ConstantValue::TYPE_FLOAT:
+ type = "float";
+ valueIndex = cf->addFloatInfo(member.value.floatValue);
+ break;
+ case unoidl::ConstantValue::TYPE_DOUBLE:
+ type = "double";
+ valueIndex = cf->addDoubleInfo(member.value.doubleValue);
+ break;
+ }
+ OString desc;
+ OString sig;
+ getFieldDescriptor(manager, dependencies, type, &desc, &sig, nullptr);
+ cf->addField(
+ static_cast< ClassFile::AccessFlags >(
+ ClassFile::ACC_PUBLIC | ClassFile::ACC_STATIC
+ | ClassFile::ACC_FINAL),
+ codemaker::convertString(member.name), desc, valueIndex, sig);
+ }
+ writeClassFile(options, className, *cf);
+}
+
+void addExceptionHandlers(
+ codemaker::ExceptionTreeNode const * node,
+ ClassFile::Code::Position start, ClassFile::Code::Position end,
+ ClassFile::Code::Position handler, ClassFile::Code * code)
+{
+ assert(node != nullptr);
+ assert(code != nullptr);
+ if (node->present) {
+ code->addException(start, end, handler, node->name.replace('.', '/'));
+ } else {
+ for (std::unique_ptr<codemaker::ExceptionTreeNode> const & p : node->children)
+ {
+ addExceptionHandlers(p.get(), start, end, handler, code);
+ }
+ }
+}
+
+void addConstructor(
+ rtl::Reference< TypeManager > const & manager,
+ std::string_view realJavaBaseName, OString const & unoName,
+ OString const & className,
+ unoidl::SingleInterfaceBasedServiceEntity::Constructor const & constructor,
+ OUString const & returnType, std::set<OUString> * dependencies,
+ ClassFile * classFile)
+{
+ assert(dependencies != nullptr);
+ assert(classFile != nullptr);
+ MethodDescriptor desc(manager, dependencies, returnType, nullptr, nullptr);
+ desc.addParameter(u"com.sun.star.uno.XComponentContext", false, false, nullptr);
+ std::unique_ptr< ClassFile::Code > code(classFile->newCode());
+ code->loadLocalReference(0);
+ // stack: context
+ code->instrInvokeinterface(
+ "com/sun/star/uno/XComponentContext", "getServiceManager",
+ "()Lcom/sun/star/lang/XMultiComponentFactory;", 1);
+ // stack: factory
+ code->loadStringConstant(unoName);
+ // stack: factory serviceName
+ codemaker::ExceptionTree tree;
+ ClassFile::Code::Position tryStart;
+ ClassFile::Code::Position tryEnd;
+ std::vector< OString > exc;
+ sal_uInt16 stack;
+ sal_uInt16 localIndex = 1;
+ ClassFile::AccessFlags access = static_cast< ClassFile::AccessFlags >(
+ ClassFile::ACC_PUBLIC | ClassFile::ACC_STATIC);
+ if (constructor.defaultConstructor) {
+ code->loadLocalReference(0);
+ // stack: factory serviceName context
+ tryStart = code->getPosition();
+ code->instrInvokeinterface(
+ "com/sun/star/lang/XMultiComponentFactory",
+ "createInstanceWithContext",
+ ("(Ljava/lang/String;Lcom/sun/star/uno/XComponentContext;)"
+ "Ljava/lang/Object;"),
+ 3);
+ tryEnd = code->getPosition();
+ // stack: instance
+ stack = 3;
+ } else {
+ if (constructor.parameters.size() == 1
+ && constructor.parameters[0].rest)
+ {
+ desc.addParameter(u"any", true, true, nullptr);
+ code->loadLocalReference(localIndex++);
+ // stack: factory serviceName args
+ stack = 4;
+ access = static_cast< ClassFile::AccessFlags >(
+ access | ClassFile::ACC_VARARGS);
+ } else {
+ code->loadIntegerConstant(constructor.parameters.size());
+ // stack: factory serviceName N
+ code->instrAnewarray("java/lang/Object");
+ // stack: factory serviceName args
+ stack = 0;
+ sal_Int32 n = 0;
+ for (const unoidl::SingleInterfaceBasedServiceEntity::Constructor::Parameter& param :
+ constructor.parameters)
+ {
+ desc.addParameter(param.type, false, true, nullptr);
+ code->instrDup();
+ // stack: factory serviceName args args
+ code->loadIntegerConstant(n++);
+ // stack: factory serviceName args args i
+ stack = std::max(
+ stack,
+ addLoadLocal(
+ manager, code.get(), &localIndex, false, param.type, true,
+ dependencies));
+ // stack: factory serviceName args args i any
+ code->instrAastore();
+ // stack: factory serviceName args
+ }
+ stack += 5;
+ }
+ code->loadLocalReference(0);
+ // stack: factory serviceName args context
+ tryStart = code->getPosition();
+ code->instrInvokeinterface(
+ "com/sun/star/lang/XMultiComponentFactory",
+ "createInstanceWithArgumentsAndContext",
+ ("(Ljava/lang/String;[Ljava/lang/Object;"
+ "Lcom/sun/star/uno/XComponentContext;)Ljava/lang/Object;"),
+ 4);
+ tryEnd = code->getPosition();
+ // stack: instance
+ createExceptionsAttribute(
+ manager, constructor.exceptions, dependencies, &exc, &tree);
+ }
+ code->loadLocalReference(0);
+ // stack: instance context
+ code->instrInvokestatic(
+ className, "$castInstance",
+ ("(Ljava/lang/Object;Lcom/sun/star/uno/XComponentContext;)"
+ "Ljava/lang/Object;"));
+ // stack: instance
+ code->instrCheckcast(
+ codemaker::convertString(returnType).replace('.', '/'));
+ // stack: instance
+ code->instrAreturn();
+ if (!tree.getRoot().present) {
+ ClassFile::Code::Position pos1 = code->getPosition();
+ // stack: e
+ code->instrInvokevirtual(
+ "java/lang/Throwable", "toString", "()Ljava/lang/String;");
+ // stack: str
+ localIndex = std::max< sal_uInt16 >(localIndex, 2);
+ code->storeLocalReference(1);
+ // stack: -
+ code->instrNew("com/sun/star/uno/DeploymentException");
+ // stack: ex
+ code->instrDup();
+ // stack: ex ex
+ code->loadStringConstant(
+ "component context fails to supply service " + unoName + " of type "
+ + realJavaBaseName + ": ");
+ // stack: ex ex "..."
+ code->loadLocalReference(1);
+ // stack: ex ex "..." str
+ code->instrInvokevirtual(
+ "java/lang/String", "concat",
+ "(Ljava/lang/String;)Ljava/lang/String;");
+ // stack: ex ex "..."
+ code->loadLocalReference(0);
+ // stack: ex ex "..." context
+ code->instrInvokespecial(
+ "com/sun/star/uno/DeploymentException", "<init>",
+ "(Ljava/lang/String;Ljava/lang/Object;)V");
+ // stack: ex
+ ClassFile::Code::Position pos2 = code->getPosition();
+ code->instrAthrow();
+ addExceptionHandlers(
+ &tree.getRoot(), tryStart, tryEnd, pos2, code.get());
+ code->addException(
+ tryStart, tryEnd, pos1, "com/sun/star/uno/Exception");
+ dependencies->insert("com.sun.star.uno.Exception");
+ stack = std::max< sal_uInt16 >(stack, 4);
+ }
+ code->setMaxStackAndLocals(stack, localIndex);
+ classFile->addMethod(
+ access,
+ codemaker::java::translateUnoToJavaIdentifier(
+ (constructor.defaultConstructor
+ ? OString("create") : codemaker::convertString(constructor.name)),
+ "method"),
+ desc.getDescriptor(), code.get(), exc, desc.getSignature());
+}
+
+void handleService(
+ const OUString& name,
+ rtl::Reference< unoidl::SingleInterfaceBasedServiceEntity > const & entity,
+ rtl::Reference< TypeManager > const & manager, JavaOptions const & options,
+ std::set<OUString> * dependencies)
+{
+ assert(entity.is());
+ assert(dependencies != nullptr);
+ OString unoName(codemaker::convertString(name));
+ OString className(
+ translateUnoidlEntityNameToJavaFullyQualifiedName(name, "service"));
+ std::unique_ptr< ClassFile > cf(
+ new ClassFile(
+ static_cast< ClassFile::AccessFlags >(
+ ClassFile::ACC_PUBLIC | ClassFile::ACC_FINAL
+ | ClassFile::ACC_SUPER),
+ className, "java/lang/Object", ""));
+ if (!entity->getConstructors().empty()) {
+ OString realJavaBaseName(
+ codemaker::convertString(entity->getBase()));
+ dependencies->insert(entity->getBase());
+ dependencies->insert("com.sun.star.lang.XMultiComponentFactory");
+ dependencies->insert("com.sun.star.uno.DeploymentException");
+ dependencies->insert("com.sun.star.uno.TypeClass");
+ dependencies->insert("com.sun.star.uno.XComponentContext");
+ for (const unoidl::SingleInterfaceBasedServiceEntity::Constructor& cons :
+ entity->getConstructors())
+ {
+ addConstructor(
+ manager, realJavaBaseName, unoName, className, cons,
+ entity->getBase(), dependencies, cf.get());
+ }
+ // Synthetic castInstance method:
+ {
+ std::unique_ptr< ClassFile::Code > code(cf->newCode());
+ code->instrNew("com/sun/star/uno/Type");
+ // stack: type
+ code->instrDup();
+ // stack: type type
+ code->loadStringConstant(realJavaBaseName);
+ // stack: type type "..."
+ code->instrGetstatic(
+ "com/sun/star/uno/TypeClass", "INTERFACE",
+ "Lcom/sun/star/uno/TypeClass;");
+ // stack: type type "..." INTERFACE
+ code->instrInvokespecial(
+ "com/sun/star/uno/Type", "<init>",
+ "(Ljava/lang/String;Lcom/sun/star/uno/TypeClass;)V");
+ // stack: type
+ code->loadLocalReference(0);
+ // stack: type instance
+ code->instrInvokestatic(
+ "com/sun/star/uno/UnoRuntime", "queryInterface",
+ ("(Lcom/sun/star/uno/Type;Ljava/lang/Object;)"
+ "Ljava/lang/Object;"));
+ // stack: instance
+ code->instrDup();
+ // stack: instance instance
+ ClassFile::Code::Branch branch = code->instrIfnull();
+ // stack: instance
+ code->instrAreturn();
+ code->branchHere(branch);
+ code->instrPop();
+ // stack: -
+ code->instrNew("com/sun/star/uno/DeploymentException");
+ // stack: ex
+ code->instrDup();
+ // stack: ex ex
+ code->loadStringConstant(
+ "component context fails to supply service " + unoName
+ + " of type " + realJavaBaseName);
+ // stack: ex ex "..."
+ code->loadLocalReference(1);
+ // stack: ex ex "..." context
+ code->instrInvokespecial(
+ "com/sun/star/uno/DeploymentException", "<init>",
+ "(Ljava/lang/String;Ljava/lang/Object;)V");
+ // stack: ex
+ code->instrAthrow();
+ code->setMaxStackAndLocals(4, 2);
+ cf->addMethod(
+ static_cast< ClassFile::AccessFlags >(
+ ClassFile::ACC_PRIVATE | ClassFile::ACC_STATIC
+ | ClassFile::ACC_SYNTHETIC),
+ "$castInstance",
+ ("(Ljava/lang/Object;Lcom/sun/star/uno/XComponentContext;)"
+ "Ljava/lang/Object;"),
+ code.get(), std::vector< OString >(), "");
+ }
+ }
+ writeClassFile(options, className, *cf);
+}
+
+void handleSingleton(
+ const OUString& name,
+ rtl::Reference< unoidl::InterfaceBasedSingletonEntity > const & entity,
+ rtl::Reference< TypeManager > const & manager, JavaOptions const & options,
+ std::set<OUString> * dependencies)
+{
+ assert(entity.is());
+ assert(dependencies != nullptr);
+ OString realJavaBaseName(codemaker::convertString(entity->getBase()));
+ OString base(realJavaBaseName.replace('.', '/'));
+ dependencies->insert(entity->getBase());
+ OString unoName(codemaker::convertString(name));
+ OString className(
+ translateUnoidlEntityNameToJavaFullyQualifiedName(name, "singleton"));
+ dependencies->insert("com.sun.star.uno.DeploymentException");
+ dependencies->insert("com.sun.star.uno.TypeClass");
+ dependencies->insert("com.sun.star.uno.XComponentContext");
+ std::unique_ptr< ClassFile > cf(
+ new ClassFile(
+ static_cast< ClassFile::AccessFlags >(
+ ClassFile::ACC_PUBLIC | ClassFile::ACC_FINAL
+ | ClassFile::ACC_SUPER),
+ className, "java/lang/Object", ""));
+ MethodDescriptor desc(manager, dependencies, entity->getBase(), nullptr, nullptr);
+ desc.addParameter(u"com.sun.star.uno.XComponentContext", false, false, nullptr);
+ std::unique_ptr< ClassFile::Code > code(cf->newCode());
+ code->loadLocalReference(0);
+ // stack: context
+ code->loadStringConstant("/singletons/" + unoName);
+ // stack: context "..."
+ code->instrInvokeinterface(
+ "com/sun/star/uno/XComponentContext", "getValueByName",
+ "(Ljava/lang/String;)Ljava/lang/Object;", 2);
+ // stack: value
+ code->instrDup();
+ // stack: value value
+ code->instrInstanceof("com/sun/star/uno/Any");
+ // stack: value 0/1
+ ClassFile::Code::Branch branch1 = code->instrIfeq();
+ // stack: value
+ code->instrCheckcast("com/sun/star/uno/Any");
+ // stack: value
+ code->instrDup();
+ // stack: value value
+ code->instrInvokevirtual(
+ "com/sun/star/uno/Any", "getType", "()Lcom/sun/star/uno/Type;");
+ // stack: value type
+ code->instrInvokevirtual(
+ "com/sun/star/uno/Type", "getTypeClass",
+ "()Lcom/sun/star/uno/TypeClass;");
+ // stack: value typeClass
+ code->instrGetstatic(
+ "com/sun/star/uno/TypeClass", "INTERFACE",
+ "Lcom/sun/star/uno/TypeClass;");
+ // stack: value typeClass INTERFACE
+ ClassFile::Code::Branch branch2 = code->instrIfAcmpne();
+ // stack: value
+ code->instrInvokevirtual(
+ "com/sun/star/uno/Any", "getObject", "()Ljava/lang/Object;");
+ // stack: value
+ code->branchHere(branch1);
+ code->instrNew("com/sun/star/uno/Type");
+ // stack: value type
+ code->instrDup();
+ // stack: value type type
+ code->loadStringConstant(realJavaBaseName);
+ // stack: value type type "..."
+ code->instrGetstatic(
+ "com/sun/star/uno/TypeClass", "INTERFACE",
+ "Lcom/sun/star/uno/TypeClass;");
+ // stack: value type type "..." INTERFACE
+ code->instrInvokespecial(
+ "com/sun/star/uno/Type", "<init>",
+ "(Ljava/lang/String;Lcom/sun/star/uno/TypeClass;)V");
+ // stack: value type
+ code->instrSwap();
+ // stack: type value
+ code->instrInvokestatic(
+ "com/sun/star/uno/UnoRuntime", "queryInterface",
+ "(Lcom/sun/star/uno/Type;Ljava/lang/Object;)Ljava/lang/Object;");
+ // stack: instance
+ code->instrDup();
+ // stack: instance instance
+ ClassFile::Code::Branch branch3 = code->instrIfnull();
+ // stack: instance
+ code->instrCheckcast(base);
+ // stack: instance
+ code->instrAreturn();
+ code->branchHere(branch2);
+ code->branchHere(branch3);
+ code->instrPop();
+ // stack: -
+ code->instrNew("com/sun/star/uno/DeploymentException");
+ // stack: ex
+ code->instrDup();
+ // stack: ex ex
+ code->loadStringConstant(
+ "component context fails to supply singleton " + unoName + " of type "
+ + realJavaBaseName);
+ // stack: ex ex "..."
+ code->loadLocalReference(0);
+ // stack: ex ex "..." context
+ code->instrInvokespecial(
+ "com/sun/star/uno/DeploymentException", "<init>",
+ "(Ljava/lang/String;Ljava/lang/Object;)V");
+ // stack: ex
+ code->instrAthrow();
+ code->setMaxStackAndLocals(5, 1);
+ cf->addMethod(
+ static_cast< ClassFile::AccessFlags >(
+ ClassFile::ACC_PUBLIC | ClassFile::ACC_STATIC),
+ "get", desc.getDescriptor(), code.get(), std::vector< OString >(),
+ desc.getSignature());
+ writeClassFile(options, className, *cf);
+}
+
+}
+
+void produce(
+ OUString const & name, rtl::Reference< TypeManager > const & manager,
+ codemaker::GeneratedTypeSet & generated, JavaOptions const & options)
+{
+ if (generated.contains(u2b(name))) {
+ return;
+ }
+ generated.add(u2b(name));
+ if (!manager->foundAtPrimaryProvider(name)) {
+ return;
+ }
+ std::set<OUString> deps;
+ rtl::Reference< unoidl::Entity > ent;
+ rtl::Reference< unoidl::MapCursor > cur;
+ switch (manager->getSort(name, &ent, &cur)) {
+ case codemaker::UnoType::Sort::Module:
+ {
+ OUString prefix;
+ if (!name.isEmpty()) {
+ prefix = name + ".";
+ }
+ for (;;) {
+ OUString mem;
+ if (!cur->getNext(&mem).is()) {
+ break;
+ }
+ produce(prefix + mem, manager, generated, options);
+ }
+ return;
+ }
+ case codemaker::UnoType::Sort::Enum:
+ handleEnumType(
+ name, dynamic_cast< unoidl::EnumTypeEntity * >(ent.get()), options);
+ break;
+ case codemaker::UnoType::Sort::PlainStruct:
+ handlePlainStructType(
+ name, dynamic_cast< unoidl::PlainStructTypeEntity * >(ent.get()),
+ manager, options, &deps);
+ break;
+ case codemaker::UnoType::Sort::PolymorphicStructTemplate:
+ handlePolyStructType(
+ name,
+ dynamic_cast< unoidl::PolymorphicStructTypeTemplateEntity * >(
+ ent.get()),
+ manager, options, &deps);
+ break;
+ case codemaker::UnoType::Sort::Exception:
+ handleExceptionType(
+ name, dynamic_cast< unoidl::ExceptionTypeEntity * >(ent.get()),
+ manager, options, &deps);
+ break;
+ case codemaker::UnoType::Sort::Interface:
+ handleInterfaceType(
+ name, dynamic_cast< unoidl::InterfaceTypeEntity * >(ent.get()),
+ manager, options, &deps);
+ break;
+ case codemaker::UnoType::Sort::Typedef:
+ handleTypedef(
+ dynamic_cast< unoidl::TypedefEntity * >(ent.get()), manager, &deps);
+ break;
+ case codemaker::UnoType::Sort::ConstantGroup:
+ handleConstantGroup(
+ name, dynamic_cast< unoidl::ConstantGroupEntity * >(ent.get()),
+ manager, options, &deps);
+ break;
+ case codemaker::UnoType::Sort::SingleInterfaceBasedService:
+ handleService(
+ name,
+ dynamic_cast< unoidl::SingleInterfaceBasedServiceEntity * >(
+ ent.get()),
+ manager, options, &deps);
+ break;
+ case codemaker::UnoType::Sort::InterfaceBasedSingleton:
+ handleSingleton(
+ name,
+ dynamic_cast< unoidl::InterfaceBasedSingletonEntity * >(ent.get()),
+ manager, options, &deps);
+ break;
+ case codemaker::UnoType::Sort::AccumulationBasedService:
+ case codemaker::UnoType::Sort::ServiceBasedSingleton:
+ break;
+ default:
+ throw CannotDumpException(
+ "unexpected entity \"" + name + "\" in call to produce");
+ }
+ if (!options.isValid("-nD")) {
+ for (const OUString& d : deps) {
+ produce(d, manager, generated, options);
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/codemaker/source/javamaker/javatype.hxx b/codemaker/source/javamaker/javatype.hxx
new file mode 100644
index 000000000..9df1d94b5
--- /dev/null
+++ b/codemaker/source/javamaker/javatype.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 .
+ */
+
+#pragma once
+
+#include <sal/config.h>
+
+#include <rtl/ref.hxx>
+
+namespace codemaker { class GeneratedTypeSet; }
+namespace rtl { class OUString; }
+class JavaOptions;
+class TypeManager;
+
+void produce(
+ OUString const & name, rtl::Reference< TypeManager > const & manager,
+ codemaker::GeneratedTypeSet & generated, JavaOptions const & options);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */