Improve vacpp support.
[boost.git] / boost / libs / python / src / converter / type_id.cpp
blobc6a8bf7a04e7379f9d29e5ba0e3498fe4637bdd1
1 // Copyright David Abrahams 2001.
2 // Distributed under the Boost Software License, Version 1.0. (See
3 // accompanying file LICENSE_1_0.txt or copy at
4 // http://www.boost.org/LICENSE_1_0.txt)
6 #include <boost/python/type_id.hpp>
7 #include <boost/python/detail/decorated_type_id.hpp>
8 #include <utility>
9 #include <vector>
10 #include <algorithm>
11 #include <memory>
12 #include <cstdlib>
13 #include <cstring>
15 #if defined(__QNXNTO__)
16 # include <ostream>
17 #else /* defined(__QNXNTO__) */
19 #if !defined(__GNUC__) || __GNUC__ >= 3 || __SGI_STL_PORT || __EDG_VERSION__
20 # include <ostream>
21 #else
22 # include <ostream.h>
23 #endif
25 # ifdef BOOST_PYTHON_HAVE_GCC_CP_DEMANGLE
26 # if defined(__GNUC__) && __GNUC__ >= 3
28 // http://lists.debian.org/debian-gcc/2003/09/msg00055.html notes
29 // that, in cxxabi.h of gcc-3.x for x < 4, this type is used before it
30 // is declared.
31 # if __GNUC__ == 3 && __GNUC_MINOR__ < 4
32 class __class_type_info;
33 # endif
35 # include <cxxabi.h>
36 # endif
37 # endif
38 #endif /* defined(__QNXNTO__) */
40 namespace boost { namespace python {
42 # ifdef BOOST_PYTHON_HAVE_GCC_CP_DEMANGLE
44 # if defined(__QNXNTO__)
45 namespace cxxabi {
46 extern "C" char* __cxa_demangle(char const*, char*, std::size_t*, int*);
48 # else /* defined(__QNXNTO__) */
50 # ifdef __GNUC__
51 # if __GNUC__ < 3
53 namespace cxxabi = :: ;
54 extern "C" char* __cxa_demangle(char const*, char*, std::size_t*, int*);
55 # else
57 namespace cxxabi = ::abi; // GCC 3.1 and later
59 # if __GNUC__ == 3 && __GNUC_MINOR__ == 0
60 namespace abi
62 extern "C" char* __cxa_demangle(char const*, char*, std::size_t*, int*);
64 # endif /* __GNUC__ == 3 && __GNUC_MINOR__ == 0 */
65 # endif /* __GNUC__ < 3 */
66 # endif /* __GNUC__ */
67 # endif /* defined(__QNXNTO__) */
69 namespace
71 struct compare_first_cstring
73 template <class T>
74 bool operator()(T const& x, T const& y)
76 return std::strcmp(x.first,y.first) < 0;
80 struct free_mem
82 free_mem(char*p)
83 : p(p) {}
85 ~free_mem()
87 std::free(p);
89 char* p;
93 bool cxxabi_cxa_demangle_is_broken()
95 static bool was_tested = false;
96 static bool is_broken = false;
97 if (!was_tested) {
98 int status;
99 free_mem keeper(cxxabi::__cxa_demangle("b", 0, 0, &status));
100 was_tested = true;
101 if (status == -2 || strcmp(keeper.p, "bool") != 0) {
102 is_broken = true;
105 return is_broken;
108 namespace detail
110 BOOST_PYTHON_DECL char const* gcc_demangle(char const* mangled)
112 typedef std::vector<
113 std::pair<char const*, char const*>
114 > mangling_map;
116 static mangling_map demangler;
117 mangling_map::iterator p
118 = std::lower_bound(
119 demangler.begin(), demangler.end()
120 , std::make_pair(mangled, (char const*)0)
121 , compare_first_cstring());
123 if (p == demangler.end() || strcmp(p->first, mangled))
125 int status;
126 free_mem keeper(
127 cxxabi::__cxa_demangle(mangled, 0, 0, &status)
130 assert(status != -3); // invalid argument error
132 if (status == -1)
134 throw std::bad_alloc();
136 else
138 char const* demangled
139 = status == -2
140 // Invalid mangled name. Best we can do is to
141 // return it intact.
142 ? mangled
143 : keeper.p;
145 // Ult Mundane, 2005 Aug 17
146 // Contributed under the Boost Software License, Version 1.0.
147 // (See accompanying file LICENSE_1_0.txt or copy at
148 // http://www.boost.org/LICENSE_1_0.txt)
149 // The __cxa_demangle function is supposed to translate
150 // builtin types from their one-character mangled names,
151 // but it doesn't in gcc 3.3.5 and gcc 3.4.x.
152 if (cxxabi_cxa_demangle_is_broken()
153 && status == -2 && strlen(mangled) == 1)
155 // list from
156 // http://www.codesourcery.com/cxx-abi/abi.html
157 switch (mangled[0])
159 case 'v': demangled = "void"; break;
160 case 'w': demangled = "wchar_t"; break;
161 case 'b': demangled = "bool"; break;
162 case 'c': demangled = "char"; break;
163 case 'a': demangled = "signed char"; break;
164 case 'h': demangled = "unsigned char"; break;
165 case 's': demangled = "short"; break;
166 case 't': demangled = "unsigned short"; break;
167 case 'i': demangled = "int"; break;
168 case 'j': demangled = "unsigned int"; break;
169 case 'l': demangled = "long"; break;
170 case 'm': demangled = "unsigned long"; break;
171 case 'x': demangled = "long long"; break;
172 case 'y': demangled = "unsigned long long"; break;
173 case 'n': demangled = "__int128"; break;
174 case 'o': demangled = "unsigned __int128"; break;
175 case 'f': demangled = "float"; break;
176 case 'd': demangled = "double"; break;
177 case 'e': demangled = "long double"; break;
178 case 'g': demangled = "__float128"; break;
179 case 'z': demangled = "..."; break;
183 p = demangler.insert(p, std::make_pair(mangled, demangled));
184 keeper.p = 0;
188 return p->second;
191 # endif
193 BOOST_PYTHON_DECL std::ostream& operator<<(std::ostream& os, type_info const& x)
195 return os << x.name();
198 namespace detail
200 BOOST_PYTHON_DECL std::ostream& operator<<(std::ostream& os, detail::decorated_type_info const& x)
202 os << x.m_base_type;
203 if (x.m_decoration & decorated_type_info::const_)
204 os << " const";
205 if (x.m_decoration & decorated_type_info::volatile_)
206 os << " volatile";
207 if (x.m_decoration & decorated_type_info::reference)
208 os << "&";
209 return os;
212 }} // namespace boost::python::converter