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