becopyilp: Do not advertise the switch to dump the solution, because this is not...
[libfirm] / ir / common / debug.c
1 /*
2  * This file is part of libFirm.
3  * Copyright (C) 2012 University of Karlsruhe.
4  */
5
6 /**
7  * @file
8  * @brief   Debug facility.
9  * @author  Michael Beck, Sebastian Hack
10  * @date    15.12.2004
11  */
12 #include "config.h"
13
14 #ifdef DEBUG_libfirm
15
16 #include <stdarg.h>
17 #include <string.h>
18
19 #include "irprintf.h"
20 #include "debug.h"
21
22 #include "hashptr.h"
23 #include "obst.h"
24 #include "set.h"
25
26 static struct obstack dbg_obst;
27 static set *module_set;
28
29 /**
30  * A debug module.
31  */
32 struct firm_dbg_module_t {
33   unsigned mask;
34   const char *name;
35   FILE *file;
36 };
37
38 /**
39  * Compares two modules by comparing their names
40  */
41 static int module_cmp(const void *p1, const void *p2, size_t size)
42 {
43   const firm_dbg_module_t *m1 = (const firm_dbg_module_t*)p1;
44   const firm_dbg_module_t *m2 = (const firm_dbg_module_t*)p2;
45   (void) size;
46
47   return strcmp(m1->name, m2->name);
48 }
49
50 /**
51  * initialize the debug module
52  */
53 static void firm_dbg_init(void)
54 {
55   obstack_init(&dbg_obst);
56   module_set = new_set(module_cmp, 16);
57 }
58
59 firm_dbg_module_t *firm_dbg_register(const char *name)
60 {
61   firm_dbg_module_t mod;
62   mod.mask = 0;
63   mod.name = name;
64   mod.file = stderr;
65
66   if (!module_set)
67     firm_dbg_init();
68
69   return set_insert(firm_dbg_module_t, module_set, &mod, sizeof(mod), hash_str(name));
70 }
71
72 void firm_dbg_set_mask(firm_dbg_module_t *module, unsigned mask)
73 {
74   module->mask = mask;
75 }
76
77 unsigned firm_dbg_get_mask(const firm_dbg_module_t *module)
78 {
79   return module->mask;
80 }
81
82 void firm_dbg_set_file(firm_dbg_module_t *module, FILE *file)
83 {
84   module->file = file;
85 }
86
87 /**
88  * A message info: a pair of debug handle and message
89  */
90 typedef struct msg_info_t {
91   const char *msg;
92   const firm_dbg_module_t *mod;
93 } msg_info_t;
94
95 /**
96  * Formats a message given by a printf-like format and a va_list argument,
97  * puts the test on an obstack and return a msg_info.
98  */
99 static void *make_msg_info(const firm_dbg_module_t *mod, const char *fmt, va_list args)
100 {
101   static const char msg_header[] = "%s(%d) %s: ";
102   msg_info_t *res = OALLOC(&dbg_obst, msg_info_t);
103
104   obstack_grow(&dbg_obst, msg_header, sizeof(msg_header) - 1);
105   ir_obst_vprintf(&dbg_obst, fmt, args);
106   obstack_1grow(&dbg_obst, '\0');
107
108   res->msg = (const char*)obstack_finish(&dbg_obst);
109   res->mod = mod;
110   return res;
111 }
112
113 void *_firm_dbg_make_msg(const firm_dbg_module_t *mod, unsigned mask, const char *fmt, ...)
114 {
115   void *res = NULL;
116
117   if (mask == 0 || (mod->mask & mask)) {
118     va_list args;
119     va_start(args, fmt);
120     res = make_msg_info(mod, fmt, args);
121     va_end(args);
122   }
123
124   return res;
125 }
126
127 void _firm_dbg_print_msg(const char *filename, int line, const char *func, void *mi_ptr)
128 {
129   msg_info_t *mi = (msg_info_t*)mi_ptr;
130   if (mi) {
131     fprintf(mi->mod->file, mi->msg, filename, line, func);
132     obstack_free(&dbg_obst, mi);
133   }
134 }
135
136 void _firm_dbg_print(const firm_dbg_module_t *mod, unsigned mask, const char *fmt, ...)
137 {
138   if (mask == 0 || (mod->mask & mask)) {
139     va_list args;
140     char *res;
141     va_start(args, fmt);
142     ir_obst_vprintf(&dbg_obst, fmt, args);
143     obstack_1grow(&dbg_obst, '\0');
144     res = (char*)obstack_finish(&dbg_obst);
145     fprintf(mod->file, "%s", res);
146     obstack_free(&dbg_obst, res);
147     va_end(args);
148   }
149 }
150
151 #else /* DEBUG_libfirm */
152
153 /* some picky compiler don't allow empty files */
154 static int __attribute__((unused)) dummy;
155
156 #endif /* DEBUG_libfirm */