LSST Applications g180d380827+0f66a164bb,g2079a07aa2+86d27d4dc4,g2305ad1205+7d304bc7a0,g29320951ab+500695df56,g2bbee38e9b+0e5473021a,g337abbeb29+0e5473021a,g33d1c0ed96+0e5473021a,g3a166c0a6a+0e5473021a,g3ddfee87b4+e42ea45bea,g48712c4677+36a86eeaa5,g487adcacf7+2dd8f347ac,g50ff169b8f+96c6868917,g52b1c1532d+585e252eca,g591dd9f2cf+c70619cc9d,g5a732f18d5+53520f316c,g5ea96fc03c+341ea1ce94,g64a986408d+f7cd9c7162,g858d7b2824+f7cd9c7162,g8a8a8dda67+585e252eca,g99cad8db69+469ab8c039,g9ddcbc5298+9a081db1e4,ga1e77700b3+15fc3df1f7,gb0e22166c9+60f28cb32d,gba4ed39666+c2a2e4ac27,gbb8dafda3b+c92fc63c7e,gbd866b1f37+f7cd9c7162,gc120e1dc64+02c66aa596,gc28159a63d+0e5473021a,gc3e9b769f7+b0068a2d9f,gcf0d15dbbd+e42ea45bea,gdaeeff99f8+f9a426f77a,ge6526c86ff+84383d05b3,ge79ae78c31+0e5473021a,gee10cc3b42+585e252eca,gff1a9f87cc+f7cd9c7162,w.2024.17
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
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 find(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)