2 * Copyright (c) 2012, Intel Corporation
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of Intel Corporation nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 #include <murphy/common/macros.h>
34 #include <murphy/common/mm.h>
35 #include <murphy/common/list.h>
36 #include <murphy/common/log.h>
37 #include <murphy/common/hashtbl.h>
38 #include <murphy/common/utils.h>
39 #include <murphy/common/debug.h>
43 int mrp_debug_stamp = 0; /* debug config stamp */
45 static int debug_enabled; /* debug messages enabled */
46 static mrp_htbl_t *rules_on; /* enabling rules */
47 static mrp_htbl_t *rules_off; /* disabling rules */
48 static mrp_htbl_t *files; /* table of per-file debug info */
49 static MRP_LIST_HOOK(debug_files);
51 static void populate_file_table(void);
53 static void free_rule_cb(void *key, void *entry)
61 static int init_rules(void)
63 mrp_htbl_config_t hcfg;
66 hcfg.comp = mrp_string_comp;
67 hcfg.hash = mrp_string_hash;
68 hcfg.free = free_rule_cb;
70 rules_on = mrp_htbl_create(&hcfg);
71 rules_off = mrp_htbl_create(&hcfg);
73 if (rules_on == NULL || rules_off == NULL)
80 static void reset_rules(void)
83 mrp_htbl_destroy(rules_on , TRUE);
84 if (rules_off != NULL)
85 mrp_htbl_destroy(rules_off, TRUE);
89 void mrp_debug_reset(void)
91 debug_enabled = FALSE;
96 int mrp_debug_enable(int enabled)
98 int prev = debug_enabled;
100 debug_enabled = !!enabled;
101 mrp_log_enable(MRP_LOG_MASK_DEBUG);
107 static int add_rule(const char *func, const char *file, int line, int off)
110 char *rule, *r, buf[PATH_MAX * 2];
112 if (rules_on == NULL)
123 if (func != NULL && file == NULL && line == 0) {
124 r = mrp_htbl_lookup(ht, (void *)func);
127 else if (func != NULL && file != NULL && line == 0) {
128 snprintf(buf, sizeof(buf), "%s@%s", func, file);
129 r = mrp_htbl_lookup(ht, (void *)buf);
132 else if (func == NULL && file != NULL && line == 0) {
133 snprintf(buf, sizeof(buf), "@%s", file);
134 r = mrp_htbl_lookup(ht, (void *)buf);
137 else if (func == NULL && file != NULL && line > 0) {
138 snprintf(buf, sizeof(buf), "%s:%d", file, line);
139 r = mrp_htbl_lookup(ht, (void *)buf);
146 rule = mrp_strdup(rule);
150 if (mrp_htbl_insert(ht, rule, rule)) {
163 static int del_rule(const char *func, const char *file, int line, int off)
166 char *r, buf[PATH_MAX * 2];
168 if (rules_on == NULL)
179 if (func != NULL && file == NULL && line == 0) {
180 r = mrp_htbl_remove(ht, (void *)func, TRUE);
182 else if (func != NULL && file != NULL && line == 0) {
183 snprintf(buf, sizeof(buf), "%s@%s", func, file);
184 r = mrp_htbl_remove(ht, (void *)buf, TRUE);
186 else if (func == NULL && file != NULL && line == 0) {
187 snprintf(buf, sizeof(buf), "@%s", file);
188 r = mrp_htbl_remove(ht, (void *)buf, TRUE);
190 else if (func == NULL && file != NULL && line > 0) {
191 snprintf(buf, sizeof(buf), "%s:%d", file, line);
192 r = mrp_htbl_remove(ht, (void *)buf, TRUE);
205 int mrp_debug_set_config(const char *cmd)
207 char buf[2 * PATH_MAX + 1], *colon, *at, *eq;
208 char *func, *file, *end;
212 if (*cmd == '+' || *cmd == '-')
213 del = (*cmd++ == '-');
217 eq = strchr(cmd, '=');
220 strncpy(buf, cmd, sizeof(buf) - 1);
221 buf[sizeof(buf) - 1] = '\0';
225 if (!strcmp(eq + 1, "on"))
227 else if (!strcmp(eq + 1, "off"))
233 if (len >= sizeof(buf))
234 len = sizeof(buf) - 1;
236 strncpy(buf, cmd, len);
240 colon = strchr(buf, ':');
243 if (strchr(buf, '@') != NULL)
249 line = strtoul(colon + 1, &end, 10);
254 mrp_log_info("%s file='%s', line=%d, %s", del ? "del" : "add",
255 file, line, off ? "off" : "on");
258 at = strchr(buf, '@');
262 func = (at == buf ? NULL : buf);
266 mrp_log_info("%s func='%s', file='%s', %s", del ? "del" : "add",
267 func ? func : "", file, off ? "off" : "on");
274 mrp_log_info("%s func='%s' %s", del ? "del" : "add",
275 func, off ? "off" : "on");
280 return add_rule(func, file, line, off);
282 return del_rule(func, file, line, off);
294 static int dump_rule_cb(void *key, void *object, void *user_data)
296 dump_t *d = (dump_t *)user_data;
298 const char *state = d->on ? "on" : "off";
302 fprintf(fp, " %s %s\n", (char *)object, state);
304 return MRP_HTBL_ITER_MORE;
308 int mrp_debug_dump_config(FILE *fp)
312 fprintf(fp, "Debugging is %sabled\n", debug_enabled ? "en" : "dis");
314 if (rules_on != NULL) {
315 fprintf(fp, "Debugging rules:\n");
319 mrp_htbl_foreach(rules_on , dump_rule_cb, &d);
321 mrp_htbl_foreach(rules_off, dump_rule_cb, &d);
324 fprintf(fp, "No debugging rules defined.\n");
330 void mrp_debug_msg(const char *site, const char *file, int line,
331 const char *func, const char *format, ...)
337 va_start(ap, format);
338 mrp_log_msgv(MRP_LOG_DEBUG, file, line, func, format, ap);
343 int mrp_debug_check(const char *func, const char *file, int line)
345 char buf[2 * PATH_MAX], *base;
348 if (!debug_enabled || rules_on == NULL)
352 if (mrp_htbl_lookup(rules_on, key) != NULL)
355 base = strrchr(file, '/');
358 if (mrp_htbl_lookup(rules_on, key) != NULL)
364 snprintf(buf, sizeof(buf), "@%s", file);
365 if (mrp_htbl_lookup(rules_on, key) != NULL)
368 snprintf(buf, sizeof(buf), "%s@%s", func, file);
369 if (mrp_htbl_lookup(rules_on, key) != NULL)
372 snprintf(buf, sizeof(buf), "%s:%d", file, line);
373 if (mrp_htbl_lookup(rules_on, key) != NULL)
376 if (mrp_htbl_lookup(rules_on, (void *)WILDCARD) == NULL)
381 if (rules_off == NULL)
385 if (mrp_htbl_lookup(rules_off, key) != NULL)
388 base = strrchr(file, '/');
391 if (mrp_htbl_lookup(rules_on, key) != NULL)
397 snprintf(buf, sizeof(buf), "@%s", file);
398 if (mrp_htbl_lookup(rules_off, key) != NULL)
401 snprintf(buf, sizeof(buf), "%s@%s", func, file);
402 if (mrp_htbl_lookup(rules_off, key) != NULL)
405 snprintf(buf, sizeof(buf), "%s:%d", file, line);
406 if (mrp_htbl_lookup(rules_off, key) != NULL)
413 int mrp_debug_register_file(mrp_debug_file_t *df)
415 mrp_list_append(&debug_files, &df->hook);
421 int mrp_debug_unregister_file(mrp_debug_file_t *df)
423 mrp_list_delete(&df->hook);
426 mrp_htbl_remove(files, (void *)df->file, FALSE);
432 const char *mrp_debug_site_function(const char *file, int line)
434 mrp_debug_info_t *info;
438 populate_file_table();
443 info = mrp_htbl_lookup(files, (void *)file);
446 while (info->func != NULL) {
447 if (info->line < line) {
461 static void populate_file_table(void)
463 mrp_htbl_config_t hcfg;
464 mrp_debug_file_t *df;
465 mrp_list_hook_t *p, *n;
469 hcfg.comp = mrp_string_comp;
470 hcfg.hash = mrp_string_hash;
472 files = mrp_htbl_create(&hcfg);
476 mrp_list_foreach(&debug_files, p, n) {
477 df = mrp_list_entry(p, typeof(*df), hook);
479 mrp_htbl_insert(files, (void *)df->file, df->info);
485 static void flush_file_table(void)
487 mrp_debug_file_t *df;
488 mrp_list_hook_t *p, *n;
491 mrp_htbl_reset(files, FALSE);
494 mrp_list_foreach(&debug_files, p, n) {
495 df = mrp_list_entry(p, typeof(*df), hook);
497 mrp_htbl_insert(files, (void *)df->file, df->info);