lsst.cpputils
g87389fa792+0bb42a27e1
Toggle main menu visibility
Loading...
Searching...
No Matches
src
Demangle.cc
Go to the documentation of this file.
1
/*
2
* LSST Data Management System
3
* Copyright 2008, 2009, 2010 LSST Corporation.
4
*
5
* This product includes software developed by the
6
* LSST Project (http://www.lsst.org/).
7
*
8
* This program is free software: you can redistribute it and/or modify
9
* it under the terms of the GNU General Public License as published by
10
* the Free Software Foundation, either version 3 of the License, or
11
* (at your option) any later version.
12
*
13
* This program is distributed in the hope that it will be useful,
14
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
* GNU General Public License for more details.
17
*
18
* You should have received a copy of the LSST License Statement and
19
* the GNU General Public License along with this program. If not,
20
* see <http://www.lsstcorp.org/LegalNotices/>.
21
*/
22
23
#include "
lsst/cpputils/Demangle.h
"
24
25
#include <iostream>
26
#include <string>
27
#include <stack>
28
#include <boost/format.hpp>
29
#include <boost/multi_index_container.hpp>
30
#include <boost/multi_index/sequenced_index.hpp>
31
#include <boost/multi_index/ordered_index.hpp>
32
#include <boost/multi_index/member.hpp>
33
34
namespace
lsst
{
35
namespace
cpputils
{
36
/*
37
* Provide a symbol table for "substitutions" while mangling
38
*/
39
using
boost::multi_index_container;
40
using namespace
boost::multi_index;
41
42
class
Symbol
{
43
public
:
44
int
n
;
// index of substitution
45
std::string
key
;
// key to saved string
46
47
Symbol
(
std::string
key
) :
n
(n_next++),
key
(
key
) { }
48
~Symbol
() {}
49
50
static
void
reset
() { n_next = 0; }
// reset counter
51
52
void
print
()
const
{
53
std::cout
<<
'\t'
<<
n
<<
" "
<<
key
<<
'\n'
;
54
}
55
private
:
56
static
int
n_next;
// the next value of n
57
};
58
59
/*
60
* Tags for indices
61
*/
62
struct
n
{};
// lookup by n
63
struct
key
{};
// lookup by key
64
65
int
Symbol::n_next = 0;
// unique ID for each symbol
66
84
static
bool
interpret_typeletter(
const
char
c,
std::string
&type) {
85
switch
(c) {
86
case
'v'
: type =
"void"
;
return
true
;
87
case
'w'
: type =
"wchar_t"
;
return
true
;
88
case
'b'
: type =
"bool"
;
return
true
;
89
case
'c'
: type =
"char"
;
return
true
;
90
case
'a'
: type =
"schar"
;
return
true
;
91
case
'h'
: type =
"uchar"
;
return
true
;
92
case
's'
: type =
"short"
;
return
true
;
93
case
't'
: type =
"ushort"
;
return
true
;
94
case
'i'
: type =
"int"
;
return
true
;
95
case
'j'
: type =
"uint"
;
return
true
;
96
case
'l'
: type =
"long"
;
return
true
;
97
case
'm'
: type =
"ulong"
;
return
true
;
98
case
'x'
: type =
"long long"
;
return
true
;
99
case
'y'
: type =
"ulong long"
;
return
true
;
100
case
'n'
: type =
"__int128"
;
return
true
;
101
case
'o'
: type =
"__uint128"
;
return
true
;
102
case
'f'
: type =
"float"
;
return
true
;
103
case
'd'
: type =
"double"
;
return
true
;
104
case
'e'
: type =
"long double"
;
return
true
;
105
case
'g'
: type =
"__float128"
;
return
true
;
106
case
'z'
: type =
"..."
;
return
true
;
107
case
'u'
: type =
"vendor extended type"
;
return
true
;
108
default
:
return
false
;
109
}
110
}
111
112
113
std::string
demangleType
(
std::string
const
_typeName) {
114
#if 1
115
typedef
multi_index_container<
116
Symbol
,
117
indexed_by<
118
ordered_unique<tag<n>,
119
member<Symbol, int, &Symbol::n> >,
120
ordered_unique<tag<key>,
121
member<Symbol, std::string, &Symbol::key> >
122
>
123
> SymbolTable;
124
typedef
SymbolTable::index<n>::type::iterator nIterator;
125
typedef
SymbolTable::index<key>::type::iterator keyIterator;
126
Symbol::reset
();
127
128
// Here's my symbol table and its indices
129
SymbolTable st;
130
131
SymbolTable::index<n>::type &nIndex = st.get<
n
>();
132
SymbolTable::index<key>::type &keyIndex = st.get<
key
>();
133
//
134
// Start mangling
135
//
136
std::string
typeName(
""
);
137
const
char
*ptr = _typeName.
c_str
();
138
139
if
(*ptr ==
'r'
|| *ptr ==
'V'
|| *ptr ==
'K'
) {
140
ptr++;
// (restrict/volatile/const)
141
}
142
143
if
(*ptr ==
'P'
) ptr++;
// We passed "this" which is (type *)
144
145
std::string
currentSymbol =
""
;
// Current symbol
146
std::stack<char>
typeStack;
// Did we last see an N or an I?
147
148
int
lastTokenWasType = 0;
// When > 0, the last token was a type such as int or float
149
while
(*ptr !=
'\0'
) {
150
lastTokenWasType--;
151
switch
(*ptr) {
152
case
'E'
:
153
ptr++;
154
currentSymbol =
""
;
155
156
if
(typeStack.
empty
()) {
157
typeStack.
push
(
'\a'
);
// at least don't crash
158
}
159
160
if
(typeStack.
top
() ==
'I'
) {
161
typeName +=
'>'
;
162
}
else
if
(typeStack.
top
() ==
'L'
) {
163
;
164
}
else
if
(typeStack.
top
() ==
'N'
) {
165
;
166
}
167
typeStack.
pop
();
168
169
if
(!typeStack.
empty
() && typeStack.
top
() ==
'I'
) {
170
if
(*ptr !=
'E'
&& typeName[typeName.size() - 1] !=
'<'
) {
171
typeName +=
','
;
172
}
173
}
174
175
break
;
176
case
'I'
:
177
typeStack.
push
(*ptr++);
178
currentSymbol =
""
;
179
180
typeName +=
'<'
;
181
break
;
182
case
'L'
:
183
typeStack.
push
(*ptr++);
184
currentSymbol =
""
;
185
{
186
std::string
type;
187
if
(interpret_typeletter(*ptr, type)) {
188
typeName +=
"("
+ type +
')'
;
189
}
else
{
190
typeName +=
'c'
;
191
}
192
ptr++;
193
}
194
if
(*ptr ==
'n'
) {
195
typeName +=
'-'
; ptr++;
196
}
197
while
(*ptr !=
'\0'
&& *ptr !=
'E'
) {
198
typeName += *ptr++;
199
}
200
break
;
201
case
'N'
:
202
typeStack.
push
(*ptr++);
203
currentSymbol =
""
;
204
break
;
205
case
'S'
:
206
++ptr;
207
switch
(*ptr) {
208
case
't'
: typeName +=
"::std::"
;
break
;
209
case
'a'
: typeName +=
"::std::allocator"
;
break
;
210
case
'b'
: typeName +=
"::std::basic_string"
;
break
;
211
case
's'
: typeName +=
"::std::basic_string<char,::std::char_traits<char>,::std::allocator<char>>"
;
break
;
212
case
'i'
: typeName +=
"::std::basic_istream<char, std::char_traits<char> >"
;
break
;
213
case
'o'
: typeName +=
"::std::basic_ostream<char,std::char_traits<char>>"
;
break
;
214
case
'd'
: typeName +=
"::std::basic_iostream<char,std::char_traits<char>>"
;
break
;
215
default
:
216
{
217
int
subst = 0;
// number of substitution
218
219
if
(*ptr ==
'_'
) {
220
;
// S_ => 0
221
}
else
if
(isdigit(*ptr) || isupper(*ptr)) {
222
while
(isdigit(*ptr) || isupper(*ptr)) {
223
if
(isdigit(*ptr)) {
224
subst = 36*subst + (*ptr -
'0'
);
225
}
else
{
226
subst = 36*subst + 10 + (*ptr -
'A'
);
227
}
228
ptr++;
229
}
230
subst++;
// S_ == 0; S1_ == 1
231
assert (*ptr ==
'_'
);
232
ptr++;
233
}
234
235
nIterator sym = nIndex.find(subst);
236
if
(sym == nIndex.end()) {
// not found
237
typeName += (boost::format(
"[S%d]"
) % subst).str();
238
}
else
{
239
typeName += sym->key;
240
}
241
242
}
243
break
;
244
}
245
currentSymbol =
""
;
246
break
;
247
case
'0'
:
case
'1'
:
case
'2'
:
case
'3'
:
case
'4'
:
248
case
'5'
:
case
'6'
:
case
'7'
:
case
'8'
:
case
'9'
:
249
{
250
const
int
len = atoi(ptr++);
251
while
(isdigit(*ptr)) ptr++;
252
253
std::string
name =
""
;
254
for
(
int
i = 0; *ptr !=
'\0'
&& i < len; i++) {
255
name += *ptr++;
256
}
257
258
if
(currentSymbol !=
""
) {
259
currentSymbol +=
"::"
;
260
typeName +=
"::"
;
261
}
262
263
currentSymbol += name;
264
typeName += name;
265
266
if
(keyIndex.find(currentSymbol) == keyIndex.end()) {
267
st.insert(currentSymbol);
268
}
269
}
270
break
;
271
default
:
272
{
273
std::string
type;
274
if
(interpret_typeletter(*ptr, type)) {
275
if
(lastTokenWasType > 0) {
276
typeName +=
","
;
277
}
278
typeName += type;
279
lastTokenWasType = 2;
// it'll be decremented on every char in the name
280
}
else
{
281
typeName += *ptr;
282
}
283
ptr++;
284
}
285
}
286
}
287
288
static
volatile
bool
dumpSymbolTable =
false
;
// can be set from gdb
289
if
(dumpSymbolTable) {
290
// The test on the iterator is paranoid, but they _could_
291
// have deleted elements. In this case, they didn't.
292
for
(
unsigned
int
i = 0; i < st.size(); i++) {
293
nIterator el = nIndex.find(2);
294
if
(el != nIndex.end()) {
// did we find it?
295
el->print();
296
}
297
}
298
}
299
300
return
typeName;
301
#else
302
return
_typeName;
303
#endif
304
}
305
306
}}
// namespace lsst::cpputils
Demangle.h
std::cout
std::string
std::string::c_str
T c_str(T... args)
lsst::cpputils::Symbol
Definition
Demangle.cc:42
lsst::cpputils::Symbol::Symbol
Symbol(std::string key)
Definition
Demangle.cc:47
lsst::cpputils::Symbol::print
void print() const
Definition
Demangle.cc:52
lsst::cpputils::Symbol::n
int n
Definition
Demangle.cc:44
lsst::cpputils::Symbol::key
std::string key
Definition
Demangle.cc:45
lsst::cpputils::Symbol::~Symbol
~Symbol()
Definition
Demangle.cc:48
lsst::cpputils::Symbol::reset
static void reset()
Definition
Demangle.cc:50
std::stack::empty
T empty(T... args)
lsst::cpputils
Definition
main.dox:1
lsst::cpputils::demangleType
std::string demangleType(std::string const _typeName)
Definition
Demangle.cc:113
lsst
std::stack::pop
T pop(T... args)
std::stack::push
T push(T... args)
std::stack
lsst::cpputils::key
Definition
Demangle.cc:63
lsst::cpputils::n
Definition
Demangle.cc:62
std::stack::top
T top(T... args)
Generated on
for lsst.cpputils by
1.17.0