From c6c58ab99ffb8e0763c532dc9970e3eba2646097 Mon Sep 17 00:00:00 2001 From: Axel Naumann <Axel.Naumann@cern.ch> Date: Fri, 18 Jan 2008 08:46:25 +0000 Subject: [PATCH] From Hady Zalek: I've encountered several compilation and runtime errors when trying to port Reflex to Solaris and AIX: AIX -- CC 5.8: - Compilation fails under xlC with the following error: "DictionaryGenerator.cxx", line 42.16: 1540-0432 (S) The qualified declarator "ROOT::Reflex::operator<<" must refer to an existing declaration. - Infinite loop on Reflex initialization due to incorrect map compare functions for 'string ' and 'const char ' Solaris -- xlC V8.0: - Infinite loop on Reflex initialization due to incorrect map compare functions for 'string ' and 'const char ' - Segmentation fault due to incorrect buffer allocation with 'new char(buffer)' instead of 'new char[buffer]' in 'Tools.cxx':Demangle Please find the first attached patch to correct the above issues... The remaining patches are for a rewrite of Tools::NormalizeName to account for the mentioned platforms and make the demangling tests pass. I also took the freedom of adding an overloaded version in Tools.h that receives a 'const char *' parameter instead of a 'const std::string &'. The patch contains test cases for inclusion in test_ReflexBuilder_unit.cxx. git-svn-id: http://root.cern.ch/svn/root/trunk@21765 27541ba8-7e3a-0410-8455-c3a389f83636 --- reflex/inc/Reflex/DictionaryGenerator.h | 4 + reflex/inc/Reflex/Tools.h | 3 + reflex/src/Tools.cxx | 117 +++++++----------------- reflex/src/stl_hash.h | 40 ++++++++ reflex/test/test_ReflexBuilder_unit.cxx | 51 +++++++++++ 5 files changed, 133 insertions(+), 82 deletions(-) diff --git a/reflex/inc/Reflex/DictionaryGenerator.h b/reflex/inc/Reflex/DictionaryGenerator.h index f89708d9d4b..4778a96dace 100644 --- a/reflex/inc/Reflex/DictionaryGenerator.h +++ b/reflex/inc/Reflex/DictionaryGenerator.h @@ -304,6 +304,10 @@ namespace ROOT }; // class DictionaryGenerator + /** stream operator */ + std::ostream & operator << ( std::ostream & s, + const DictionaryGenerator & obj ); + } // namespace Reflex } // namespace ROOT diff --git a/reflex/inc/Reflex/Tools.h b/reflex/inc/Reflex/Tools.h index 713636049d3..7fa9d7d4456 100644 --- a/reflex/inc/Reflex/Tools.h +++ b/reflex/inc/Reflex/Tools.h @@ -165,6 +165,9 @@ namespace ROOT { RFLX_API std::string NormalizeName( const std::string & name ); + + RFLX_API std::string NormalizeName( const char * name ); + /** * MakeVector is a utility function to create and initialize a std::vector of diff --git a/reflex/src/Tools.cxx b/reflex/src/Tools.cxx index d9a21697b47..5a286e9b193 100644 --- a/reflex/src/Tools.cxx +++ b/reflex/src/Tools.cxx @@ -388,25 +388,29 @@ std::string Tools::Demangle( const std::type_info & ti ) { #elif defined(__SUNPRO_CC) - std::string mangled = ti.name(); + const char* mangled = ti.name(); size_t buffer = 1024; - char * c_demangled = new char(buffer); - int ret = cplus_demangle( mangled.c_str(), c_demangled, buffer); + char * c_demangled = new char[buffer]; + int ret = cplus_demangle( mangled, c_demangled, buffer); while ( ret == -1 ) { buffer = buffer*2; - delete c_demangled; - c_demangled = new char(buffer); - ret = cplus_demangle( mangled.c_str(), c_demangled, buffer); + delete[] c_demangled; + c_demangled = new char[buffer]; + ret = cplus_demangle( mangled, c_demangled, buffer); } if ( ret == 1 ) { throw RuntimeError(std::string("Symbol ") + mangled + " not mangled correctly"); } else { - std::string demangled = c_demangled; - delete c_demangled; + std::string demangled = Tools::NormalizeName(c_demangled); + delete[] c_demangled; return demangled; } +#elif defined(__IBMCPP__) + + return Tools::NormalizeName(ti.name()); + #endif return ""; } @@ -476,84 +480,33 @@ bool isalphanum(int i) { //------------------------------------------------------------------------------- -std::string Tools::NormalizeName( const std::string & nam ) { +std::string Tools::NormalizeName( const char * nam ) { //------------------------------------------------------------------------------- // Normalize a type name. - std::string norm_name = ""; - //char lchar = ' '; - unsigned int nlen = nam.length(); - unsigned int par = 0; - bool first_word = true; - char cprev = ' '; - char cnext = ' '; - - for (unsigned int i = 0; i < nlen; ++i ) { - - switch (nam[i]) { - - case ' ': - // are we at the beginning of the name - //bool fist_pos = i ? false : true; - - // consume all spaces - while (i < nlen && nam[i+1] == ' ') ++i; - - // if only white spaces at the beginning break or - // spaces at the end of the name then break - if ( first_word || ( i = nlen -1) ) break; - - // if the last pos and the next pos is char - // or we are at the closing of angular braces - // then insert a space and the next position - cprev = nam[i-1]; - cnext = nam[i+1]; - if ( ( isalphanum(cprev) && isalpha(cnext) ) || - ( cprev == '>' && cnext == '>' ) ) norm_name += ' ' + nam[i+1]; - // otherwise only add the next pos - else norm_name += nam[i+1]; - // increase counter by consumed pos - ++i; - break; - - case '(': - case '<': - ++par; - norm_name += nam[i]; - ++i; - break; - - case ')': - case '>': - --par; - norm_name += nam[i]; - ++i; - break; - - case '*': - case '&': - first_word = false; - norm_name += nam[i]; - ++i; - break; - - case 'c': - norm_name += nam[i]; - ++i; - break; - - case 'v': - norm_name += nam[i]; - ++i; - break; - - default: - norm_name += nam[i]; - ++i; - break; - + std::string norm_name; + char prev = 0; + for (size_t i = 0; nam[i] != 0; i++) { + char curr = nam[i]; + if (curr == ' ') { + char next = 0; + while (nam[i] != 0 && (next = nam[i + 1]) == ' ') { + ++i; + } + if (!isalphanum(prev) || !isalpha(next)) { + continue; // continue on non-word boundaries + } + } else if (curr == '>' && prev == '>' || curr == '(' && prev != ')') { + norm_name += ' '; } - + norm_name += (prev = curr); } return norm_name; } + + +//------------------------------------------------------------------------------- +std::string Tools::NormalizeName( const std::string & nam ) { +//------------------------------------------------------------------------------- + return Tools::NormalizeName(nam.c_str()); +} diff --git a/reflex/src/stl_hash.h b/reflex/src/stl_hash.h index a6c70d5e758..e40feef4284 100644 --- a/reflex/src/stl_hash.h +++ b/reflex/src/stl_hash.h @@ -125,4 +125,44 @@ namespace std { #endif // __GNUC__ + + +#if defined(__SUNPRO_CC) + +namespace __gnu_cxx { + + template<> struct less<const char *> { + typedef const char* Key; + bool operator() (Key& k1, Key& k2) const { return strcmp(k1, k2) < 0; } + }; + + template<> struct less<const std::string *> { + typedef const std::string* Key; + bool operator() (Key& k1, Key& k2) const { return *k1 < *k2; } + }; + +} // namespace __gnu_cxx + +#endif // __SUNPRO_CC + + + +#if defined(_AIX) + +namespace __gnu_cxx { + + template<> struct less<const char *> { + typedef const char* Key; + bool operator() (Key k1, Key k2) const { return strcmp(k1, k2) < 0; } + }; + + template<> struct less<const std::string *> { + typedef const std::string* Key; + bool operator() (Key k1, Key k2) const { return *k1 < *k2; } + }; + +} // namespace __gnu_cxx + +#endif // _AIX + #endif // __GNU_CXX_HASH_H diff --git a/reflex/test/test_ReflexBuilder_unit.cxx b/reflex/test/test_ReflexBuilder_unit.cxx index c73b15de0f0..de0b8f5a361 100644 --- a/reflex/test/test_ReflexBuilder_unit.cxx +++ b/reflex/test/test_ReflexBuilder_unit.cxx @@ -46,6 +46,7 @@ class ReflexBuilderUnitTest : public CppUnit::TestFixture { CPPUNIT_TEST( freefunctionbuilder ); CPPUNIT_TEST( freevariablebuilder ); CPPUNIT_TEST( demangler ); + CPPUNIT_TEST( normalizer ); CPPUNIT_TEST( forwarddeclarations ); CPPUNIT_TEST( subscopebuilder ); CPPUNIT_TEST( type_equivalence ); @@ -72,6 +73,7 @@ public: void freefunctionbuilder(); void freevariablebuilder(); void demangler(); + void normalizer(); void forwarddeclarations(); void subscopebuilder(); void offset(); @@ -134,6 +136,55 @@ void ReflexBuilderUnitTest::demangler() Tools::Demangle(typeid(vector<bar>))); } +//============================================================================================== +// Normalize test +//============================================================================================== +void ReflexBuilderUnitTest::normalizer() +{ + CPPUNIT_ASSERT_EQUAL(string(""), Tools::NormalizeName("")); + CPPUNIT_ASSERT_EQUAL(string(""), Tools::NormalizeName(" ")); + CPPUNIT_ASSERT_EQUAL(string(""), Tools::NormalizeName(" ")); + CPPUNIT_ASSERT_EQUAL(string("x"), Tools::NormalizeName("x")); + CPPUNIT_ASSERT_EQUAL(string("x"), Tools::NormalizeName(" x")); + CPPUNIT_ASSERT_EQUAL(string("int"), Tools::NormalizeName("int")); + CPPUNIT_ASSERT_EQUAL(string("int"), Tools::NormalizeName(" int")); + CPPUNIT_ASSERT_EQUAL(string("int"), Tools::NormalizeName("int ")); + CPPUNIT_ASSERT_EQUAL(string("int*"), Tools::NormalizeName("int *")); + CPPUNIT_ASSERT_EQUAL(string("int**"), Tools::NormalizeName("int **")); + CPPUNIT_ASSERT_EQUAL(string("int**"), Tools::NormalizeName("int ** ")); + CPPUNIT_ASSERT_EQUAL(string("int*&"), Tools::NormalizeName("int *&")); + CPPUNIT_ASSERT_EQUAL(string("float (int)"), Tools::NormalizeName("float (int)")); + CPPUNIT_ASSERT_EQUAL(string("float* (int)"), Tools::NormalizeName("float *(int)")); + CPPUNIT_ASSERT_EQUAL(string("float* (int)"), Tools::NormalizeName("float * (int)")); + CPPUNIT_ASSERT_EQUAL(string("float* (int)"), Tools::NormalizeName("float*(int)")); + CPPUNIT_ASSERT_EQUAL(string("float** (int)"), Tools::NormalizeName("float **(int)")); + CPPUNIT_ASSERT_EQUAL(string("float*& (int)"), Tools::NormalizeName("float *&(int)")); + CPPUNIT_ASSERT_EQUAL(string("float*& (int)"), Tools::NormalizeName("float * & (int)")); + CPPUNIT_ASSERT_EQUAL(string("float*& (int)"), Tools::NormalizeName("float * & (int)")); + CPPUNIT_ASSERT_EQUAL(string("float**& (int)"), Tools::NormalizeName("float **&(int)")); + CPPUNIT_ASSERT_EQUAL(string("float (*)(int)"), Tools::NormalizeName("float (*)(int)")); + CPPUNIT_ASSERT_EQUAL(string("float (*)(int)"), Tools::NormalizeName("float(*)(int)")); + CPPUNIT_ASSERT_EQUAL(string("float (*)(int)"), Tools::NormalizeName(" float ( * ) ( int ) ")); + CPPUNIT_ASSERT_EQUAL(string("float& (*)(int)"), Tools::NormalizeName("float& (*)(int)")); + CPPUNIT_ASSERT_EQUAL(string("float**& (*)(int)"), Tools::NormalizeName("float**& (*)(int)")); + CPPUNIT_ASSERT_EQUAL(string("a::b"), Tools::NormalizeName("a::b")); + CPPUNIT_ASSERT_EQUAL(string("std::vector<bar,std::allocator<bar> >"), Tools::NormalizeName("std::vector<bar,std::allocator<bar> >")); + CPPUNIT_ASSERT_EQUAL(string("std::vector<bar,std::allocator<bar> >"), Tools::NormalizeName("std::vector<bar, std::allocator<bar>>")); + CPPUNIT_ASSERT_EQUAL(string("std::vector<bar,std::vector<bar,std::allocator<bar> > >"), Tools::NormalizeName("std::vector<bar, std::vector<bar, std::allocator<bar>>>")); + CPPUNIT_ASSERT_EQUAL(string("float ()(int)"), Tools::NormalizeName("float ()(int)")); + CPPUNIT_ASSERT_EQUAL(string("float ()(int)"), Tools::NormalizeName("float ( )( int)")); + CPPUNIT_ASSERT_EQUAL(string("float ()(int)"), Tools::NormalizeName("float ( )( int)")); + CPPUNIT_ASSERT_EQUAL(string("float* ()(int)"), Tools::NormalizeName("float* ()(int)")); + CPPUNIT_ASSERT_EQUAL(string("float* ()(int)"), Tools::NormalizeName("float * () (int)")); + CPPUNIT_ASSERT_EQUAL(string("float* ()(int)"), Tools::NormalizeName("float* ( ) (int)")); + CPPUNIT_ASSERT_EQUAL(string("float* ()(int)"), Tools::NormalizeName("float * ( ) ( int )")); + CPPUNIT_ASSERT_EQUAL(string("unsigned int"), Tools::NormalizeName("unsigned int")); + CPPUNIT_ASSERT_EQUAL(string("unsigned int"), Tools::NormalizeName("unsigned int")); + CPPUNIT_ASSERT_EQUAL(string("unsigned int"), Tools::NormalizeName(" unsigned int ")); + CPPUNIT_ASSERT_EQUAL(string("const char*"), Tools::NormalizeName(" const char *")); + CPPUNIT_ASSERT_EQUAL(string("volatile const char*"), Tools::NormalizeName(" volatile const char *")); +} + //============================================================================================== // Class Building test //============================================================================================== -- GitLab