LSST Applications g0f08755f38+82efc23009,g12f32b3c4e+e7bdf1200e,g1653933729+a8ce1bb630,g1a0ca8cf93+50eff2b06f,g28da252d5a+52db39f6a5,g2bbee38e9b+37c5a29d61,g2bc492864f+37c5a29d61,g2cdde0e794+c05ff076ad,g3156d2b45e+41e33cbcdc,g347aa1857d+37c5a29d61,g35bb328faa+a8ce1bb630,g3a166c0a6a+37c5a29d61,g3e281a1b8c+fb992f5633,g414038480c+7f03dfc1b0,g41af890bb2+11b950c980,g5fbc88fb19+17cd334064,g6b1c1869cb+12dd639c9a,g781aacb6e4+a8ce1bb630,g80478fca09+72e9651da0,g82479be7b0+04c31367b4,g858d7b2824+82efc23009,g9125e01d80+a8ce1bb630,g9726552aa6+8047e3811d,ga5288a1d22+e532dc0a0b,gae0086650b+a8ce1bb630,gb58c049af0+d64f4d3760,gc28159a63d+37c5a29d61,gcf0d15dbbd+2acd6d4d48,gd7358e8bfb+778a810b6e,gda3e153d99+82efc23009,gda6a2b7d83+2acd6d4d48,gdaeeff99f8+1711a396fd,ge2409df99d+6b12de1076,ge79ae78c31+37c5a29d61,gf0baf85859+d0a5978c5a,gf3967379c6+4954f8c433,gfb92a5be7c+82efc23009,gfec2e1e490+2aaed99252,w.2024.46
LSST Data Management Base Package
Loading...
Searching...
No Matches
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
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
34namespace lsst {
35namespace cpputils {
36/*
37 * Provide a symbol table for "substitutions" while mangling
38 */
39using boost::multi_index_container;
40using namespace boost::multi_index;
41
42class Symbol {
43public:
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) { }
49
50 static void reset() { n_next = 0; } // reset counter
51
52 void print() const {
53 std::cout << '\t' << n << " " << key << '\n';
54 }
55private:
56 static int n_next; // the next value of n
57};
58
59/*
60 * Tags for indices
61 */
62struct n {}; // lookup by n
63struct key {}; // lookup by key
64
65int Symbol::n_next = 0; // unique ID for each symbol
66
84static 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
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;
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 {
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 {
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
table::Key< std::string > name
Definition Amplifier.cc:116
table::Key< int > type
Definition Detector.cc:163
std::uint64_t * ptr
Definition RangeSet.cc:95
T c_str(T... args)
Symbol(std::string key)
Definition Demangle.cc:47
void print() const
Definition Demangle.cc:52
static void reset()
Definition Demangle.cc:50
T empty(T... args)
T insert(T... args)
std::string demangleType(std::string const _typeName)
Definition Demangle.cc:113
T pop(T... args)
T push(T... args)
T top(T... args)