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