1 /*
2 * KCemu -- The emulator for the KC85 homecomputer series and much more.
3 * Copyright (C) 1997-2010 Torsten Paul
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <fstream>
23
24 #include "libdbg/dbg.h"
25
p_map(const char * name,bool allow_subkeys)26 p_map::p_map(const char *name, bool allow_subkeys)
27 {
28 _name = strdup(name);
29 _allow_subkeys = allow_subkeys;
30 }
31
~p_map(void)32 p_map::~p_map(void)
33 {
34 if (_name)
35 free(_name);
36 }
37
38 const char *
get_name(void)39 p_map::get_name(void)
40 {
41 if (_name)
42 return _name;
43 return "<none>";
44 }
45
46 void
set_allow_subkeys(bool allow_subkeys)47 p_map::set_allow_subkeys(bool allow_subkeys)
48 {
49 _allow_subkeys = allow_subkeys;
50 }
51
52 bool
get_allow_subkeys(void)53 p_map::get_allow_subkeys(void)
54 {
55 return _allow_subkeys;
56 }
57
p_tree(void)58 p_tree::p_tree(void)
59 {
60 _map = new p_map("", false);
61 }
62
~p_tree(void)63 p_tree::~p_tree(void)
64 {
65 delete _map;
66 }
67
68 void
add(const char * data,bool allow_subkeys)69 p_tree::add(const char *data, bool allow_subkeys)
70 {
71 p_map *m;
72 char *ptr, *tmp;
73 char d[1024];
74
75 strncpy(d, data, 1024);
76 d[1023] = '\0';
77
78 m = _map;
79 ptr = strtok(d, "/");
80 while (ptr != 0)
81 {
82 p_map::const_iterator m_it = m->find(ptr);
83 if (m_it == m->end())
84 {
85 tmp = strdup(ptr);
86 p_map *new_map = new p_map(tmp, false);
87 (*m)[tmp] = new_map;
88 m = new_map;
89 }
90 else
91 {
92 m = (*m_it).second;
93 }
94 ptr = strtok(0, "/");
95 }
96 if (allow_subkeys)
97 m->set_allow_subkeys(true);
98 }
99
100 bool
check_path(const char * data)101 p_tree::check_path(const char *data)
102 {
103 p_map *m;
104 char *ptr;
105 char d[1024];
106
107 strncpy(d, data, 1024);
108 d[1023] = '\0';
109
110 m = _map;
111 ptr = strtok(d, "/");
112 while (ptr != 0)
113 {
114 if (m->get_allow_subkeys())
115 break;
116 p_map::const_iterator m_it = m->find(ptr);
117 if (m_it == m->end())
118 {
119 return false;
120 }
121 m = (*m_it).second;
122 ptr = strtok(0, "/");
123 }
124
125 return true;
126 }
127
128 void
clear()129 p_tree::clear()
130 {
131 clear(_map);
132 }
133
134 void
clear(p_map * map)135 p_tree::clear(p_map *map)
136 {
137 for (p_map::iterator it = map->begin();it != map->end();it++)
138 clear((*it).second);
139
140 map->clear();
141
142 if (_map != map) // don't free top level object
143 delete map;
144 }
145
146 void
dump(std::ostream & os,p_map * map,int level) const147 p_tree::dump(std::ostream& os, p_map *map, int level) const
148 {
149 for (int a = 0;a < level;a++)
150 os << " ";
151 os << map->get_name();
152 if (map->get_allow_subkeys())
153 os << " <*>";
154 os << std::endl;
155
156 for (p_map::iterator it = map->begin();it != map->end();it++)
157 dump(os, (*it).second, level + 1);
158 }
159
operator <<(std::ostream & os,const p_tree & t)160 std::ostream& operator<< (std::ostream& os, const p_tree& t)
161 {
162 os << "p_tree:" << std::endl;
163 t.dump(os, t._map, 0);
164 return os;
165 }
166
167 DBG_class *DBG_class::_singleton = 0;
168
DBG_class(void)169 DBG_class::DBG_class(void)
170 {
171 _o = &std::cout;
172 load_config();
173 }
174
~DBG_class(void)175 DBG_class::~DBG_class(void)
176 {
177 _tree.clear();
178 }
179
180 DBG_class *
instance(void)181 DBG_class::instance(void)
182 {
183 if (_singleton == 0)
184 _singleton = new DBG_class();
185 return _singleton;
186 }
187
188 void
clear(void)189 DBG_class::clear(void)
190 {
191 _tree.clear();
192 }
193
194 void
load_config(void)195 DBG_class::load_config(void)
196 {
197 char *filename, *tmp;
198
199 clear();
200
201 tmp = getenv("HOME");
202 if (tmp)
203 {
204 filename = new char[strlen(tmp) + 8];
205 strcpy(filename, tmp);
206 strcat(filename, "/.debug");
207 load_file(filename);
208 delete[] filename;
209 }
210 }
211
212 void
load_file(const char * filename)213 DBG_class::load_file(const char *filename)
214 {
215 std::ifstream is;
216 char line[4096];
217
218 is.open(filename);
219 if (!is)
220 return;
221
222 while (242)
223 {
224 is.getline(line, 4096);
225 if (is.eof())
226 break;
227 if (line[0] != '#')
228 add_path(line, false);
229 }
230
231 is.close();
232 }
233
234 void
set_output_stream(std::ostream * os)235 DBG_class::set_output_stream(std::ostream *os)
236 {
237 _o = os;
238 }
239
240 void
add_path(const char * path,bool allow_subkeys)241 DBG_class::add_path(const char *path, bool allow_subkeys)
242 {
243 _tree.add(path, allow_subkeys);
244 }
245
246 void
form(const char * path,const char * format...)247 DBG_class::form(const char *path, const char *format ...)
248 {
249 char buf[8192];
250
251 if (!_tree.check_path(path))
252 return;
253
254 va_list ap;
255 va_start(ap, format);
256 vsnprintf(buf, 8192, format, ap);
257 *_o << buf;
258 _o->flush();
259 va_end(ap);
260 }
261
262 void
print(const char * path,const char * msg)263 DBG_class::print(const char *path, const char *msg)
264 {
265 if (!_tree.check_path(path))
266 return;
267
268 *_o << "DEBUG: " << path << " - " << msg;
269 _o->flush();
270 }
271
272 void
println(const char * path,const char * msg)273 DBG_class::println(const char *path, const char *msg)
274 {
275 if (!_tree.check_path(path))
276 return;
277
278 *_o << "DEBUG: " << path << " - " << msg << std::endl;
279 _o->flush();
280 }
281
282 bool
check(const char * path)283 DBG_class::check(const char *path)
284 {
285 return _tree.check_path(path);
286 }
287
operator <<(std::ostream & os,const DBG_class & dbg)288 std::ostream& operator<< (std::ostream& os, const DBG_class& dbg)
289 {
290 os << "DBG:" << std::endl;
291 os << dbg._tree;
292 return os;
293 }
294