LSSTApplications  10.0+286,10.0+36,10.0+46,10.0-2-g4f67435,10.1+152,10.1+37,11.0,11.0+1,11.0-1-g47edd16,11.0-1-g60db491,11.0-1-g7418c06,11.0-2-g04d2804,11.0-2-g68503cd,11.0-2-g818369d,11.0-2-gb8b8ce7
LSSTDataManagementBasePackage
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/utils/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 utils {
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::utils
std::string demangleType(std::string const _typeName)
Definition: Demangle.cc:113
table::Key< std::string > name
Definition: ApCorrMap.cc:71
std::string key
Definition: Demangle.cc:45
Symbol(std::string key)
Definition: Demangle.cc:47
void print() const
Definition: Demangle.cc:52
static void reset()
Definition: Demangle.cc:50
static int n_next
Definition: Demangle.cc:56