From 14236d6864fbf5ad9ff38dbd56b29f4c6101dceb Mon Sep 17 00:00:00 2001
From: Markus Frank <markus.frank@cern.ch>
Date: Wed, 25 Mar 2015 14:38:47 +0000
Subject: [PATCH] Protect against douple instantiation of static storage

---
 DDCore/include/XML/UnicodeValues.h |  2 ++
 DDCore/include/XML/XMLElements.h   |  6 ++++
 DDCore/src/XML/XMLTags.cpp         | 54 +++++++++++++++++++++---------
 3 files changed, 46 insertions(+), 16 deletions(-)

diff --git a/DDCore/include/XML/UnicodeValues.h b/DDCore/include/XML/UnicodeValues.h
index 882e98a8a..8a8bfc4c7 100644
--- a/DDCore/include/XML/UnicodeValues.h
+++ b/DDCore/include/XML/UnicodeValues.h
@@ -233,6 +233,7 @@ namespace DD4hep {
     UNICODE (name);
     UNICODE (nmodules);
     UNICODE (nModules);
+    UNICODE (normal);
     UNICODE (nonprojective_cylinder);
     UNICODE (nPads);
     UNICODE (nphi);
@@ -278,6 +279,7 @@ namespace DD4hep {
     UNICODE (physvolid);
     UNICODE (plugin);
     UNICODE (plugins);
+    UNICODE (point);
     UNICODE (polyhedra);
     UNICODE (polycone);
     UNICODE (position);
diff --git a/DDCore/include/XML/XMLElements.h b/DDCore/include/XML/XMLElements.h
index 7faaa184d..1f93556d0 100644
--- a/DDCore/include/XML/XMLElements.h
+++ b/DDCore/include/XML/XMLElements.h
@@ -249,6 +249,12 @@ namespace DD4hep {
     Tag_t(const std::string& s)
       : Strng_t(s), m_str(s) {
       }
+      /// Constructor from STL string with registration.
+      /// ONLY to be used for static global entries to protect against duplicated static memory.
+    Tag_t(const std::string& v, const std::string& s, void (*register_func)(const std::string&, Tag_t*))
+      : Strng_t(s), m_str(s) {
+	register_func(v, this);
+      }
       /// Destructor
       ~Tag_t() {
       }
diff --git a/DDCore/src/XML/XMLTags.cpp b/DDCore/src/XML/XMLTags.cpp
index 1f80738f7..3954ccdb3 100644
--- a/DDCore/src/XML/XMLTags.cpp
+++ b/DDCore/src/XML/XMLTags.cpp
@@ -1,46 +1,68 @@
+// $Id$
+//====================================================================
+//  AIDA Detector description implementation
+//--------------------------------------------------------------------
+//
+//  Author     : M.Frank
+//
+//====================================================================
+#include <stdexcept>
 #include <iostream>
+#include <map>
+
 #include "XML/XMLElements.h"
 #ifndef __TIXML__
 #include "xercesc/util/XMLString.hpp"
 #include "xercesc/util/PlatformUtils.hpp"
+#endif
 
 namespace {
   struct __Init {
+    typedef std::map<std::string,DD4hep::XML::Tag_t*> Inventory_t;
+    Inventory_t m_inventory;
     __Init() {
+#ifndef __TIXML__
       try {
         xercesc::XMLPlatformUtils::Initialize();
       }
       catch (const xercesc::XMLException& e) {
-        std::cout << "Xerces-c error in initialization:" << xercesc::XMLString::transcode(e.getMessage()) << std::endl;
+        std::string xml_err = xercesc::XMLString::transcode(e.getMessage());
+        std::string err = "xercesc::XMLPlatformUtils: Xerces-c error in initialization:"+xml_err;
+        std::cout << err << std::endl;
+	throw std::runtime_error(err);
       }
+#endif
     }
     ~__Init() {
+#ifndef __TIXML__
       xercesc::XMLPlatformUtils::Terminate();
+#endif
     }
+    static void register_tag(const std::string& name, DD4hep::XML::Tag_t* tag);
   };
   __Init  __In__;
+  void __Init::register_tag(const std::string& name, DD4hep::XML::Tag_t* tag)  {
+      Inventory_t::const_iterator i = __In__.m_inventory.find(name);
+      if ( i !=  __In__.m_inventory.end() )  {
+	std::string err = "XMLTags: Failed to register XML tag: "+name+". [Tag already exists]";
+	std::cout << err << std::endl;
+	throw std::runtime_error(err);
+      }
+      __In__.m_inventory[name] = tag;
+  }
 }
-#else
-namespace {
-  struct __Init {
-    __Init() {
-    }
-  };
-  __Init __In__;
-}
-#endif
 
-#define UNICODE(x)        extern const Tag_t Unicode_##x (#x)
+#define UNICODE(x)        extern const Tag_t Unicode_##x (#x, #x, __Init::register_tag)
 #include "XML/UnicodeValues.h"
 
 namespace DD4hep {
   namespace XML {
 
-    extern const Tag_t Unicode_NULL("0");
-    extern const Tag_t Unicode_empty("");
-    extern const Tag_t Unicode_star("*");
-    extern const Tag_t Unicode_PI("3.14159265358979323846");
-    extern const Tag_t Unicode_TWOPI("6.28318530717958647692");
+    extern const Tag_t Unicode_NULL("NULL", "0", __Init::register_tag);
+    extern const Tag_t Unicode_empty("", "", __Init::register_tag);
+    extern const Tag_t Unicode_star("star", "*", __Init::register_tag);
+    extern const Tag_t Unicode_PI("PI", "3.14159265358979323846", __Init::register_tag);
+    extern const Tag_t Unicode_TWOPI("TWOPI", "6.28318530717958647692", __Init::register_tag);
 
     void tags_init() {
       static __Init i;
-- 
GitLab