Extract embindmaker from cppumaker into its own tool
...that directly generates one large .cxx Change-Id: I046539b83f8fde5eda7168c93a8b819137399665 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/162343 Tested-by: Jenkins Reviewed-by: Stephan Bergmann <stephan.bergmann@allotropia.de>
This commit is contained in:
parent
f504b2de4a
commit
b2ade3e63e
@ -33,6 +33,7 @@ $(eval $(call gb_Helper_register_executables,NONE, \
|
|||||||
concat-deps \
|
concat-deps \
|
||||||
cpp \
|
cpp \
|
||||||
cppunittester \
|
cppunittester \
|
||||||
|
$(if $(or $(filter EMSCRIPTEN,$(BUILD_TYPE_FOR_HOST)),$(filter EMSCRIPTEN,$(OS))),embindmaker) \
|
||||||
gbuildtojson \
|
gbuildtojson \
|
||||||
$(if $(filter MSC,$(COM)), \
|
$(if $(filter MSC,$(COM)), \
|
||||||
gcc-wrapper \
|
gcc-wrapper \
|
||||||
|
@ -45,6 +45,7 @@ $(eval $(call gb_Module_add_moduledirs,cross_toolset,\
|
|||||||
shell \
|
shell \
|
||||||
solenv \
|
solenv \
|
||||||
soltools \
|
soltools \
|
||||||
|
$(if $(filter EMSCRIPTEN,$(BUILD_TYPE_FOR_HOST)),static) \
|
||||||
stoc \
|
stoc \
|
||||||
store \
|
store \
|
||||||
tools \
|
tools \
|
||||||
|
@ -216,24 +216,6 @@ bool CppuOptions::initOptions(int ac, char* av[], bool bCmdFile)
|
|||||||
|
|
||||||
m_options["-G"_ostr] = OString();
|
m_options["-G"_ostr] = OString();
|
||||||
break;
|
break;
|
||||||
case 'W': // generate embind javascript bindings for LOWA
|
|
||||||
if (av[i][2] != '\0')
|
|
||||||
{
|
|
||||||
OString tmp("'-W', please check"_ostr);
|
|
||||||
if (i <= ac - 1)
|
|
||||||
{
|
|
||||||
tmp += OString::Concat(" your input '") + av[i] + "'";
|
|
||||||
}
|
|
||||||
|
|
||||||
throw IllegalArgument(tmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isValid("-C"_ostr) && !isValid("-CS"_ostr) && !isValid("-L"_ostr))
|
|
||||||
{
|
|
||||||
throw IllegalArgument("'-W' requires '-C' or '-CS' or '-L' option"_ostr);
|
|
||||||
}
|
|
||||||
m_options["-W"_ostr] = OString();
|
|
||||||
break;
|
|
||||||
case 'X': // support for eXtra type rdbs
|
case 'X': // support for eXtra type rdbs
|
||||||
{
|
{
|
||||||
if (av[i][2] == '\0')
|
if (av[i][2] == '\0')
|
||||||
|
@ -159,7 +159,6 @@ OString getFileExtension(FileType eFileType)
|
|||||||
default:
|
default:
|
||||||
case FileType::HDL: return ".hdl"_ostr;
|
case FileType::HDL: return ".hdl"_ostr;
|
||||||
case FileType::HPP: return ".hpp"_ostr;
|
case FileType::HPP: return ".hpp"_ostr;
|
||||||
case FileType::EMBIND_CXX: return "_embind.cxx"_ostr;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -189,8 +188,6 @@ public:
|
|||||||
|
|
||||||
virtual void dumpHppFile(FileStream& o, codemaker::cppumaker::Includes & includes) = 0;
|
virtual void dumpHppFile(FileStream& o, codemaker::cppumaker::Includes & includes) = 0;
|
||||||
|
|
||||||
void dumpEmbindCppFile(FileStream& o);
|
|
||||||
|
|
||||||
OUString dumpHeaderDefine(FileStream& o, std::u16string_view extension) const;
|
OUString dumpHeaderDefine(FileStream& o, std::u16string_view extension) const;
|
||||||
|
|
||||||
void dumpGetCppuType(FileStream & out);
|
void dumpGetCppuType(FileStream & out);
|
||||||
@ -241,8 +238,6 @@ protected:
|
|||||||
assert(false); // this cannot happen
|
assert(false); // this cannot happen
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void dumpEmbindDeclaration(FileStream &) {};
|
|
||||||
|
|
||||||
virtual void dumpFiles(OUString const & uri, CppuOptions const & options);
|
virtual void dumpFiles(OUString const & uri, CppuOptions const & options);
|
||||||
|
|
||||||
virtual void addLightGetCppuTypeIncludes(
|
virtual void addLightGetCppuTypeIncludes(
|
||||||
@ -324,8 +319,6 @@ void CppuType::dumpFiles(OUString const & uri, CppuOptions const & options)
|
|||||||
{
|
{
|
||||||
dumpFile(uri, name_, FileType::HDL, options);
|
dumpFile(uri, name_, FileType::HDL, options);
|
||||||
dumpFile(uri, name_, FileType::HPP, options);
|
dumpFile(uri, name_, FileType::HPP, options);
|
||||||
if(options.isValid("-W"_ostr))
|
|
||||||
dumpFile(uri, name_, FileType::EMBIND_CXX, options);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CppuType::addLightGetCppuTypeIncludes(
|
void CppuType::addLightGetCppuTypeIncludes(
|
||||||
@ -460,9 +453,6 @@ void CppuType::dumpFile(
|
|||||||
case FileType::HDL:
|
case FileType::HDL:
|
||||||
dumpHdlFile(out, includes);
|
dumpHdlFile(out, includes);
|
||||||
break;
|
break;
|
||||||
case FileType::EMBIND_CXX:
|
|
||||||
dumpEmbindCppFile(out);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
out.close();
|
out.close();
|
||||||
@ -608,13 +598,6 @@ void CppuType::dumpHFileContent(
|
|||||||
out << " *);\n\n#endif\n";
|
out << " *);\n\n#endif\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
void CppuType::dumpEmbindCppFile(FileStream &out)
|
|
||||||
{
|
|
||||||
out << "#include <emscripten/bind.h>\n"
|
|
||||||
"#include <" << name_.replace('.', '/') << ".hpp>\n";
|
|
||||||
dumpEmbindDeclaration(out);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CppuType::dumpGetCppuType(FileStream & out)
|
void CppuType::dumpGetCppuType(FileStream & out)
|
||||||
{
|
{
|
||||||
if (name_ == "com.sun.star.uno.XInterface") {
|
if (name_ == "com.sun.star.uno.XInterface") {
|
||||||
@ -1136,14 +1119,10 @@ public:
|
|||||||
OUString const & name, rtl::Reference< TypeManager > const & typeMgr);
|
OUString const & name, rtl::Reference< TypeManager > const & typeMgr);
|
||||||
|
|
||||||
virtual void dumpDeclaration(FileStream& o) override;
|
virtual void dumpDeclaration(FileStream& o) override;
|
||||||
virtual void dumpEmbindDeclaration(FileStream& o) override;
|
|
||||||
void dumpHppFile(FileStream& o, codemaker::cppumaker::Includes & includes) override;
|
void dumpHppFile(FileStream& o, codemaker::cppumaker::Includes & includes) override;
|
||||||
|
|
||||||
void dumpAttributes(FileStream& o) const;
|
void dumpAttributes(FileStream& o) const;
|
||||||
void dumpEmbindAttributeBindings(FileStream& o) const;
|
|
||||||
void dumpMethods(FileStream& o) const;
|
void dumpMethods(FileStream& o) const;
|
||||||
void dumpEmbindMethodBindings(FileStream& o, bool bDumpForReference=false) const;
|
|
||||||
void dumpEmbindWrapperFunc(FileStream& o, const unoidl::InterfaceTypeEntity::Method& method, bool bDumpForReference=false) const;
|
|
||||||
void dumpNormalGetCppuType(FileStream& o) override;
|
void dumpNormalGetCppuType(FileStream& o) override;
|
||||||
void dumpComprehensiveGetCppuType(FileStream& o) override;
|
void dumpComprehensiveGetCppuType(FileStream& o) override;
|
||||||
void dumpCppuAttributeRefs(FileStream& o, sal_uInt32& index);
|
void dumpCppuAttributeRefs(FileStream& o, sal_uInt32& index);
|
||||||
@ -1214,53 +1193,6 @@ void InterfaceType::dumpDeclaration(FileStream & out)
|
|||||||
out << "};\n\n";
|
out << "};\n\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
void InterfaceType::dumpEmbindDeclaration(FileStream & out)
|
|
||||||
{
|
|
||||||
// TODO: This is a temporary workaround that likely causes the Embind UNO
|
|
||||||
// bindings to leak memory. Reference counting and cloning mechanisms of
|
|
||||||
// Embind should be investigated to figure out what exactly we need here.
|
|
||||||
out << "namespace emscripten { namespace internal { \n"
|
|
||||||
"template<> void raw_destructor<" << codemaker::cpp::scopedCppName(u2b(name_))
|
|
||||||
<< ">(" << codemaker::cpp::scopedCppName(u2b(name_)) << "*){}\n"
|
|
||||||
"}}\n";
|
|
||||||
|
|
||||||
out << "EMSCRIPTEN_BINDINGS(uno_bindings_";
|
|
||||||
codemaker::cppumaker::dumpTypeFullWithDecorator(out, name_, u"_");
|
|
||||||
codemaker::cppumaker::dumpTypeIdentifier(out, name_);
|
|
||||||
out << ") {\n";
|
|
||||||
|
|
||||||
out << "\n::emscripten::class_<" << codemaker::cpp::scopedCppName(u2b(name_)) << ">(\"";
|
|
||||||
codemaker::cppumaker::dumpTypeFullWithDecorator(out, name_, u"$");
|
|
||||||
codemaker::cppumaker::dumpTypeIdentifier(out, name_);
|
|
||||||
out << "\")\n";
|
|
||||||
|
|
||||||
inc();
|
|
||||||
// dump bindings for attributes and methods.
|
|
||||||
dumpEmbindAttributeBindings(out);
|
|
||||||
dumpEmbindMethodBindings(out);
|
|
||||||
out << indent() << ";\n";
|
|
||||||
dec();
|
|
||||||
|
|
||||||
// dump reference bindings.
|
|
||||||
out << "\n::emscripten::class_<::css::uno::Reference<" << codemaker::cpp::scopedCppName(u2b(name_)) << ">, ::emscripten::base<::css::uno::BaseReference>>(\"";
|
|
||||||
codemaker::cppumaker::dumpTypeFullWithDecorator(out, name_, u"$");
|
|
||||||
codemaker::cppumaker::dumpTypeIdentifier(out, name_);
|
|
||||||
out << "Ref\")\n";
|
|
||||||
inc();
|
|
||||||
out << indent() << ".constructor<>()\n"
|
|
||||||
<< indent() << ".constructor<::css::uno::BaseReference, ::css::uno::UnoReference_Query>()\n"
|
|
||||||
<< indent() << ".function(\"is\", &::css::uno::Reference<" << codemaker::cpp::scopedCppName(u2b(name_)) << ">::is)\n"
|
|
||||||
<< indent() << ".function(\"get\", &::css::uno::Reference<" << codemaker::cpp::scopedCppName(u2b(name_)) << ">::get, ::emscripten::allow_raw_pointers())\n"
|
|
||||||
<< indent() << ".function(\"set\", ::emscripten::select_overload<bool(const ::css::uno::Any&, com::sun::star::uno::UnoReference_Query)>(&::css::uno::Reference<" << codemaker::cpp::scopedCppName(u2b(name_)) << ">::set))\n";
|
|
||||||
dumpEmbindAttributeBindings(out);
|
|
||||||
dumpEmbindMethodBindings(out, true);
|
|
||||||
out << indent() << ";\n";
|
|
||||||
dec();
|
|
||||||
|
|
||||||
out << "}\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void InterfaceType::dumpHppFile(
|
void InterfaceType::dumpHppFile(
|
||||||
FileStream & out, codemaker::cppumaker::Includes & includes)
|
FileStream & out, codemaker::cppumaker::Includes & includes)
|
||||||
{
|
{
|
||||||
@ -1312,31 +1244,6 @@ void InterfaceType::dumpAttributes(FileStream & out) const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void InterfaceType::dumpEmbindAttributeBindings(FileStream& out) const
|
|
||||||
{
|
|
||||||
if (!entity_->getDirectAttributes().empty())
|
|
||||||
{
|
|
||||||
out << indent() << "// Bindings for attributes\n";
|
|
||||||
}
|
|
||||||
for (const unoidl::InterfaceTypeEntity::Attribute& attr : entity_->getDirectAttributes())
|
|
||||||
{
|
|
||||||
if (m_isDeprecated || isDeprecated(attr.annotations))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
out << indent();
|
|
||||||
out << ".function(\"";
|
|
||||||
out << "get" << attr.name << "\", &" << codemaker::cpp::scopedCppName(u2b(name_)) << "::get"
|
|
||||||
<< attr.name << ")\n";
|
|
||||||
if (!attr.readOnly)
|
|
||||||
{
|
|
||||||
out << indent();
|
|
||||||
out << ".function(\"";
|
|
||||||
out << "set" << attr.name << "\", &" << codemaker::cpp::scopedCppName(u2b(name_))
|
|
||||||
<< "::set" << attr.name << ")\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void InterfaceType::dumpMethods(FileStream & out) const
|
void InterfaceType::dumpMethods(FileStream & out) const
|
||||||
{
|
{
|
||||||
if (!entity_->getDirectMethods().empty()) {
|
if (!entity_->getDirectMethods().empty()) {
|
||||||
@ -1377,115 +1284,6 @@ void InterfaceType::dumpMethods(FileStream & out) const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void InterfaceType::dumpEmbindWrapperFunc(FileStream& out,
|
|
||||||
const unoidl::InterfaceTypeEntity::Method& method,
|
|
||||||
bool bDumpForReference) const
|
|
||||||
{
|
|
||||||
out << indent();
|
|
||||||
out << ".function(\"" << method.name << "\", ";
|
|
||||||
out << indent() << "+[](";
|
|
||||||
if (bDumpForReference)
|
|
||||||
out << "::css::uno::Reference<";
|
|
||||||
out << codemaker::cpp::scopedCppName(u2b(name_));
|
|
||||||
if (bDumpForReference)
|
|
||||||
out << ">";
|
|
||||||
out << "* self";
|
|
||||||
if(!method.parameters.empty())
|
|
||||||
out << ",";
|
|
||||||
|
|
||||||
auto dumpParameters = [&](bool bDumpType)
|
|
||||||
{
|
|
||||||
// dumpParams with references as pointers
|
|
||||||
if (!method.parameters.empty())
|
|
||||||
{
|
|
||||||
out << " ";
|
|
||||||
for (std::vector<unoidl::InterfaceTypeEntity::Method::Parameter>::const_iterator
|
|
||||||
parameter(method.parameters.begin());
|
|
||||||
parameter != method.parameters.end();)
|
|
||||||
{
|
|
||||||
bool isConst;
|
|
||||||
bool isRef;
|
|
||||||
if (parameter->direction
|
|
||||||
== unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_IN)
|
|
||||||
{
|
|
||||||
isConst = passByReference(parameter->type);
|
|
||||||
isRef = isConst;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
isConst = false;
|
|
||||||
isRef = true;
|
|
||||||
}
|
|
||||||
// for the embind wrapper, we define a pointer instead of a reference.
|
|
||||||
if (bDumpType)
|
|
||||||
dumpType(out, parameter->type, isConst, /*isRef=*/false);
|
|
||||||
if (isRef)
|
|
||||||
out << "*";
|
|
||||||
|
|
||||||
out << " " << parameter->name;
|
|
||||||
++parameter;
|
|
||||||
if (parameter != method.parameters.end())
|
|
||||||
{
|
|
||||||
out << ", ";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
out << " ";
|
|
||||||
}
|
|
||||||
};
|
|
||||||
dumpParameters(/*bDumpType=*/true);
|
|
||||||
|
|
||||||
if (bDumpForReference)
|
|
||||||
{
|
|
||||||
out << ") { return self->get()->" << method.name << "(";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
out << ") { return self->" << method.name << "(";
|
|
||||||
}
|
|
||||||
|
|
||||||
dumpParameters(/*bDumpType=*/false);
|
|
||||||
out << "); }, ::emscripten::allow_raw_pointers() )\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
void InterfaceType::dumpEmbindMethodBindings(FileStream & out, bool bDumpForReference) const
|
|
||||||
{
|
|
||||||
if (!entity_->getDirectMethods().empty()) {
|
|
||||||
out << indent() << "// Bindings for methods\n";
|
|
||||||
}
|
|
||||||
for (const unoidl::InterfaceTypeEntity::Method& method : entity_->getDirectMethods()) {
|
|
||||||
if( m_isDeprecated || isDeprecated(method.annotations) )
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// if dumping the method binding for a reference implementation
|
|
||||||
// dump wrapper.
|
|
||||||
if(bDumpForReference)
|
|
||||||
{
|
|
||||||
dumpEmbindWrapperFunc(out, method, true);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool bHasOutParams = std::any_of(
|
|
||||||
method.parameters.begin(), method.parameters.end(),
|
|
||||||
[](const auto& parameter) {
|
|
||||||
return parameter.direction
|
|
||||||
!= unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_IN;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (bHasOutParams)
|
|
||||||
{
|
|
||||||
dumpEmbindWrapperFunc(out, method, false);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
out << indent();
|
|
||||||
out << ".function(\"" << method.name << "\", &"
|
|
||||||
<< codemaker::cpp::scopedCppName(u2b(name_))
|
|
||||||
<< "::" << method.name << ")\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void InterfaceType::dumpNormalGetCppuType(FileStream & out)
|
void InterfaceType::dumpNormalGetCppuType(FileStream & out)
|
||||||
{
|
{
|
||||||
dumpGetCppuTypePreamble(out);
|
dumpGetCppuTypePreamble(out);
|
||||||
@ -3748,8 +3546,6 @@ private:
|
|||||||
|
|
||||||
virtual void dumpFiles(OUString const & uri, CppuOptions const & options) override {
|
virtual void dumpFiles(OUString const & uri, CppuOptions const & options) override {
|
||||||
dumpFile(uri, name_, FileType::HPP, options);
|
dumpFile(uri, name_, FileType::HPP, options);
|
||||||
if(options.isValid("-W"_ostr))
|
|
||||||
dumpFile(uri, name_, FileType::EMBIND_CXX, options);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -32,8 +32,7 @@ namespace codemaker::cppumaker {
|
|||||||
enum class FileType
|
enum class FileType
|
||||||
{
|
{
|
||||||
HDL,
|
HDL,
|
||||||
HPP,
|
HPP
|
||||||
EMBIND_CXX
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,20 +74,6 @@ void dumpTypeIdentifier(FileStream & out, std::u16string_view entityName) {
|
|||||||
out << entityName.substr(entityName.rfind('.') + 1);
|
out << entityName.substr(entityName.rfind('.') + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool dumpTypeFullWithDecorator(FileStream& out, std::u16string_view entityName, std::u16string_view decorator)
|
|
||||||
{
|
|
||||||
bool bOutput = false;
|
|
||||||
for (sal_Int32 i = 0; i >= 0;)
|
|
||||||
{
|
|
||||||
std::u16string_view id(o3tl::getToken(entityName, 0, '.', i));
|
|
||||||
if (i >= 0)
|
|
||||||
{
|
|
||||||
out << id << decorator;
|
|
||||||
bOutput = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return bOutput;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||||
|
@ -35,9 +35,6 @@ bool dumpNamespaceOpen(FileStream& out, std::u16string_view entityName, bool ful
|
|||||||
bool dumpNamespaceClose(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);
|
void dumpTypeIdentifier(FileStream& out, std::u16string_view entityName);
|
||||||
|
|
||||||
bool dumpTypeFullWithDecorator(FileStream& out, std::u16string_view entityName,
|
|
||||||
std::u16string_view decorator);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||||
|
@ -1422,6 +1422,9 @@ if test "$_os" = "Emscripten"; then
|
|||||||
if test $EMSCRIPTEN_ERROR -ne 0; then
|
if test $EMSCRIPTEN_ERROR -ne 0; then
|
||||||
AC_MSG_ERROR(["Please fix your EMSDK setup to build with Emscripten!"])
|
AC_MSG_ERROR(["Please fix your EMSDK setup to build with Emscripten!"])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
dnl Some build-side things are conditional on "EMSCRIPTEN in BUILD_TYPE_FOR_HOST":
|
||||||
|
BUILD_TYPE="$BUILD_TYPE EMSCRIPTEN"
|
||||||
fi
|
fi
|
||||||
AC_SUBST(EMSDK_FILE_PACKAGER)
|
AC_SUBST(EMSDK_FILE_PACKAGER)
|
||||||
|
|
||||||
|
@ -43,8 +43,13 @@ class TypeManager final : public salhelper::SimpleReferenceObject {
|
|||||||
public:
|
public:
|
||||||
TypeManager();
|
TypeManager();
|
||||||
|
|
||||||
|
rtl::Reference<unoidl::Manager> const & getManager() const { return manager_; }
|
||||||
|
|
||||||
void loadProvider(OUString const & uri, bool primary);
|
void loadProvider(OUString const & uri, bool primary);
|
||||||
|
|
||||||
|
std::vector<rtl::Reference<unoidl::Provider>> const & getPrimaryProviders() const
|
||||||
|
{ return primaryProviders_; }
|
||||||
|
|
||||||
bool foundAtPrimaryProvider(OUString const & name) const;
|
bool foundAtPrimaryProvider(OUString const & name) const;
|
||||||
|
|
||||||
codemaker::UnoType::Sort getSort(
|
codemaker::UnoType::Sort getSort(
|
||||||
|
@ -36,8 +36,6 @@ define gb_UnoApi_add_idlfiles
|
|||||||
$(call gb_UnoApiTarget_add_idlfiles,$(1),$(2),$(3))
|
$(call gb_UnoApiTarget_add_idlfiles,$(1),$(2),$(3))
|
||||||
$(call gb_UnoApiHeadersTarget_add_headerfiles,$(1),$(2),$(addsuffix .hpp,$(3)))
|
$(call gb_UnoApiHeadersTarget_add_headerfiles,$(1),$(2),$(addsuffix .hpp,$(3)))
|
||||||
$(call gb_UnoApiHeadersTarget_add_headerfiles,$(1),$(2),$(addsuffix .hdl,$(3)))
|
$(call gb_UnoApiHeadersTarget_add_headerfiles,$(1),$(2),$(addsuffix .hdl,$(3)))
|
||||||
$(if $(filter EMSCRIPTEN, $(OS)),\
|
|
||||||
$(call gb_UnoApiHeadersTarget_add_embind,$(1),$(2),$(addsuffix _embind,$(3))))
|
|
||||||
|
|
||||||
endef
|
endef
|
||||||
|
|
||||||
@ -71,19 +69,4 @@ $(call gb_UnoApiTarget_set_reference_rdbfile,$(1),$(2))
|
|||||||
|
|
||||||
endef
|
endef
|
||||||
|
|
||||||
ifeq ($(OS),EMSCRIPTEN)
|
|
||||||
$(eval $(call gb_StaticLibrary_StaticLibrary,unoembind))
|
|
||||||
$(eval $(call gb_StaticLibrary_set_include,unoembind,\
|
|
||||||
$$(INCLUDE) \
|
|
||||||
))
|
|
||||||
$(eval $(call gb_StaticLibrary_use_api,unoembind,\
|
|
||||||
offapi \
|
|
||||||
udkapi \
|
|
||||||
))
|
|
||||||
$(eval $(call gb_StaticLibrary_add_exception_objects,unoembind,\
|
|
||||||
static/source/unoembindhelpers/PrimaryBindings\
|
|
||||||
))
|
|
||||||
|
|
||||||
endif
|
|
||||||
|
|
||||||
# vim: set noet sw=4 ts=4:
|
# vim: set noet sw=4 ts=4:
|
||||||
|
@ -152,7 +152,7 @@ $(call gb_UnoApiHeadersTarget_get_real_comprehensive_target,%) : \
|
|||||||
$(call gb_Output_announce,$*,$(true),HPC,3)
|
$(call gb_Output_announce,$*,$(true),HPC,3)
|
||||||
$(call gb_Trace_StartRange,$*,HPC)
|
$(call gb_Trace_StartRange,$*,HPC)
|
||||||
$(call gb_UnoApiHeadersTarget__command,$@,$*,$(call gb_UnoApiHeadersTarget_get_comprehensive_dir,$*), \
|
$(call gb_UnoApiHeadersTarget__command,$@,$*,$(call gb_UnoApiHeadersTarget_get_comprehensive_dir,$*), \
|
||||||
-C $(if $(filter EMSCRIPTEN, $(OS)), -W))
|
-C)
|
||||||
$(call gb_Trace_EndRange,$*,HPC)
|
$(call gb_Trace_EndRange,$*,HPC)
|
||||||
|
|
||||||
$(call gb_UnoApiHeadersTarget_get_real_target,%) : \
|
$(call gb_UnoApiHeadersTarget_get_real_target,%) : \
|
||||||
@ -237,19 +237,6 @@ define gb_UnoApiHeadersTarget_add_headerfiles
|
|||||||
$(foreach hdr,$(3),$(call gb_UnoApiHeadersTarget_add_headerfile,$(1),$(2)/$(hdr)))
|
$(foreach hdr,$(3),$(call gb_UnoApiHeadersTarget_add_headerfile,$(1),$(2)/$(hdr)))
|
||||||
endef
|
endef
|
||||||
|
|
||||||
# call gb_UnoApiEmbindTarget_add_embind,unoapi,directory,headerfilenames
|
|
||||||
define gb_UnoApiHeadersTarget_add_embind
|
|
||||||
$(if $(filter offapi udkapi, $(1)),\
|
|
||||||
$(foreach hdr,$(3),$(eval $(call gb_UnoApiEmbindTarget__add_embind,$(1),$(2),$(hdr)))))
|
|
||||||
endef
|
|
||||||
|
|
||||||
define gb_UnoApiEmbindTarget__add_embind
|
|
||||||
$(eval $(call gb_StaticLibrary_add_generated_exception_objects,unoembind,\
|
|
||||||
UnoApiHeadersTarget/$(1)/comprehensive/$(2)/$(3) \
|
|
||||||
))
|
|
||||||
|
|
||||||
endef
|
|
||||||
|
|
||||||
define gb_UnoApiHeadersTarget__use_api_for_target
|
define gb_UnoApiHeadersTarget__use_api_for_target
|
||||||
$(call gb_UnoApiHeadersTarget_get_$(3),$(1)) : $(call gb_UnoApiTarget_get_target,$(2))
|
$(call gb_UnoApiHeadersTarget_get_$(3),$(1)) : $(call gb_UnoApiTarget_get_target,$(2))
|
||||||
$(call gb_UnoApiHeadersTarget_get_$(3),$(1)) : UNOAPI_DEPS += -X$(call gb_UnoApiTarget_get_target,$(2))
|
$(call gb_UnoApiHeadersTarget_get_$(3),$(1)) : UNOAPI_DEPS += -X$(call gb_UnoApiTarget_get_target,$(2))
|
||||||
|
@ -16,6 +16,7 @@ gb_BUILD_TOOLS_executables = \
|
|||||||
climaker \
|
climaker \
|
||||||
cpp \
|
cpp \
|
||||||
cppumaker \
|
cppumaker \
|
||||||
|
$(if $(filter EMSCRIPTEN,$(BUILD_TYPE_FOR_HOST)),embindmaker) \
|
||||||
gencoll_rule \
|
gencoll_rule \
|
||||||
genconv_dict \
|
genconv_dict \
|
||||||
gendict \
|
gendict \
|
||||||
|
22
static/CustomTarget_unoembind.mk
Normal file
22
static/CustomTarget_unoembind.mk
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t; fill-column: 100 -*-
|
||||||
|
#
|
||||||
|
# This file is part of the LibreOffice project.
|
||||||
|
#
|
||||||
|
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
#
|
||||||
|
|
||||||
|
$(eval $(call gb_CustomTarget_CustomTarget,static/unoembind))
|
||||||
|
|
||||||
|
$(eval $(call gb_CustomTarget_register_targets,static/unoembind, \
|
||||||
|
bindings_uno.cxx \
|
||||||
|
))
|
||||||
|
|
||||||
|
$(call gb_CustomTarget_get_workdir,static/unoembind)/bindings_uno.cxx: \
|
||||||
|
$(call gb_Executable_get_target_for_build,embindmaker) $(call gb_UnoApi_get_target,udkapi) \
|
||||||
|
$(call gb_UnoApi_get_target,offapi)
|
||||||
|
$(call gb_Executable_get_command,embindmaker) uno +$(call gb_UnoApi_get_target,udkapi) \
|
||||||
|
+$(call gb_UnoApi_get_target,offapi) > $@
|
||||||
|
|
||||||
|
# vim: set noet sw=4 ts=4:
|
26
static/Executable_embindmaker.mk
Normal file
26
static/Executable_embindmaker.mk
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t; fill-column: 100 -*-
|
||||||
|
#
|
||||||
|
# This file is part of the LibreOffice project.
|
||||||
|
#
|
||||||
|
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
#
|
||||||
|
|
||||||
|
$(eval $(call gb_Executable_Executable,embindmaker))
|
||||||
|
|
||||||
|
$(eval $(call gb_Executable_add_exception_objects,embindmaker, \
|
||||||
|
static/source/embindmaker/embindmaker \
|
||||||
|
))
|
||||||
|
|
||||||
|
$(eval $(call gb_Executable_use_libraries,embindmaker, \
|
||||||
|
sal \
|
||||||
|
salhelper \
|
||||||
|
unoidl \
|
||||||
|
))
|
||||||
|
|
||||||
|
$(eval $(call gb_Executable_use_static_libraries,embindmaker, \
|
||||||
|
codemaker \
|
||||||
|
))
|
||||||
|
|
||||||
|
# vim: set noet sw=4 ts=4:
|
@ -18,6 +18,8 @@ $(eval $(call gb_Module_add_targets,static,\
|
|||||||
ifeq (EMSCRIPTEN,$(OS))
|
ifeq (EMSCRIPTEN,$(OS))
|
||||||
$(eval $(call gb_Module_add_targets,static,\
|
$(eval $(call gb_Module_add_targets,static,\
|
||||||
CustomTarget_emscripten_fs_image \
|
CustomTarget_emscripten_fs_image \
|
||||||
|
CustomTarget_unoembind \
|
||||||
|
StaticLibrary_unoembind \
|
||||||
$(if $(ENABLE_QT5), \
|
$(if $(ENABLE_QT5), \
|
||||||
CustomTarget_wasm-qt5-mandelbrot_moc \
|
CustomTarget_wasm-qt5-mandelbrot_moc \
|
||||||
Executable_wasm-qt5-mandelbrot \
|
Executable_wasm-qt5-mandelbrot \
|
||||||
@ -27,4 +29,10 @@ endif
|
|||||||
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifneq ($(filter EMSCRIPTEN,$(BUILD_TYPE_FOR_HOST)),)
|
||||||
|
$(eval $(call gb_Module_add_targets,static, \
|
||||||
|
Executable_embindmaker \
|
||||||
|
))
|
||||||
|
endif
|
||||||
|
|
||||||
# vim: set noet sw=4 ts=4:
|
# vim: set noet sw=4 ts=4:
|
||||||
|
27
static/StaticLibrary_unoembind.mk
Normal file
27
static/StaticLibrary_unoembind.mk
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t; fill-column: 100 -*-
|
||||||
|
#
|
||||||
|
# This file is part of the LibreOffice project.
|
||||||
|
#
|
||||||
|
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
#
|
||||||
|
|
||||||
|
$(eval $(call gb_StaticLibrary_StaticLibrary,unoembind))
|
||||||
|
|
||||||
|
$(eval $(call gb_StaticLibrary_add_exception_objects,unoembind, \
|
||||||
|
static/source/unoembindhelpers/PrimaryBindings \
|
||||||
|
))
|
||||||
|
|
||||||
|
$(eval $(call gb_StaticLibrary_add_generated_exception_objects,unoembind, \
|
||||||
|
CustomTarget/static/unoembind/bindings_uno \
|
||||||
|
))
|
||||||
|
|
||||||
|
$(eval $(call gb_StaticLibrary_use_api,unoembind,\
|
||||||
|
offapi \
|
||||||
|
udkapi \
|
||||||
|
))
|
||||||
|
|
||||||
|
$(call gb_StaticLibrary_get_target,unoembind): $(call gb_CustomTarget_get_target,static/unoembind)
|
||||||
|
|
||||||
|
# vim: set noet sw=4 ts=4:
|
510
static/source/embindmaker/embindmaker.cxx
Normal file
510
static/source/embindmaker/embindmaker.cxx
Normal file
@ -0,0 +1,510 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
|
||||||
|
/*
|
||||||
|
* This file is part of the LibreOffice project.
|
||||||
|
*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sal/config.h>
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <iostream>
|
||||||
|
#include <string_view>
|
||||||
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <codemaker/global.hxx>
|
||||||
|
#include <codemaker/typemanager.hxx>
|
||||||
|
#include <osl/file.hxx>
|
||||||
|
#include <osl/process.h>
|
||||||
|
#include <rtl/process.h>
|
||||||
|
#include <rtl/ref.hxx>
|
||||||
|
#include <rtl/string.hxx>
|
||||||
|
#include <rtl/ustrbuf.hxx>
|
||||||
|
#include <rtl/ustring.hxx>
|
||||||
|
#include <sal/main.h>
|
||||||
|
#include <sal/types.h>
|
||||||
|
#include <unoidl/unoidl.hxx>
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
void badUsage()
|
||||||
|
{
|
||||||
|
std::cerr
|
||||||
|
<< "Usage:\n\n"
|
||||||
|
" embindmaker <prefix> <registries>\n\n"
|
||||||
|
"where each <registry> is '+' (primary) or ':' (secondary), followed by: either a\n"
|
||||||
|
"new- or legacy-format .rdb file, a single .idl file, or a root directory of an\n"
|
||||||
|
".idl file tree. Embind code for all primary registries is written to stdout,"
|
||||||
|
"with <prefix> used as part of the name passed to EMSCRIPTEN_BINDINGS.\n";
|
||||||
|
std::exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<OUString, bool> parseRegistryArgument(sal_uInt32 argument)
|
||||||
|
{
|
||||||
|
OUString arg;
|
||||||
|
rtl_getAppCommandArg(argument, &arg.pData);
|
||||||
|
bool primary;
|
||||||
|
if (arg.startsWith(u"+", &arg))
|
||||||
|
{
|
||||||
|
primary = true;
|
||||||
|
}
|
||||||
|
else if (arg.startsWith(u":", &arg))
|
||||||
|
{
|
||||||
|
primary = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cerr << "Bad registry argument \"" << arg << "\"\n";
|
||||||
|
std::exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
OUString url;
|
||||||
|
auto const e1 = osl::FileBase::getFileURLFromSystemPath(arg, url);
|
||||||
|
if (e1 != osl::FileBase::E_None)
|
||||||
|
{
|
||||||
|
std::cerr << "Cannot convert \"" << arg << "\" to file URL, error code " << +e1 << "\n";
|
||||||
|
std::exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
OUString cwd;
|
||||||
|
auto const e2 = osl_getProcessWorkingDir(&cwd.pData);
|
||||||
|
if (e2 != osl_Process_E_None)
|
||||||
|
{
|
||||||
|
std::cerr << "Cannot obtain working directory, error code " << +e2 << "\n";
|
||||||
|
std::exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
OUString abs;
|
||||||
|
auto const e3 = osl::FileBase::getAbsoluteFileURL(cwd, url, abs);
|
||||||
|
if (e3 != osl::FileBase::E_None)
|
||||||
|
{
|
||||||
|
std::cerr << "Cannot make \"" << url << "\" into an absolute file URL, error code " << +e3
|
||||||
|
<< "\n";
|
||||||
|
std::exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
return { abs, primary };
|
||||||
|
}
|
||||||
|
|
||||||
|
void scan(rtl::Reference<unoidl::MapCursor> const& cursor, std::u16string_view prefix,
|
||||||
|
std::vector<OUString>& interfaces)
|
||||||
|
{
|
||||||
|
assert(cursor.is());
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
OUString id;
|
||||||
|
auto const ent = cursor->getNext(&id);
|
||||||
|
if (!ent.is())
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
OUString name(prefix + id);
|
||||||
|
switch (ent->getSort())
|
||||||
|
{
|
||||||
|
case unoidl::Entity::SORT_MODULE:
|
||||||
|
scan(static_cast<unoidl::ModuleEntity*>(ent.get())->createCursor(),
|
||||||
|
Concat2View(name + "."), interfaces);
|
||||||
|
break;
|
||||||
|
case unoidl::Entity::SORT_INTERFACE_TYPE:
|
||||||
|
interfaces.emplace_back(name);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
OUString cppName(OUString const& name) { return "::" + name.replaceAll(u".", u"::"); }
|
||||||
|
|
||||||
|
OUString jsName(OUString const& name) { return name.replace('.', '$'); }
|
||||||
|
|
||||||
|
void dumpAttributes(OUString const& name, rtl::Reference<unoidl::InterfaceTypeEntity> const& entity)
|
||||||
|
{
|
||||||
|
for (auto const& attr : entity->getDirectAttributes())
|
||||||
|
{
|
||||||
|
std::cout << " .function(\"get" << attr.name << "\", &" << cppName(name) << "::get"
|
||||||
|
<< attr.name << ")\n";
|
||||||
|
if (!attr.readOnly)
|
||||||
|
{
|
||||||
|
std::cout << " .function(\"set" << attr.name << "\", &" << cppName(name)
|
||||||
|
<< "::set" << attr.name << ")\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
OUString resolveOuterTypedefs(rtl::Reference<TypeManager> const& manager, OUString const& name)
|
||||||
|
{
|
||||||
|
for (OUString n(name);;)
|
||||||
|
{
|
||||||
|
rtl::Reference<unoidl::Entity> ent;
|
||||||
|
if (manager->getSort(n, &ent) != codemaker::UnoType::Sort::Typedef)
|
||||||
|
{
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
n = dynamic_cast<unoidl::TypedefEntity&>(*ent).getType();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
OUString resolveAllTypedefs(rtl::Reference<TypeManager> const& manager, std::u16string_view name)
|
||||||
|
{
|
||||||
|
sal_Int32 k1;
|
||||||
|
OUString n(b2u(codemaker::UnoType::decompose(u2b(name), &k1)));
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
rtl::Reference<unoidl::Entity> ent;
|
||||||
|
if (manager->getSort(n, &ent) != codemaker::UnoType::Sort::Typedef)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
sal_Int32 k2;
|
||||||
|
n = b2u(codemaker::UnoType::decompose(
|
||||||
|
u2b(static_cast<unoidl::TypedefEntity*>(ent.get())->getType()), &k2));
|
||||||
|
k1 += k2; //TODO: overflow
|
||||||
|
}
|
||||||
|
OUStringBuffer b;
|
||||||
|
for (sal_Int32 i = 0; i != k1; ++i)
|
||||||
|
{
|
||||||
|
b.append("[]");
|
||||||
|
}
|
||||||
|
b.append(n);
|
||||||
|
return b.makeStringAndClear();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool passByReference(rtl::Reference<TypeManager> const& manager, OUString const& name)
|
||||||
|
{
|
||||||
|
switch (manager->getSort(resolveOuterTypedefs(manager, 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 passByReference");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void dumpType(rtl::Reference<TypeManager> const& manager, std::u16string_view name, bool isConst)
|
||||||
|
{
|
||||||
|
sal_Int32 k;
|
||||||
|
std::vector<OString> args;
|
||||||
|
OUString n(
|
||||||
|
b2u(codemaker::UnoType::decompose(u2b(resolveAllTypedefs(manager, name)), &k, &args)));
|
||||||
|
if (isConst)
|
||||||
|
{
|
||||||
|
std::cout << "const ";
|
||||||
|
}
|
||||||
|
for (sal_Int32 i = 0; i != k; ++i)
|
||||||
|
{
|
||||||
|
std::cout << "::css::uno::Sequence<";
|
||||||
|
}
|
||||||
|
switch (manager->getSort(n))
|
||||||
|
{
|
||||||
|
case codemaker::UnoType::Sort::Void:
|
||||||
|
std::cout << "void";
|
||||||
|
break;
|
||||||
|
case codemaker::UnoType::Sort::Boolean:
|
||||||
|
std::cout << "::sal_Bool";
|
||||||
|
break;
|
||||||
|
case codemaker::UnoType::Sort::Byte:
|
||||||
|
std::cout << "::sal_Int8";
|
||||||
|
break;
|
||||||
|
case codemaker::UnoType::Sort::Short:
|
||||||
|
std::cout << "::sal_Int16";
|
||||||
|
break;
|
||||||
|
case codemaker::UnoType::Sort::UnsignedShort:
|
||||||
|
std::cout << "::sal_uInt16";
|
||||||
|
break;
|
||||||
|
case codemaker::UnoType::Sort::Long:
|
||||||
|
std::cout << "::sal_Int32";
|
||||||
|
break;
|
||||||
|
case codemaker::UnoType::Sort::UnsignedLong:
|
||||||
|
std::cout << "::sal_uInt32";
|
||||||
|
break;
|
||||||
|
case codemaker::UnoType::Sort::Hyper:
|
||||||
|
std::cout << "::sal_Int64";
|
||||||
|
break;
|
||||||
|
case codemaker::UnoType::Sort::UnsignedHyper:
|
||||||
|
std::cout << "::sal_uInt64";
|
||||||
|
break;
|
||||||
|
case codemaker::UnoType::Sort::Float:
|
||||||
|
std::cout << "float";
|
||||||
|
break;
|
||||||
|
case codemaker::UnoType::Sort::Double:
|
||||||
|
std::cout << "double";
|
||||||
|
break;
|
||||||
|
case codemaker::UnoType::Sort::Char:
|
||||||
|
std::cout << "::sal_Unicode";
|
||||||
|
break;
|
||||||
|
case codemaker::UnoType::Sort::String:
|
||||||
|
std::cout << "::rtl::OUString";
|
||||||
|
break;
|
||||||
|
case codemaker::UnoType::Sort::Type:
|
||||||
|
std::cout << "::css::uno::Type";
|
||||||
|
break;
|
||||||
|
case codemaker::UnoType::Sort::Any:
|
||||||
|
std::cout << "::css::uno::Any";
|
||||||
|
break;
|
||||||
|
case codemaker::UnoType::Sort::Enum:
|
||||||
|
case codemaker::UnoType::Sort::PlainStruct:
|
||||||
|
case codemaker::UnoType::Sort::Exception:
|
||||||
|
std::cout << cppName(n);
|
||||||
|
break;
|
||||||
|
case codemaker::UnoType::Sort::PolymorphicStructTemplate:
|
||||||
|
std::cout << cppName(n);
|
||||||
|
if (!args.empty())
|
||||||
|
{
|
||||||
|
std::cout << "<";
|
||||||
|
bool first = true;
|
||||||
|
for (auto const& arg : args)
|
||||||
|
{
|
||||||
|
if (first)
|
||||||
|
{
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cout << ", ";
|
||||||
|
}
|
||||||
|
dumpType(manager, b2u(arg), false);
|
||||||
|
}
|
||||||
|
std::cout << ">";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case codemaker::UnoType::Sort::Interface:
|
||||||
|
std::cout << "::css::uno::Reference<";
|
||||||
|
std::cout << cppName(n);
|
||||||
|
std::cout << ">";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw CannotDumpException(OUString::Concat("unexpected entity \"") + name
|
||||||
|
+ "\" in call to dumpType");
|
||||||
|
}
|
||||||
|
for (sal_Int32 i = 0; i != k; ++i)
|
||||||
|
{
|
||||||
|
std::cout << ">";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void dumpParameters(rtl::Reference<TypeManager> const& manager,
|
||||||
|
unoidl::InterfaceTypeEntity::Method const& method, bool declarations)
|
||||||
|
{
|
||||||
|
bool first = true;
|
||||||
|
for (auto const& param : method.parameters)
|
||||||
|
{
|
||||||
|
if (first)
|
||||||
|
{
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cout << ", ";
|
||||||
|
}
|
||||||
|
bool isConst;
|
||||||
|
bool isRef;
|
||||||
|
if (param.direction == unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_IN)
|
||||||
|
{
|
||||||
|
isConst = passByReference(manager, param.type);
|
||||||
|
isRef = isConst;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
isConst = false;
|
||||||
|
isRef = true;
|
||||||
|
}
|
||||||
|
// For the embind wrapper, we define a pointer instead of a reference:
|
||||||
|
if (declarations)
|
||||||
|
{
|
||||||
|
dumpType(manager, param.type, isConst);
|
||||||
|
std::cout << " ";
|
||||||
|
}
|
||||||
|
if (isRef)
|
||||||
|
{
|
||||||
|
std::cout << "*";
|
||||||
|
}
|
||||||
|
if (declarations)
|
||||||
|
{
|
||||||
|
std::cout << " ";
|
||||||
|
}
|
||||||
|
std::cout << param.name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void dumpWrapper(rtl::Reference<TypeManager> const& manager, OUString const& interfaceName,
|
||||||
|
unoidl::InterfaceTypeEntity::Method const& method, bool forReference)
|
||||||
|
{
|
||||||
|
std::cout << " .function(\"" << method.name << "\", +[](";
|
||||||
|
if (forReference)
|
||||||
|
{
|
||||||
|
std::cout << "::com::sun::star::uno::Reference<";
|
||||||
|
}
|
||||||
|
std::cout << cppName(interfaceName);
|
||||||
|
if (forReference)
|
||||||
|
{
|
||||||
|
std::cout << ">";
|
||||||
|
}
|
||||||
|
std::cout << " * the_self";
|
||||||
|
if (!method.parameters.empty())
|
||||||
|
{
|
||||||
|
std::cout << ", ";
|
||||||
|
}
|
||||||
|
dumpParameters(manager, method, true);
|
||||||
|
std::cout << ") { return the_self->";
|
||||||
|
if (forReference)
|
||||||
|
{
|
||||||
|
std::cout << "get()->";
|
||||||
|
}
|
||||||
|
std::cout << method.name << "(";
|
||||||
|
dumpParameters(manager, method, false);
|
||||||
|
std::cout << "); }, ::emscripten::allow_raw_pointers())\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
void dumpMethods(rtl::Reference<TypeManager> const& manager, OUString const& name,
|
||||||
|
rtl::Reference<unoidl::InterfaceTypeEntity> const& entity, bool forReference)
|
||||||
|
{
|
||||||
|
for (auto const& meth : entity->getDirectMethods())
|
||||||
|
{
|
||||||
|
if (forReference)
|
||||||
|
{
|
||||||
|
dumpWrapper(manager, name, meth, true);
|
||||||
|
}
|
||||||
|
else if (std::any_of(
|
||||||
|
meth.parameters.begin(), meth.parameters.end(), [](auto const& parameter) {
|
||||||
|
return parameter.direction
|
||||||
|
!= unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_IN;
|
||||||
|
}))
|
||||||
|
{
|
||||||
|
dumpWrapper(manager, name, meth, false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cout << " .function(\"" << meth.name << "\", &" << cppName(name)
|
||||||
|
<< "::" << meth.name << ")\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SAL_IMPLEMENT_MAIN()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
auto const args = rtl_getAppCommandArgCount();
|
||||||
|
if (args == 0)
|
||||||
|
{
|
||||||
|
badUsage();
|
||||||
|
}
|
||||||
|
OUString prefix;
|
||||||
|
rtl_getAppCommandArg(0, &prefix.pData);
|
||||||
|
rtl::Reference<TypeManager> mgr(new TypeManager);
|
||||||
|
for (sal_uInt32 i = 1; i != args; ++i)
|
||||||
|
{
|
||||||
|
auto const & [ uri, primary ] = parseRegistryArgument(i);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
mgr->loadProvider(uri, primary);
|
||||||
|
}
|
||||||
|
catch (unoidl::NoSuchFileException&)
|
||||||
|
{
|
||||||
|
std::cerr << "Input <" << uri << "> does not exist\n";
|
||||||
|
std::exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::vector<OUString> interfaces;
|
||||||
|
for (auto const& prov : mgr->getPrimaryProviders())
|
||||||
|
{
|
||||||
|
scan(prov->createRootCursor(), u"", interfaces);
|
||||||
|
}
|
||||||
|
std::cout << "#include <emscripten/bind.h>\n"
|
||||||
|
"#include <com/sun/star/uno/Any.hxx>\n"
|
||||||
|
"#include <com/sun/star/uno/Reference.hxx>\n";
|
||||||
|
for (auto const& ifc : interfaces)
|
||||||
|
{
|
||||||
|
std::cout << "#include <" << ifc.replace('.', '/') << ".hpp>\n";
|
||||||
|
}
|
||||||
|
std::cout << "\n"
|
||||||
|
"// TODO: This is a temporary workaround that likely causes the Embind UNO\n"
|
||||||
|
"// bindings to leak memory. Reference counting and cloning mechanisms of\n"
|
||||||
|
"// Embind should be investigated to figure out what exactly we need here:\n"
|
||||||
|
"namespace emscripten::internal {\n";
|
||||||
|
for (auto const& ifc : interfaces)
|
||||||
|
{
|
||||||
|
std::cout << " template<> void raw_destructor<" << cppName(ifc) << ">("
|
||||||
|
<< cppName(ifc) << " *) {}\n";
|
||||||
|
}
|
||||||
|
std::cout << "}\n\n"
|
||||||
|
"EMSCRIPTEN_BINDINGS(uno_bindings_"
|
||||||
|
<< prefix << ") {\n";
|
||||||
|
for (auto const& ifc : interfaces)
|
||||||
|
{
|
||||||
|
auto const ent = mgr->getManager()->findEntity(ifc);
|
||||||
|
assert(ent.is());
|
||||||
|
assert(ent->getSort() == unoidl::Entity::SORT_INTERFACE_TYPE);
|
||||||
|
rtl::Reference const ifcEnt(static_cast<unoidl::InterfaceTypeEntity*>(ent.get()));
|
||||||
|
std::cout << " ::emscripten::class_<" << cppName(ifc) << ">(\"" << jsName(ifc)
|
||||||
|
<< "\")\n";
|
||||||
|
dumpAttributes(ifc, ifcEnt);
|
||||||
|
dumpMethods(mgr, ifc, ifcEnt, false);
|
||||||
|
std::cout << " ;\n"
|
||||||
|
" ::emscripten::class_<::com::sun::star::uno::Reference<"
|
||||||
|
<< cppName(ifc)
|
||||||
|
<< ">, ::emscripten::base<::com::sun::star::uno::BaseReference>>(\""
|
||||||
|
<< jsName(ifc)
|
||||||
|
<< "Ref\")\n"
|
||||||
|
" .constructor<>()\n"
|
||||||
|
" .constructor<::com::sun::star::uno::BaseReference, "
|
||||||
|
"::com::sun::star::uno::UnoReference_Query>()\n"
|
||||||
|
" .function(\"is\", &::com::sun::star::uno::Reference<"
|
||||||
|
<< cppName(ifc)
|
||||||
|
<< ">::is)\n"
|
||||||
|
" .function(\"get\", &::com::sun::star::uno::Reference<"
|
||||||
|
<< cppName(ifc)
|
||||||
|
<< ">::get, ::emscripten::allow_raw_pointers())\n"
|
||||||
|
" .function(\"set\", "
|
||||||
|
"::emscripten::select_overload<bool(::com::sun::star::uno::Any const "
|
||||||
|
"&, "
|
||||||
|
"com::sun::star::uno::UnoReference_Query)>(&::com::sun::star::uno::"
|
||||||
|
"Reference<"
|
||||||
|
<< cppName(ifc) << ">::set))\n";
|
||||||
|
dumpAttributes(ifc, ifcEnt);
|
||||||
|
dumpMethods(mgr, ifc, ifcEnt, true);
|
||||||
|
std::cout << " ;\n";
|
||||||
|
}
|
||||||
|
std::cout << "}\n";
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
catch (unoidl::FileFormatException const& e)
|
||||||
|
{
|
||||||
|
std::cerr << "Bad input <" << e.getUri() << ">: " << e.getDetail() << "\n";
|
||||||
|
std::exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
catch (CannotDumpException const& e)
|
||||||
|
{
|
||||||
|
std::cerr << "Failure: " << e.getMessage() << "\n";
|
||||||
|
std::exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
catch (std::exception const& e)
|
||||||
|
{
|
||||||
|
std::cerr << "Failure: " << e.what() << "\n";
|
||||||
|
std::exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
|
Loading…
x
Reference in New Issue
Block a user