enough with umpteen "i18n.h" files. Consolidate on pbd/i18n.h
[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
61 /* These are debug bits that are used by backends. Since these are loaded dynamically,
62    after command-line parsing, defining them in code that is part of the backend
63    doesn't make them available for command line parsing. Put them here.
64
65    This is sort of a hack, because it means that the debug bits aren't defined
66    with the code in which they are relevant. But providing access to debug bits
67    from dynamically loaded code, for use in command line parsing, is way above the pay grade
68    of this debug tracing scheme.
69 */
70 DebugBits PBD::DEBUG::WavesMIDI = PBD::new_debug_bit ("WavesMIDI");
71 DebugBits PBD::DEBUG::WavesAudio = PBD::new_debug_bit ("WavesAudio");
72
73 DebugBits PBD::debug_bits;
74
75 DebugBits
76 PBD::new_debug_bit (const char* name)
77 {
78         DebugBits ret;
79         DebugMap::iterator i =_debug_bit_map().find (name);
80
81         if (i != _debug_bit_map().end()) {
82                 return i->second;
83         }
84
85         if (_debug_bit >= debug_bits.size()) {
86                 cerr << "Too many debug bits defined, offender was " << name << endl;
87                 abort ();
88                 /*NOTREACHED*/
89         }
90
91         ret.set (_debug_bit++, 1);
92         _debug_bit_map().insert (make_pair (name, ret));
93         return ret;
94 }
95
96 void
97 PBD::debug_print (const char* prefix, string str)
98 {
99         cout << prefix << ": " << str;
100 }
101
102 int
103 PBD::parse_debug_options (const char* str)
104 {
105         string in_str = str;
106         typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
107         boost::char_separator<char> sep (",");
108         tokenizer tokens (in_str, sep);
109         DebugBits bits;
110
111         for (tokenizer::iterator tok_iter = tokens.begin(); tok_iter != tokens.end(); ++tok_iter) {
112                 if (*tok_iter == "list") {
113                         list_debug_options ();
114                         return 1;
115                 }
116
117                 if (*tok_iter == "all") {
118                         debug_bits.set (); /* sets all bits */
119                         return 0;
120                 }
121
122                 for (map<const char*,DebugBits>::iterator i = _debug_bit_map().begin(); i != _debug_bit_map().end(); ++i) {
123                         const char* cstr = (*tok_iter).c_str();
124
125                         if (strncasecmp (cstr, i->first, strlen (cstr)) == 0) {
126                                 bits |= i->second;
127                                 cout << i->first << " set ... debug bits now set to " << bits << " using " << i->second << endl;
128                         }
129                 }
130         }
131
132         debug_bits = bits;
133
134         return 0;
135 }
136
137 void
138 PBD::list_debug_options ()
139 {
140         cout << _("The following debug options are available. Separate multiple options with commas.\nNames are case-insensitive and can be abbreviated.") << endl << endl;
141         cout << '\t' << X_("all") << endl;
142
143         vector<string> options;
144
145         for (map<const char*,DebugBits>::iterator i = _debug_bit_map().begin(); i != _debug_bit_map().end(); ++i) {
146                 options.push_back (i->first);
147         }
148
149         sort (options.begin(), options.end());
150
151         for (vector<string>::iterator i = options.begin(); i != options.end(); ++i) {
152                 cout << "\t" << (*i) << endl;
153         }
154 }