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