[Libreoffice-commits] core.git: Repository.mk solenv/gbuild unoidl/Executable_reg2unoidl.mk unoidl/Executable_unoidl-write.mk unoidl/Module_unoidl.mk unoidl/README unoidl/source

Stephan Bergmann sbergman at redhat.com
Mon Sep 16 07:51:20 PDT 2013


 Repository.mk                     |    2 
 solenv/gbuild/LinkTarget.mk       |    4 
 solenv/gbuild/UnoApiTarget.mk     |    4 
 unoidl/Executable_reg2unoidl.mk   |   22 
 unoidl/Executable_unoidl-write.mk |   22 
 unoidl/Module_unoidl.mk           |    2 
 unoidl/README                     |   21 
 unoidl/source/reg2unoidl.cxx      |  977 ---------------------------------
 unoidl/source/sourceprovider.cxx  |  111 ++-
 unoidl/source/unoidl-write.cxx    | 1112 ++++++++++++++++++++++++++++++++++++++
 10 files changed, 1221 insertions(+), 1056 deletions(-)

New commits:
commit fc54915c461dc753866627bd52ea60b12b71a012
Author: Stephan Bergmann <sbergman at redhat.com>
Date:   Mon Sep 16 16:48:09 2013 +0200

    Replace reg2unoidl with unoidl-write
    
    ...that can also generate an .rdb containing a specific set of entities,
    intended to replace idlc (when reading directly from .idl source registries).
    
    Change-Id: I630ce4640828979d7952dc24dbbef80a42a8140a

