no environment anymore for emitters
[libfirm] / ir / common / debug.c
1 /*
2  * Copyright (C) 1995-2007 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  * @version $Id$
26  */
27 #ifdef HAVE_CONFIG_H
28 #include "config.h"
29 #endif
30
31 #include "firm_config.h"
32
33 #ifdef DEBUG_libfirm
34
35 #include <stdarg.h>
36 #include <string.h>
37
38 #include "irprintf.h"
39 #include "debug.h"
40
41 #include "hashptr.h"
42 #include "obst.h"
43 #include "set.h"
44
45 #ifdef WITH_LIBCORE
46
47 #include "irargs_t.h"
48
49 static void firm_dbg_default_printer(struct obstack *obst, const char *fmt, va_list args)
50 {
51   static lc_arg_env_t *env = NULL;
52
53   if(!env)
54     env = firm_get_arg_env();
55
56   lc_evoprintf(env, obst, fmt, args);
57
58 }
59
60 firm_dbg_module_t *firm_dbg_register(const char *name)
61 {
62   return lc_dbg_register_with_printer(name, firm_dbg_default_printer);
63 }
64
65 #else
66
67 static struct obstack dbg_obst;
68 static set *module_set;
69
70 /**
71  * A debug module.
72  */
73 struct _firm_dbg_module_t {
74   unsigned mask;
75   const char *name;
76   FILE *file;
77 };
78
79 /**
80  * Compares two modules by comparing it's names
81  */
82 static int module_cmp(const void *p1, const void *p2, size_t size)
83 {
84   const firm_dbg_module_t *m1 = p1;
85   const firm_dbg_module_t *m2 = p2;
86   return strcmp(m1->name, m2->name);
87 }
88
89 /**
90  * initialize the debug module
91  */
92 static void firm_dbg_init(void)
93 {
94   obstack_init(&dbg_obst);
95   module_set = new_set(module_cmp, 16);
96 }
97
98 firm_dbg_module_t *firm_dbg_register(const char *name)
99 {
100   firm_dbg_module_t mod;
101   mod.mask = 0;
102   mod.name = name;
103   mod.file = stderr;
104
105   if(!module_set)
106     firm_dbg_init();
107
108   return set_insert(module_set, &mod, sizeof(mod), HASH_STR(name, strlen(name)));
109 }
110
111 void firm_dbg_set_mask(firm_dbg_module_t *module, unsigned mask)
112 {
113   module->mask = mask;
114 }
115
116 unsigned firm_dbg_get_mask(const firm_dbg_module_t *module)
117 {
118   return module->mask;
119 }
120
121 void firm_dbg_set_file(firm_dbg_module_t *module, FILE *file)
122 {
123   module->file = file;
124 }
125
126 /**
127  * A message info: a pair of debug handle and message
128  */
129 typedef struct _msg_info_t {
130   const char *msg;
131   const firm_dbg_module_t *mod;
132 } msg_info_t;
133
134 /**
135  * Formats a message given by a printf-like format and a va_list argument,
136  * puts the test on an obstack and return a msg_info.
137  */
138 static void *make_msg_info(const firm_dbg_module_t *mod, const char *fmt, va_list args)
139 {
140   static const char msg_header[] = "%s(%d) %s: ";
141   msg_info_t *res = obstack_alloc(&dbg_obst, sizeof(*res));
142
143   obstack_grow(&dbg_obst, msg_header, sizeof(msg_header) - 1);
144   ir_obst_vprintf(&dbg_obst, fmt, args);
145   obstack_1grow(&dbg_obst, '\0');
146
147   res->msg = obstack_finish(&dbg_obst);
148   res->mod = mod;
149   return res;
150 }
151
152 void *_firm_dbg_make_msg(const firm_dbg_module_t *mod, unsigned mask, const char *fmt, ...)
153 {
154   void *res = NULL;
155
156   if(mask == 0 || (mod->mask & mask)) {
157     va_list args;
158     va_start(args, fmt);
159     res = make_msg_info(mod, fmt, args);
160     va_end(args);
161   }
162
163   return res;
164 }
165
166 void _firm_dbg_print_msg(const char *filename, int line, const char *func, void *mi_ptr)
167 {
168   msg_info_t *mi = mi_ptr;
169   if(mi) {
170     fprintf(mi->mod->file, mi->msg, filename, line, func);
171     obstack_free(&dbg_obst, mi);
172   }
173 }
174
175 void _firm_dbg_print(const firm_dbg_module_t *mod, unsigned mask, const char *fmt, ...)
176 {
177   if(mask == 0 || (mod->mask & mask)) {
178     va_list args;
179     char *res;
180     va_start(args, fmt);
181     ir_obst_vprintf(&dbg_obst, fmt, args);
182     obstack_1grow(&dbg_obst, '\0');
183     res = obstack_finish(&dbg_obst);
184     fprintf(mod->file, res);
185     obstack_free(&dbg_obst, res);
186     va_end(args);
187   }
188 }
189
190 #endif /* WITH_LIBCORE */
191
192 #else /* DEBUG_libfirm */
193
194 /* some picky compiler don't allow empty files */
195 static int dummy;
196
197 #endif /* DEBUG_libfirm */