1 /* ScummVM - Graphic Adventure Engine
2 *
3 * ScummVM is the legal property of its developers, whose names
4 * are too numerous to list here. Please refer to the COPYRIGHT
5 * file distributed with this source distribution.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 *
21 */
22
23 #include "common/debug.h"
24 #include "common/debug-channels.h"
25 #include "common/system.h"
26 #include "common/textconsole.h"
27 #include "common/algorithm.h"
28
29 #include <stdarg.h> // For va_list etc.
30
31 // TODO: Move gDebugLevel into namespace Common.
32 int gDebugLevel = -1;
33 bool gDebugChannelsOnly = false;
34
35 namespace Common {
36
37 DECLARE_SINGLETON(DebugManager);
38
39 namespace {
40
41 struct DebugLevelComperator {
operator ()Common::__anon05d3dd690111::DebugLevelComperator42 bool operator()(const DebugManager::DebugChannel &l, const DebugManager::DebugChannel &r) {
43 return (l.name.compareToIgnoreCase(r.name) < 0);
44 }
45 };
46
47 } // end of anonymous namespace
48
addDebugChannel(uint32 channel,const String & name,const String & description)49 bool DebugManager::addDebugChannel(uint32 channel, const String &name, const String &description) {
50 if (name.equalsIgnoreCase("all")) {
51 warning("Debug channel 'all' is reserved for internal use");
52 return false;
53 }
54
55 if (gDebugChannels.contains(name))
56 warning("Duplicate declaration of engine debug channel '%s'", name.c_str());
57
58 gDebugChannels[name] = DebugChannel(channel, name, description);
59
60 return true;
61 }
62
clearAllDebugChannels()63 void DebugManager::clearAllDebugChannels() {
64 gDebugChannelsEnabled = 0;
65 gDebugChannels.clear();
66 }
67
enableDebugChannel(const String & name)68 bool DebugManager::enableDebugChannel(const String &name) {
69 DebugChannelMap::iterator i = gDebugChannels.find(name);
70
71 if (i != gDebugChannels.end()) {
72 gDebugChannelsEnabled |= i->_value.channel;
73 i->_value.enabled = true;
74
75 return true;
76 } else {
77 return false;
78 }
79 }
80
disableDebugChannel(const String & name)81 bool DebugManager::disableDebugChannel(const String &name) {
82 DebugChannelMap::iterator i = gDebugChannels.find(name);
83
84 if (i != gDebugChannels.end()) {
85 gDebugChannelsEnabled &= ~i->_value.channel;
86 i->_value.enabled = false;
87
88 return true;
89 } else {
90 return false;
91 }
92 }
93
listDebugChannels()94 DebugManager::DebugChannelList DebugManager::listDebugChannels() {
95 DebugChannelList tmp;
96 for (DebugChannelMap::iterator i = gDebugChannels.begin(); i != gDebugChannels.end(); ++i)
97 tmp.push_back(i->_value);
98 sort(tmp.begin(), tmp.end(), DebugLevelComperator());
99
100 return tmp;
101 }
102
enableAllDebugChannels()103 void DebugManager::enableAllDebugChannels() {
104 for (DebugChannelMap::iterator i = gDebugChannels.begin(); i != gDebugChannels.end(); ++i)
105 enableDebugChannel(i->_value.name);
106 }
107
disableAllDebugChannels()108 void DebugManager::disableAllDebugChannels() {
109 for (DebugChannelMap::iterator i = gDebugChannels.begin(); i != gDebugChannels.end(); ++i)
110 disableDebugChannel(i->_value.name);
111 }
112
isDebugChannelEnabled(uint32 channel,bool enforce)113 bool DebugManager::isDebugChannelEnabled(uint32 channel, bool enforce) {
114 // Debug level 11 turns on all special debug level messages
115 if (gDebugLevel == 11 && enforce == false)
116 return true;
117 else
118 return (gDebugChannelsEnabled & channel) != 0;
119 }
120
121 } // End of namespace Common
122
debugLevelSet(int level)123 bool debugLevelSet(int level) {
124 return level <= gDebugLevel;
125 }
126
debugChannelSet(int level,uint32 debugChannels)127 bool debugChannelSet(int level, uint32 debugChannels) {
128 if (gDebugLevel != 11 || level == -1)
129 if ((level != -1 && level > gDebugLevel) || !(DebugMan.isDebugChannelEnabled(debugChannels, level == -1)))
130 return false;
131
132 return true;
133 }
134
135
136 #ifndef DISABLE_TEXT_CONSOLE
137
debugHelper(const char * s,va_list va,bool caret=true)138 static void debugHelper(const char *s, va_list va, bool caret = true) {
139 Common::String buf = Common::String::vformat(s, va);
140
141 if (caret)
142 buf += '\n';
143
144 if (g_system)
145 g_system->logMessage(LogMessageType::kDebug, buf.c_str());
146 // TODO: Think of a good fallback in case we do not have
147 // any OSystem yet.
148 }
149
debug(const char * s,...)150 void debug(const char *s, ...) {
151 va_list va;
152
153 if (gDebugChannelsOnly)
154 return;
155
156 va_start(va, s);
157 debugHelper(s, va);
158 va_end(va);
159 }
160
debug(int level,const char * s,...)161 void debug(int level, const char *s, ...) {
162 va_list va;
163
164 if (level > gDebugLevel || gDebugChannelsOnly)
165 return;
166
167 va_start(va, s);
168 debugHelper(s, va);
169 va_end(va);
170
171 }
172
debugN(const char * s,...)173 void debugN(const char *s, ...) {
174 va_list va;
175
176 if (gDebugChannelsOnly)
177 return;
178
179 va_start(va, s);
180 debugHelper(s, va, false);
181 va_end(va);
182 }
183
debugN(int level,const char * s,...)184 void debugN(int level, const char *s, ...) {
185 va_list va;
186
187 if (level > gDebugLevel || gDebugChannelsOnly)
188 return;
189
190 va_start(va, s);
191 debugHelper(s, va, false);
192 va_end(va);
193 }
194
debugC(int level,uint32 debugChannels,const char * s,...)195 void debugC(int level, uint32 debugChannels, const char *s, ...) {
196 va_list va;
197
198 // Debug level 11 turns on all special debug level messages
199 if (gDebugLevel != 11)
200 if (level > gDebugLevel || !(DebugMan.isDebugChannelEnabled(debugChannels)))
201 return;
202
203 va_start(va, s);
204 debugHelper(s, va);
205 va_end(va);
206 }
207
debugCN(int level,uint32 debugChannels,const char * s,...)208 void debugCN(int level, uint32 debugChannels, const char *s, ...) {
209 va_list va;
210
211 // Debug level 11 turns on all special debug level messages
212 if (gDebugLevel != 11)
213 if (level > gDebugLevel || !(DebugMan.isDebugChannelEnabled(debugChannels)))
214 return;
215
216 va_start(va, s);
217 debugHelper(s, va, false);
218 va_end(va);
219 }
220
debugC(uint32 debugChannels,const char * s,...)221 void debugC(uint32 debugChannels, const char *s, ...) {
222 va_list va;
223
224 // Debug level 11 turns on all special debug level messages
225 if (gDebugLevel != 11)
226 if (!(DebugMan.isDebugChannelEnabled(debugChannels)))
227 return;
228
229 va_start(va, s);
230 debugHelper(s, va);
231 va_end(va);
232 }
233
debugCN(uint32 debugChannels,const char * s,...)234 void debugCN(uint32 debugChannels, const char *s, ...) {
235 va_list va;
236
237 // Debug level 11 turns on all special debug level messages
238 if (gDebugLevel != 11)
239 if (!(DebugMan.isDebugChannelEnabled(debugChannels)))
240 return;
241
242 va_start(va, s);
243 debugHelper(s, va, false);
244 va_end(va);
245 }
246
247 #endif
248