diff --git a/Repository.mk b/Repository.mk
index cff654b..b3111fb 100644
--- a/Repository.mk
+++ b/Repository.mk
@@ -48,7 +48,6 @@ $(eval $(call gb_Helper_register_executables,NONE, \
 	pdfunzip \
 	pocheck \
 	propex \
-	reg2unoidl \
 	regsvrex \
 	rsc \
 	saxparser \
@@ -60,6 +59,7 @@ $(eval $(call gb_Helper_register_executables,NONE, \
 	treex \
 	uiex \
 	ulfex \
+	unoidl-write \
 	xrmex \
 ))
 
diff --git a/solenv/gbuild/LinkTarget.mk b/solenv/gbuild/LinkTarget.mk
index 44fc886..b7150f0 100644
--- a/solenv/gbuild/LinkTarget.mk
+++ b/solenv/gbuild/LinkTarget.mk
@@ -850,11 +850,11 @@ gb_BUILD_HELPER_LIBS := basegfx \
 
 gb_BUILD_HELPER_TOOLS := cppumaker \
 	idlc \
-	reg2unoidl \
 	regcompare \
 	regmerge \
 	rsc \
-	svidl
+	svidl \
+	unoidl-write \
 
 define gb_LinkTarget__is_build_lib
 $(if $(filter $(1),$(foreach lib,$(gb_BUILD_HELPER_LIBS),$(call gb_Library_get_linktargetname,$(lib)))),$(true),$(false))
diff --git a/solenv/gbuild/UnoApiTarget.mk b/solenv/gbuild/UnoApiTarget.mk
index 97ec264..92b812c 100644
--- a/solenv/gbuild/UnoApiTarget.mk
+++ b/solenv/gbuild/UnoApiTarget.mk
@@ -80,7 +80,7 @@ endif
 
 gb_UnoApiTarget_REGCOMPAREDEPS := $(call gb_Executable_get_runtime_dependencies,regcompare)
 gb_UnoApiTarget_REGCOMPARECOMMAND := SOLARBINDIR=$(OUTDIR_FOR_BUILD)/bin $(call gb_Executable_get_command,regcompare)
-gb_UnoApiTarget_REGMERGEDEPS := $(call gb_Executable_get_runtime_dependencies,regmerge) $(call gb_Executable_get_runtime_dependencies,reg2unoidl)
+gb_UnoApiTarget_REGMERGEDEPS := $(call gb_Executable_get_runtime_dependencies,regmerge) $(call gb_Executable_get_runtime_dependencies,unoidl-write)
 gb_UnoApiTarget_REGMERGECOMMAND := SOLARBINDIR=$(OUTDIR_FOR_BUILD)/bin $(call gb_Executable_get_command,regmerge)
 
 gb_UnoApiTarget_TYPESRDB := $(call gb_UnoApiTarget_get_target,types)
@@ -90,7 +90,7 @@ RESPONSEFILE=$(call var2file,$(shell $(gb_MKTEMP)),500,$(1).oldformat $(2) $(3))
 $(gb_UnoApiTarget_REGMERGECOMMAND) @$${RESPONSEFILE} && \
 rm -f $${RESPONSEFILE} && \
 SOLARBINDIR=$(OUTDIR_FOR_BUILD)/bin \
-	$(call gb_Executable_get_command,reg2unoidl) \
+	$(call gb_Executable_get_command,unoidl-write) \
 	$(foreach rdb,$(4),$(call gb_UnoApiTarget_get_target,$(rdb))) \
 	$(1).oldformat $(1)
 endef
diff --git a/unoidl/Executable_reg2unoidl.mk b/unoidl/Executable_unoidl-write.mk
similarity index 65%
rename from unoidl/Executable_reg2unoidl.mk
rename to unoidl/Executable_unoidl-write.mk
index 7f21a08..8936955 100644
--- a/unoidl/Executable_reg2unoidl.mk
+++ b/unoidl/Executable_unoidl-write.mk
@@ -7,13 +7,13 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 #
 
-$(eval $(call gb_Executable_Executable,reg2unoidl))
+$(eval $(call gb_Executable_Executable,unoidl-write))
 
-$(eval $(call gb_Executable_add_exception_objects,reg2unoidl, \
-    unoidl/source/reg2unoidl \
+$(eval $(call gb_Executable_add_exception_objects,unoidl-write, \
+    unoidl/source/unoidl-write \
 ))
 
-$(eval $(call gb_Executable_use_libraries,reg2unoidl, \
+$(eval $(call gb_Executable_use_libraries,unoidl-write, \
     sal \
     salhelper \
     unoidl \
diff --git a/unoidl/Module_unoidl.mk b/unoidl/Module_unoidl.mk
index 92a779e..c035257 100644
--- a/unoidl/Module_unoidl.mk
+++ b/unoidl/Module_unoidl.mk
@@ -14,7 +14,7 @@ $(eval $(call gb_Module_add_targets,unoidl, \
 ))
 
 $(eval $(call gb_Module_add_targets_for_build,unoidl, \
-    Executable_reg2unoidl \
+    Executable_unoidl-write \
 ))
 
 # vim: set noet sw=4 ts=4:
diff --git a/unoidl/README b/unoidl/README
index 84246e9..cf405a1 100644
--- a/unoidl/README
+++ b/unoidl/README
@@ -8,16 +8,16 @@ for both the new and the old types.rdb formats (unoidl::loadProvider tries both
 implementations in turn for a given file, so the old format is still supported
 transparently for now).
 
-Executable_reg2unoidl is a helper tool to convert from the old to the new
+Executable_unoidl-write is a helper tool to convert from the old to the new
 types.rdb format.  It is currently used at build-time.  idlc still generates the
 old format, and any new-format files (used at build-time only, or included in
 installation sets in URE or program/types/ or as part of bundled extensions that
 are created during the build and not merely included as pre-built .oxt files)
-are explicitly generated via reg2unoidl.  The SDK is still designed to generate
-old-format files exclusively (especially, any non-bundled extensions will only
-contain old-format files for now; that allows to modify the new format further
-without having to worry about compatibility with multiple versions of that
-format).
+are explicitly generated via unoidl-write.  The SDK is still designed to
+generate old-format files exclusively (especially, any non-bundled extensions
+will only contain old-format files for now; that allows to modify the new format
+further without having to worry about compatibility with multiple versions of
+that format).
 
 == Specification of the new UNOIDL types.rdb format ==
 
@@ -56,7 +56,7 @@ The following definitions are used throughout:
 * Map: zero or more Entries
 
 The file starts with an 8 byte header, followed by information about the root
-map (reg2unoidl generates files in a single depth-first pass, so the root map
+map (unoidl-write generates files in a single depth-first pass, so the root map
 itself is at the end of the file):
 
 * 7 byte magic header "UNOIDL\xFF"
@@ -65,11 +65,12 @@ itself is at the end of the file):
 * UInt32 number of entries of root Map
 ...
 
-Files generated by reg2unoidl follow that by a
+Files generated by unoidl-write follow that by a
 
-  "\0** Created by LibreOffice " LIBO_VERSION_DOTTED " reg2unoidl **\0"
+  "\0** Created by LibreOffice " LIBO_VERSION_DOTTED " unoidl-write **\0"
 
-banner (cf. config_host/config_version.h.in), as a debugging aid.
+banner (cf. config_host/config_version.h.in), as a debugging aid.  (Old versions
+used "reg2unoidl" instead of "unoidl-write" in that banner.)
 
 Layout of per-entry payload in the root or a module Map:
 
diff --git a/unoidl/source/sourceprovider.cxx b/unoidl/source/sourceprovider.cxx
index ed44e40..ea7f110 100755
--- a/unoidl/source/sourceprovider.cxx
+++ b/unoidl/source/sourceprovider.cxx
@@ -14,6 +14,7 @@
 #include <new>
 
 #include "osl/file.h"
+#include "osl/file.hxx"
 #include "osl/thread.h"
 #include "rtl/character.hxx"
 #include "rtl/ref.hxx"
@@ -86,6 +87,20 @@ private:
     { return rtl::Reference<Entity>(); } //TODO
 };
 
+class SourceModuleEntity: public ModuleEntity {
+public:
+    SourceModuleEntity() {}
+
+private:
+    virtual ~SourceModuleEntity() throw () {}
+
+    virtual std::vector<OUString> getMemberNames() const
+    { return std::vector<OUString>(); } //TODO
+
+    virtual rtl::Reference< MapCursor > createCursor() const
+    { return new Cursor; }
+};
+
 }
 
 SourceProvider::SourceProvider(
@@ -147,53 +162,67 @@ rtl::Reference<Entity> SourceProvider::findEntity(OUString const & name) const {
         throw FileFormatException( //TODO
             "", "Illegal UNOIDL identifier \"" + name + "\"");
     }
-    OUString uri(uri_ + buf.makeStringAndClear() + ".idl");
-    oslFileHandle handle;
-    oslFileError e = osl_openFile(uri.pData, &handle, osl_File_OpenFlag_Read);
-    switch (e) {
-    case osl_File_E_None:
-        break;
-    case osl_File_E_NOENT:
-        cache_.insert(
-            std::map< OUString, rtl::Reference<Entity> >::value_type(
-                name, rtl::Reference<Entity>()));
-        return rtl::Reference<Entity>();
-    default:
-        throw FileFormatException(uri, "cannot open: " + OUString::number(e));
-    }
-    sal_uInt64 size;
-    e = osl_getFileSize(handle, &size);
-    if (e != osl_File_E_None) {
-        oslFileError e2 = osl_closeFile(handle);
-        SAL_WARN_IF(
-            e2 != osl_File_E_None, "unoidl",
-            "cannot close " << uri << ": " << +e2);
-        throw FileFormatException(
-            uri, "cannot get size: " + OUString::number(e));
-    }
-    void * address;
-    e = osl_mapFile(handle, &address, size, 0, osl_File_MapFlag_RandomAccess);
-    if (e != osl_File_E_None) {
-        oslFileError e2 = osl_closeFile(handle);
-        SAL_WARN_IF(
-            e2 != osl_File_E_None, "unoidl",
-            "cannot close " << uri << ": " << +e2);
-        throw FileFormatException(uri, "cannot mmap: " + OUString::number(e));
-    }
+    OUString uri(uri_ + buf.makeStringAndClear());
     rtl::Reference<Entity> ent;
-    try {
-        ent = parse(manager_, name, uri, address, size);
-    } catch (...) {
+    osl::DirectoryItem item;
+    osl::FileStatus status(osl_FileStatus_Mask_Type);
+    if (osl::DirectoryItem::get(uri, item) == osl::FileBase::E_None
+        && item.getFileStatus(status) == osl::FileBase::E_None
+        && status.getFileType() == osl::FileStatus::Directory)
+    {
+        ent = new SourceModuleEntity;
+    } else {
+        uri += ".idl";
+        oslFileHandle handle;
+        oslFileError e = osl_openFile(
+            uri.pData, &handle, osl_File_OpenFlag_Read);
+        switch (e) {
+        case osl_File_E_None:
+            break;
+        case osl_File_E_NOENT:
+            cache_.insert(
+                std::map< OUString, rtl::Reference<Entity> >::value_type(
+                    name, rtl::Reference<Entity>()));
+            return rtl::Reference<Entity>();
+        default:
+            throw FileFormatException(
+                uri, "cannot open: " + OUString::number(e));
+        }
+        sal_uInt64 size;
+        e = osl_getFileSize(handle, &size);
+        if (e != osl_File_E_None) {
+            oslFileError e2 = osl_closeFile(handle);
+            SAL_WARN_IF(
+                e2 != osl_File_E_None, "unoidl",
+                "cannot close " << uri << ": " << +e2);
+            throw FileFormatException(
+                uri, "cannot get size: " + OUString::number(e));
+        }
+        void * address;
+        e = osl_mapFile(
+            handle, &address, size, 0, osl_File_MapFlag_RandomAccess);
+        if (e != osl_File_E_None) {
+            oslFileError e2 = osl_closeFile(handle);
+            SAL_WARN_IF(
+                e2 != osl_File_E_None, "unoidl",
+                "cannot close " << uri << ": " << +e2);
+            throw FileFormatException(
+                uri, "cannot mmap: " + OUString::number(e));
+        }
+        try {
+            ent = parse(manager_, name, uri, address, size);
+        } catch (...) {
+            e = osl_unmapMappedFile(handle, address, size);
+            SAL_WARN_IF(e != osl_File_E_None, "unoidl", "cannot unmap: " << +e);
+            e = osl_closeFile(handle);
+            SAL_WARN_IF(e != osl_File_E_None, "unoidl", "cannot close: " << +e);
+            throw;
+        }
         e = osl_unmapMappedFile(handle, address, size);
         SAL_WARN_IF(e != osl_File_E_None, "unoidl", "cannot unmap: " << +e);
         e = osl_closeFile(handle);
         SAL_WARN_IF(e != osl_File_E_None, "unoidl", "cannot close: " << +e);
-        throw;
     }
-    e = osl_unmapMappedFile(handle, address, size);
-    SAL_WARN_IF(e != osl_File_E_None, "unoidl", "cannot unmap: " << +e);
-    e = osl_closeFile(handle);
-    SAL_WARN_IF(e != osl_File_E_None, "unoidl", "cannot close: " << +e);
     cache_.insert(
         std::map< OUString, rtl::Reference<Entity> >::value_type(name, ent));
     return ent;
diff --git a/unoidl/source/reg2unoidl.cxx b/unoidl/source/unoidl-write.cxx
similarity index 81%
rename from unoidl/source/reg2unoidl.cxx
rename to unoidl/source/unoidl-write.cxx
index bf2b6d2..dbb3ef7 100644
--- a/unoidl/source/reg2unoidl.cxx
+++ b/unoidl/source/unoidl-write.cxx
@@ -34,9 +34,38 @@
 
 namespace {
 
-OUString getArgumentUri(sal_uInt32 argument) {
+void badUsage() {
+    std::cerr
+        << "Usage:" << std::endl << std::endl
+        << "  unoidl-write [<registries>] [@<entities file>] <unoidl file>"
+        << std::endl << std::endl
+        << ("where each <registry> is either a new- or legacy-format .rdb"
+            " file or a")
+        << std::endl
+        << ("root directory of an .idl file tree, and the UTF-8 encoded"
+            " <entities file>")
+        << std::endl
+        << ("contains zero or more space-separated names of (non-module)"
+            " entities to include")
+        << std::endl
+        << ("in the output, and, if omitted, defaults to the complete content"
+            " of the final")
+        << std::endl << "<registry>, if any." << std::endl;
+    std::exit(EXIT_FAILURE);
+}
+
+OUString getArgumentUri(sal_uInt32 argument, bool * entities) {
     OUString arg;
     rtl_getAppCommandArg(argument, &arg.pData);
+    if (arg.startsWith("@")) {
+        if (entities == 0) {
+            badUsage();
+        }
+        *entities = true;
+        arg = arg.copy(1);
+    } else if (entities != 0) {
+        *entities = false;
+    }
     OUString url;
     osl::FileBase::RC e1 = osl::FileBase::getFileURLFromSystemPath(arg, url);
     if (e1 != osl::FileBase::E_None) {
@@ -64,22 +93,6 @@ OUString getArgumentUri(sal_uInt32 argument) {
     return abs;
 }
 
-rtl::Reference< unoidl::Provider > load(
-    rtl::Reference< unoidl::Manager > const & manager, OUString const & uri)
-{
-    try {
-        return unoidl::loadProvider(manager, uri);
-    } catch (unoidl::NoSuchFileException &) {
-        std::cerr << "Input <" << uri << "> does not exist" << std::endl;
-        std::exit(EXIT_FAILURE);
-    } catch (unoidl::FileFormatException & e) {
-        std::cerr
-            << "Cannot read input <" << uri << ">: " << e.getDetail()
-            << std::endl;
-        std::exit(EXIT_FAILURE);
-    }
-}
-
 sal_uInt64 getOffset(osl::File & file) {
     sal_uInt64 off;
     osl::FileBase::RC e = file.getPos(off);
@@ -292,6 +305,7 @@ struct Item {
     {}
 
     rtl::Reference< unoidl::Entity > entity;
+    std::map< OUString, Item > module;
     sal_uInt64 nameOffset;
     sal_uInt64 dataOffset;
 };
@@ -310,35 +324,139 @@ struct ConstItem {
     sal_uInt64 dataOffset;
 };
 
-sal_uInt64 writeMap(
-    osl::File & file, rtl::Reference< unoidl::MapCursor > const & cursor,
-    std::size_t * rootSize)
+void mapEntities(
+    rtl::Reference< unoidl::Manager > const & manager, OUString const & uri,
+    std::map< OUString, Item > & map)
 {
-    assert(cursor.is());
-    std::map< OUString, Item > map;
+    assert(manager.is());
+    osl::File f(uri);
+    osl::FileBase::RC e = f.open(osl_File_OpenFlag_Read);
+    if (e != osl::FileBase::E_None) {
+        std::cerr
+            << "Cannot open <" << f.getURL() << "> for reading, error code "
+            << +e << std::endl;
+        std::exit(EXIT_FAILURE);
+    }
     for (;;) {
-        OUString name;
-        rtl::Reference< unoidl::Entity > ent(cursor->getNext(&name));
-        if (!ent.is()) {
+        sal_Bool eof;
+        e = f.isEndOfFile(&eof);
+        if (e != osl::FileBase::E_None) {
+            std::cerr
+                << "Cannot check <" << f.getURL() << "> for EOF, error code "
+                << +e << std::endl;
+            std::exit(EXIT_FAILURE);
+        }
+        if (eof) {
             break;
         }
-        if (!map.insert(std::make_pair(name, Item(ent))).second) {
-            std::cout << "Duplicate name \"" << name << '"' << std::endl;
+        rtl::ByteSequence s1;
+        e = f.readLine(s1);
+        if (e != osl::FileBase::E_None) {
+            std::cerr
+                << "Cannot read from <" << f.getURL() << ">, error code "
+                << +e << std::endl;
+            std::exit(EXIT_FAILURE);
+        }
+        OUString s2;
+        if (!rtl_convertStringToUString(
+                &s2.pData, reinterpret_cast< char const * >(s1.getConstArray()),
+                s1.getLength(), RTL_TEXTENCODING_UTF8,
+                (RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR
+                 | RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR
+                 | RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR)))
+        {
+            std::cerr
+                << "Cannot interpret line read from <" << f.getURL()
+                << "> as UTF-8" << std::endl;
             std::exit(EXIT_FAILURE);
         }
+        for (sal_Int32 i = 0; i != -1;) {
+            OUString t(s2.getToken(0, ' ', i));
+            if (!t.isEmpty()) {
+                rtl::Reference< unoidl::Entity > ent(manager->findEntity(t));
+                if (!ent.is()) {
+                    std::cerr
+                        << "Unknown entity \"" << t << "\" read from <"
+                        << f.getURL() << ">" << std::endl;
+                    std::exit(EXIT_FAILURE);
+                }
+                if (ent->getSort() == unoidl::Entity::SORT_MODULE) {
+                    std::cerr
+                        << "Module entity \"" << t << "\" read from <"
+                        << f.getURL() << ">" << std::endl;
+                    std::exit(EXIT_FAILURE);
+                }
+                std::map< OUString, Item > * map2 = ↦
+                for (sal_Int32 j = 0;;) {
+                    OUString id(t.getToken(0, '.', j));
+                    if (j == -1) {
+                        map2->insert(std::make_pair(id, Item(ent)));
+                        break;
+                    }
+                    std::map< OUString, Item >::iterator k(map2->find(id));
+                    if (k == map2->end()) {
+                        rtl::Reference< unoidl::Entity > ent2(
+                            manager->findEntity(t.copy(0, j - 1)));
+                        assert(ent2.is());
+                        k = map2->insert(std::make_pair(id, Item(ent2))).first;
+                    }
+                    assert(
+                        k->second.entity->getSort()
+                        == unoidl::Entity::SORT_MODULE);
+                    map2 = &k->second.module;
+                }
+            }
+        }
+    }
+    e = f.close();
+    if (e != osl::FileBase::E_None) {
+        std::cerr
+            << "Cannot close <" << f.getURL() << "> after reading, error code "
+            << +e << std::endl;
+        std::exit(EXIT_FAILURE);
     }
+}
+
+void mapCursor(
+    rtl::Reference< unoidl::MapCursor > const & cursor,
+    std::map< OUString, Item > & map)
+{
+    if (cursor.is()) {
+        for (;;) {
+            OUString name;
+            rtl::Reference< unoidl::Entity > ent(cursor->getNext(&name));
+            if (!ent.is()) {
+                break;
+            }
+            std::pair< std::map< OUString, Item >::iterator, bool > i(
+                map.insert(std::make_pair(name, Item(ent))));
+            if (!i.second) {
+                std::cout << "Duplicate name \"" << name << '"' << std::endl;
+                std::exit(EXIT_FAILURE);
+            }
+            if (i.first->second.entity->getSort()
+                == unoidl::Entity::SORT_MODULE)
+            {
+                mapCursor(
+                    rtl::Reference< unoidl::ModuleEntity >(
+                        static_cast< unoidl::ModuleEntity * >(
+                            i.first->second.entity.get()))->createCursor(),
+                    i.first->second.module);
+            }
+        }
+    }
+}
+
+sal_uInt64 writeMap(
+    osl::File & file, std::map< OUString, Item > & map, std::size_t * rootSize)
+{
     for (std::map< OUString, Item >::iterator i(map.begin()); i != map.end();
          ++i)
     {
         switch (i->second.entity->getSort()) {
         case unoidl::Entity::SORT_MODULE:
-            {
-                rtl::Reference< unoidl::ModuleEntity > ent2(
-                    static_cast< unoidl::ModuleEntity * >(
-                        i->second.entity.get()));
-                i->second.dataOffset = writeMap(file, ent2->createCursor(), 0);
-                break;
-            }
+            i->second.dataOffset = writeMap(file, i->second.module, 0);
+            break;
         case unoidl::Entity::SORT_ENUM_TYPE:
             {
                 rtl::Reference< unoidl::EnumTypeEntity > ent2(
@@ -905,73 +1023,90 @@ sal_uInt64 writeMap(
 }
 
 SAL_IMPLEMENT_MAIN() {
-    sal_uInt32 args = rtl_getAppCommandArgCount();
-    if (args < 2) {
-        std::cerr
-            << "Usage: reg2unoidl <extra .rdb files> <.rdb file> <unoidl file>"
-            << std::endl;
-        std::exit(EXIT_FAILURE);
-    }
-    rtl::Reference< unoidl::Manager > mgr(new unoidl::Manager);
-    for (sal_uInt32 i = 0; i != args - 2; ++i) {
-        mgr->addProvider(load(mgr, getArgumentUri(i)));
-    }
-    rtl::Reference< unoidl::Provider > prov(
-        load(mgr, getArgumentUri(args - 2)));
-    osl::File f(getArgumentUri(args - 1));
-    osl::FileBase::RC e = f.open(osl_File_OpenFlag_Write);
-    if (e == osl::FileBase::E_NOENT) {
-        e = f.open(osl_File_OpenFlag_Write | osl_File_OpenFlag_Create);
-    }
-    if (e != osl::FileBase::E_None) {
-        std::cerr
-            << "Cannot open <" << f.getURL() << "> for writing, error code "
-            << +e << std::endl;
-        std::exit(EXIT_FAILURE);
-    }
-    write(f, "UNOIDL\xFF\0", 8);
-    write32(f, 0); // root map offset
-    write32(f, 0); // root map size
-    write(
-        f,
-        RTL_CONSTASCII_STRINGPARAM(
-            "\0** Created by LibreOffice " LIBO_VERSION_DOTTED
-            " reg2unoidl **\0"));
-    sal_uInt64 off;
-    std::size_t size;
     try {
-        off = writeMap(f, prov->createRootCursor(), &size);
+        sal_uInt32 args = rtl_getAppCommandArgCount();
+        if (args == 0) {
+            badUsage();
+        }
+        rtl::Reference< unoidl::Manager > mgr(new unoidl::Manager);
+        bool entities = false;
+        rtl::Reference< unoidl::Provider > prov;
+        std::map< OUString, Item > map;
+        for (sal_uInt32 i = 0; i != args - 1; ++i) {
+            assert(args > 1);
+            OUString uri(getArgumentUri(i, i == args - 2 ? &entities : 0));
+            if (entities) {
+                mapEntities(mgr, uri, map);
+            } else {
+                try {
+                    prov = unoidl::loadProvider(mgr, uri);
+                } catch (unoidl::NoSuchFileException &) {
+                    std::cerr
+                        << "Input <" << uri << "> does not exist" << std::endl;
+                    std::exit(EXIT_FAILURE);
+                }
+                mgr->addProvider(prov);
+            }
+        }
+        if (!entities) {
+            mapCursor(
+                (prov.is()
+                 ? prov->createRootCursor()
+                 : rtl::Reference< unoidl::MapCursor >()),
+                map);
+        }
+        osl::File f(getArgumentUri(args - 1, 0));
+        osl::FileBase::RC e = f.open(osl_File_OpenFlag_Write);
+        if (e == osl::FileBase::E_NOENT) {
+            e = f.open(osl_File_OpenFlag_Write | osl_File_OpenFlag_Create);
+        }
+        if (e != osl::FileBase::E_None) {
+            std::cerr
+                << "Cannot open <" << f.getURL() << "> for writing, error code "
+                << +e << std::endl;
+            std::exit(EXIT_FAILURE);
+        }
+        write(f, "UNOIDL\xFF\0", 8);
+        write32(f, 0); // root map offset
+        write32(f, 0); // root map size
+        write(
+            f,
+            RTL_CONSTASCII_STRINGPARAM(
+                "\0** Created by LibreOffice " LIBO_VERSION_DOTTED
+                " unoidl-write **\0"));
+        std::size_t size;
+        sal_uInt64 off = writeMap(f, map, &size);
+        e = f.setSize(getOffset(f)); // truncate in case it already existed
+        if (e != osl::FileBase::E_None) {
+            std::cerr
+                << "Cannot set size of <" << f.getURL() << ">, error code "
+                << +e << std::endl;
+            std::exit(EXIT_FAILURE);
+        }
+        e = f.setPos(osl_Pos_Absolut, 8);
+        if (e != osl::FileBase::E_None) {
+            std::cerr
+                << "Cannot rewind current position in <" << f.getURL()
+                << ">, error code " << +e << std::endl;
+            std::exit(EXIT_FAILURE);
+        }
+        write32(f, off);
+        write32(f, size);
+            // overflow from std::map::size_type -> sal_uInt64 is unrealistic
+        e = f.close();
+        if (e != osl::FileBase::E_None) {
+            std::cerr
+                << "Cannot close <" << f.getURL()
+                << "> after writing, error code " << +e << std::endl;
+            std::exit(EXIT_FAILURE);
+        }
+        return EXIT_SUCCESS;
     } catch (unoidl::FileFormatException & e1) {
         std::cerr
             << "Bad input <" << e1.getUri() << ">: " << e1.getDetail()
             << std::endl;
         std::exit(EXIT_FAILURE);
     }
-    e = f.setSize(getOffset(f)); // truncate in case it already existed
-    if (e != osl::FileBase::E_None) {
-        std::cerr
-            << "Cannot set size of <" << f.getURL() << ">, error code " << +e
-            << std::endl;
-        std::exit(EXIT_FAILURE);
-    }
-    e = f.setPos(osl_Pos_Absolut, 8);
-    if (e != osl::FileBase::E_None) {
-        std::cerr
-            << "Cannot rewind current position in <" << f.getURL()
-            << ">, error code " << +e << std::endl;
-        std::exit(EXIT_FAILURE);
-    }
-    write32(f, off);
-    write32(f, size);
-        // overflow from std::map::size_type -> sal_uInt64 is unrealistic
-    e = f.close();
-    if (e != osl::FileBase::E_None) {
-        std::cerr
-            << "Cannot close <" << f.getURL() << "> after writing, error code "
-            << +e << std::endl;
-        std::exit(EXIT_FAILURE);
-    }
-    return EXIT_SUCCESS;
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */


More information about the Libreoffice-commits mailing list