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)
5
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>
14
15 #if defined(__QNXNTO__)
16 # include <ostream>
17 #else /* defined(__QNXNTO__) */
18
19 #if !defined(__GNUC__) || __GNUC__ >= 3 || __SGI_STL_PORT || __EDG_VERSION__
20 # include <ostream>
21 #else
22 # include <ostream.h>
23 #endif
24
25 # ifdef BOOST_PYTHON_HAVE_GCC_CP_DEMANGLE
26 # if defined(__GNUC__) && __GNUC__ >= 3
27
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
34
35 # include <cxxabi.h>
36 # endif
37 # endif
38 #endif /* defined(__QNXNTO__) */
39
40 namespace boost { namespace python {
41
42 # ifdef BOOST_PYTHON_HAVE_GCC_CP_DEMANGLE
43
44 # if defined(__QNXNTO__)
45 namespace cxxabi {
46 extern "C" char* __cxa_demangle(char const*, char*, std::size_t*, int*);
47 }
48 # else /* defined(__QNXNTO__) */
49
50 # ifdef __GNUC__
51 # if __GNUC__ < 3
52
53 namespace cxxabi = :: ;
54 extern "C" char* __cxa_demangle(char const*, char*, std::size_t*, int*);
55 # else
56
57 namespace cxxabi = ::abi; // GCC 3.1 and later
58
59 # if __GNUC__ == 3 && __GNUC_MINOR__ == 0
60 namespace abi
61 {
62 extern "C" char* __cxa_demangle(char const*, char*, std::size_t*, int*);
63 }
64 # endif /* __GNUC__ == 3 && __GNUC_MINOR__ == 0 */
65 # endif /* __GNUC__ < 3 */
66 # endif /* __GNUC__ */
67 # endif /* defined(__QNXNTO__) */
68
69 namespace
70 {
71 struct compare_first_cstring
72 {
73 template <class T>
operator ()boost::python::__anon776d2ae10111::compare_first_cstring74 bool operator()(T const& x, T const& y)
75 {
76 return std::strcmp(x.first,y.first) < 0;
77 }
78 };
79
80 struct free_mem
81 {
free_memboost::python::__anon776d2ae10111::free_mem82 free_mem(char*p)
83 : p(p) {}
84
~free_memboost::python::__anon776d2ae10111::free_mem85 ~free_mem()
86 {
87 std::free(p);
88 }
89 char* p;
90 };
91 }
92
cxxabi_cxa_demangle_is_broken()93 bool cxxabi_cxa_demangle_is_broken()
94 {
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;
103 }
104 }
105 return is_broken;
106 }
107
108 namespace detail
109 {
gcc_demangle(char const * mangled)110 BOOST_PYTHON_DECL char const* gcc_demangle(char const* mangled)
111 {
112 typedef std::vector<
113 std::pair<char const*, char const*>
114 > mangling_map;
115
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());
122
123 if (p == demangler.end() || strcmp(p->first, mangled))
124 {
125 int status;
126 free_mem keeper(
127 cxxabi::__cxa_demangle(mangled, 0, 0, &status)
128 );
129
130 assert(status != -3); // invalid argument error
131
132 if (status == -1)
133 {
134 throw std::bad_alloc();
135 }
136 else
137 {
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;
144
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)
154 {
155 // list from
156 // http://www.codesourcery.com/cxx-abi/abi.html
157 switch (mangled[0])
158 {
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;
180 }
181 }
182
183 p = demangler.insert(p, std::make_pair(mangled, demangled));
184 keeper.p = 0;
185 }
186 }
187
188 return p->second;
189 }
190 }
191 # endif
192
operator <<(std::ostream & os,type_info const & x)193 BOOST_PYTHON_DECL std::ostream& operator<<(std::ostream& os, type_info const& x)
194 {
195 return os << x.name();
196 }
197
198 namespace detail
199 {
operator <<(std::ostream & os,detail::decorated_type_info const & x)200 BOOST_PYTHON_DECL std::ostream& operator<<(std::ostream& os, detail::decorated_type_info const& x)
201 {
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;
210 }
211 }
212 }} // namespace boost::python::converter
213