'PBD::demangle()' - Minor modification to keep MSVC happy
[ardour.git] / libs / pbd / stacktrace.cc
1 /*
2     Copyright (C) 2000-2007 Paul Davis 
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 #include "libpbd-config.h"
21
22 #include "pbd/stacktrace.h"
23 #include <cstdio>
24 #include <iostream>
25 #include <string>
26
27 void
28 PBD::trace_twb ()
29 {
30 }
31
32 /* Obtain a backtrace and print it to stdout. */
33
34 #ifdef HAVE_EXECINFO
35
36 #include <execinfo.h>
37 #include <cxxabi.h>
38
39 static std::string 
40 symbol_demangle (const std::string& l)
41 {
42         int status;
43
44         try {
45                 
46                 char* realname = abi::__cxa_demangle (l.c_str(), 0, 0, &status);
47                 std::string d (realname);
48                 free (realname);
49                 return d;
50         } catch (std::exception) {
51                 
52         }
53
54         return l;
55 }
56
57 std::string 
58 PBD::demangle (std::string const & l)
59 {
60         std::string::size_type const b = l.find_first_of ("(");
61
62         if (b == std::string::npos) {
63                 return symbol_demangle (l);
64         }
65
66         std::string::size_type const p = l.find_last_of ("+");
67         if (p == std::string::npos) {
68                 return symbol_demangle (l);
69         }
70
71         if ((p - b) <= 1) {
72                 return symbol_demangle (l);
73         }
74         
75         std::string const fn = l.substr (b + 1, p - b - 1);
76
77         return symbol_demangle (fn);
78 }
79
80 void
81 PBD::stacktrace (std::ostream& out, int levels)
82 {
83         void *array[200];
84         size_t size;
85         char **strings;
86         size_t i;
87      
88         size = backtrace (array, 200);
89
90         if (size) {
91                 strings = backtrace_symbols (array, size);
92      
93                 if (strings) {
94                         
95                         for (i = 0; i < size && (levels == 0 || i < size_t(levels)); i++) {
96                                 out << "  " << demangle (strings[i]) << std::endl;
97                         }
98                         
99                         free (strings);
100                 }
101         } else {
102                 out << "no stacktrace available!" << std::endl;
103         }
104 }
105
106 #else
107
108 std::string 
109 PBD::demangle (std::string const & l)
110 {
111         std::string empty_string;
112         return empty_string;
113 }
114
115 void
116 PBD::stacktrace (std::ostream& out, int /*levels*/)
117 {
118         out << "stack tracing is not enabled on this platform" << std::endl;
119 }
120
121 void
122 c_stacktrace ()
123 {
124         PBD::stacktrace (std::cout);
125 }
126
127 #endif /* HAVE_EXECINFO */