LSST Applications g063fba187b+fee0456c91,g0f08755f38+ea96e5a5a3,g1653933729+a8ce1bb630,g168dd56ebc+a8ce1bb630,g1a2382251a+90257ff92a,g20f6ffc8e0+ea96e5a5a3,g217e2c1bcf+937a289c59,g28da252d5a+daa7da44eb,g2bbee38e9b+253935c60e,g2bc492864f+253935c60e,g3156d2b45e+6e55a43351,g32e5bea42b+31359a2a7a,g347aa1857d+253935c60e,g35bb328faa+a8ce1bb630,g3a166c0a6a+253935c60e,g3b1af351f3+a8ce1bb630,g3e281a1b8c+c5dd892a6c,g414038480c+416496e02f,g41af890bb2+afe91b1188,g599934f4f4+0db33f7991,g7af13505b9+e36de7bce6,g80478fca09+da231ba887,g82479be7b0+a4516e59e3,g858d7b2824+ea96e5a5a3,g89c8672015+f4add4ffd5,g9125e01d80+a8ce1bb630,ga5288a1d22+bc6ab8dfbd,gb58c049af0+d64f4d3760,gc28159a63d+253935c60e,gcab2d0539d+3f2b72788c,gcf0d15dbbd+4ea9c45075,gda6a2b7d83+4ea9c45075,gdaeeff99f8+1711a396fd,ge79ae78c31+253935c60e,gef2f8181fd+3031e3cf99,gf0baf85859+c1f95f4921,gfa517265be+ea96e5a5a3,gfa999e8aa5+17cd334064,w.2024.50
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)