Use enum for exec stderr parameter (1/2)
[ardour.git] / libs / pbd / debug.cc
1 /*
2     Copyright (C) 2009 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 <cstring>
21 #include <cstdlib>
22 #include <iostream>
23 #include <map>
24 #include <vector>
25 #include <algorithm>
26
27 #include <boost/tokenizer.hpp>
28
29 #include "pbd/debug.h"
30
31 #include "pbd/i18n.h"
32
33 using namespace std;
34 using PBD::DebugBits;
35
36 static uint64_t _debug_bit = 0;
37
38 typedef std::map<const char*,DebugBits> DebugMap;
39
40 namespace PBD {
41         DebugMap & _debug_bit_map()
42         {
43                 static DebugMap map;
44                 return map;
45         }
46 }
47
48 DebugBits PBD::DEBUG::Stateful = PBD::new_debug_bit ("stateful");
49 DebugBits PBD::DEBUG::Properties = PBD::new_debug_bit ("properties");
50 DebugBits PBD::DEBUG::FileManager = PBD::new_debug_bit ("filemanager");
51 DebugBits PBD::DEBUG::Pool = PBD::new_debug_bit ("pool");
52 DebugBits PBD::DEBUG::EventLoop = PBD::new_debug_bit ("eventloop");
53 DebugBits PBD::DEBUG::AbstractUI = PBD::new_debug_bit ("abstractui");
54 DebugBits PBD::DEBUG::FileUtils = PBD::new_debug_bit ("fileutils");
55 DebugBits PBD::DEBUG::Configuration = PBD::new_debug_bit ("configuration");
56 DebugBits PBD::DEBUG::UndoHistory = PBD::new_debug_bit ("undohistory");
57 DebugBits PBD::DEBUG::Timing = PBD::new_debug_bit ("timing");
58 DebugBits PBD::DEBUG::Threads = PBD::new_debug_bit ("threads");
59 DebugBits PBD::DEBUG::Locale = PBD::new_debug_bit ("locale");
60 DebugBits PBD::DEBUG::StringConvert = PBD::new_debug_bit ("stringconvert");
61
62 /* These are debug bits that are used by backends. Since these are loaded dynamically,
63    after command-line parsing, defining them in code that is part of the backend
64    doesn't make them available for command line parsing. Put them here.
65
66    This is sort of a hack, because it means that the debug bits aren't defined
67    with the code in which they are relevant. But providing access to debug bits
68    from dynamically loaded code, for use in command line parsing, is way above the pay grade
69    of this debug tracing scheme.
70 */
71 DebugBits PBD::DEBUG::WavesMIDI = PBD::new_debug_bit ("WavesMIDI");
72 DebugBits PBD::DEBUG::WavesAudio = PBD::new_debug_bit ("WavesAudio");
73
74 DebugBits PBD::debug_bits;
75
76 DebugBits
77 PBD::new_debug_bit (const char* name)
78 {
79         DebugBits ret;
80         DebugMap::iterator i =_debug_bit_map().find (name);
81
82         if (i != _debug_bit_map().end()) {
83                 return i->second;
84         }
85
86         if (_debug_bit >= debug_bits.size()) {
87                 cerr << "Too many debug bits defined, offender was " << name << endl;
88                 abort ();
89                 /*NOTREACHED*/
90         }
91
92         ret.set (_debug_bit++, 1);
93         _debug_bit_map().insert (make_pair (name, ret));
94         return ret;
95 }
96
97 void
98 PBD::debug_print (const char* prefix, string str)
99 {
100         cout << prefix << ": " << str;
101 }
102
103 int
104 PBD::parse_debug_options (const char* str)
105 {
106         string in_str = str;
107         typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
108         boost::char_separator<char> sep (",");
109         tokenizer tokens (in_str, sep);
110         DebugBits bits;
111
112         for (tokenizer::iterator tok_iter = tokens.begin(); tok_iter != tokens.end(); ++tok_iter) {
113                 if (*tok_iter == "list") {
114                         list_debug_options ();
115                         return 1;
116                 }
117
118                 if (*tok_iter == "all") {
119                         debug_bits.set (); /* sets all bits */
120                         return 0;
121                 }
122
123                 for (map<const char*,DebugBits>::iterator i = _debug_bit_map().begin(); i != _debug_bit_map().end(); ++i) {
124                         const char* cstr = (*tok_iter).c_str();
125
126                         if (strncasecmp (cstr, i->first, strlen (cstr)) == 0) {
127                                 bits |= i->second;
128                                 cout << i->first << " set ... debug bits now set to " << bits << " using " << i->second << endl;
129                         }
130                 }
131         }
132
133         debug_bits = bits;
134
135         return 0;
136 }
137
138 void
139 PBD::list_debug_options ()
140 {
141         cout << _("The following debug options are available. Separate multiple options with commas.\nNames are case-insensitive and can be abbreviated.") << endl << endl;
142         cout << '\t' << X_("all") << endl;
143
144         vector<string> options;
145
146         for (map<const char*,DebugBits>::iterator i = _debug_bit_map().begin(); i != _debug_bit_map().end(); ++i) {
147                 options.push_back (i->first);
148         }
149
150         sort (options.begin(), options.end());
151
152         for (vector<string>::iterator i = options.begin(); i != options.end(); ++i) {
153                 cout << "\t" << (*i) << endl;
154         }
155 }