hashptr.h: use inline functions instead of #define
[libfirm] / ir / common / debug.c
1 /*
2  * Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
3  *
4  * This file is part of libFirm.
5  *
6  * This file may be distributed and/or modified under the terms of the
7  * GNU General Public License version 2 as published by the Free Software
8  * Foundation and appearing in the file LICENSE.GPL included in the
9  * packaging of this file.
10  *
11  * Licensees holding valid libFirm Professional Edition licenses may use
12  * this file in accordance with the libFirm Commercial License.
13  * Agreement provided with the Software.
14  *
15  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE.
18  */
19
20 /**
21  * @file
22  * @brief   Debug facility.
23  * @author  Michael Beck, Sebastian Hack
24  * @date    15.12.2004
25  */
26 #include "config.h"
27
28 #ifdef DEBUG_libfirm
29
30 #include <stdarg.h>
31 #include <string.h>
32
33 #include "irprintf.h"
34 #include "debug.h"
35
36 #include "hashptr.h"
37 #include "obst.h"
38 #include "set.h"
39
40 static struct obstack dbg_obst;
41 static set *module_set;
42
43 /**
44  * A debug module.
45  */
46 struct firm_dbg_module_t {
47   unsigned mask;
48   const char *name;
49   FILE *file;
50 };
51
52 /**
53  * Compares two modules by comparing their names
54  */
55 static int module_cmp(const void *p1, const void *p2, size_t size)
56 {
57   const firm_dbg_module_t *m1 = (const firm_dbg_module_t*)p1;
58   const firm_dbg_module_t *m2 = (const firm_dbg_module_t*)p2;
59   (void) size;
60
61   return strcmp(m1->name, m2->name);
62 }
63
64 /**
65  * initialize the debug module
66  */
67 static void firm_dbg_init(void)
68 {
69   obstack_init(&dbg_obst);
70   module_set = new_set(module_cmp, 16);
71 }
72
73 firm_dbg_module_t *firm_dbg_register(const char *name)
74 {
75   firm_dbg_module_t mod;
76   mod.mask = 0;
77   mod.name = name;
78   mod.file = stderr;
79
80   if (!module_set)
81     firm_dbg_init();
82
83   return (firm_dbg_module_t*)set_insert(module_set, &mod, sizeof(mod), hash_str(name));
84 }
85
86 void firm_dbg_set_mask(firm_dbg_module_t *module, unsigned mask)
87 {
88   module->mask = mask;
89 }
90
91 unsigned firm_dbg_get_mask(const firm_dbg_module_t *module)
92 {
93   return module->mask;
94 }
95
96 void firm_dbg_set_file(firm_dbg_module_t *module, FILE *file)
97 {
98   module->file = file;
99 }
100
101 /**
102  * A message info: a pair of debug handle and message
103  */
104 typedef struct msg_info_t {
105   const char *msg;
106   const firm_dbg_module_t *mod;
107 } msg_info_t;
108
109 /**
110  * Formats a message given by a printf-like format and a va_list argument,
111  * puts the test on an obstack and return a msg_info.
112  */
113 static void *make_msg_info(const firm_dbg_module_t *mod, const char *fmt, va_list args)
114 {
115   static const char msg_header[] = "%s(%d) %s: ";
116   msg_info_t *res = OALLOC(&dbg_obst, msg_info_t);
117
118   obstack_grow(&dbg_obst, msg_header, sizeof(msg_header) - 1);
119   ir_obst_vprintf(&dbg_obst, fmt, args);
120   obstack_1grow(&dbg_obst, '\0');
121
122   res->msg = (const char*)obstack_finish(&dbg_obst);
123   res->mod = mod;
124   return res;
125 }
126
127 void *_firm_dbg_make_msg(const firm_dbg_module_t *mod, unsigned mask, const char *fmt, ...)
128 {
129   void *res = NULL;
130
131   if (mask == 0 || (mod->mask & mask)) {
132     va_list args;
133     va_start(args, fmt);
134     res = make_msg_info(mod, fmt, args);
135     va_end(args);
136   }
137
138   return res;
139 }
140
141 void _firm_dbg_print_msg(const char *filename, int line, const char *func, void *mi_ptr)
142 {
143   msg_info_t *mi = (msg_info_t*)mi_ptr;
144   if (mi) {
145     fprintf(mi->mod->file, mi->msg, filename, line, func);
146     obstack_free(&dbg_obst, mi);
147   }
148 }
149
150 void _firm_dbg_print(const firm_dbg_module_t *mod, unsigned mask, const char *fmt, ...)
151 {
152   if (mask == 0 || (mod->mask & mask)) {
153     va_list args;
154     char *res;
155     va_start(args, fmt);
156     ir_obst_vprintf(&dbg_obst, fmt, args);
157     obstack_1grow(&dbg_obst, '\0');
158     res = (char*)obstack_finish(&dbg_obst);
159     fprintf(mod->file, "%s", res);
160     obstack_free(&dbg_obst, res);
161     va_end(args);
162   }
163 }
164
165 #else /* DEBUG_libfirm */
166
167 /* some picky compiler don't allow empty files */
168 static int __attribute__((unused)) dummy;
169
170 #endif /* DEBUG_libfirm */