--- /dev/null
+/**
+ * Debug facility.
+ * @author Michael Beck, Sebastian Hack
+ * @date 15.12.2004
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdarg.h>
+#include <string.h>
+
+#include "irprintf.h"
+#include "debug.h"
+
+#include "hashptr.h"
+#include "obst.h"
+#include "set.h"
+
+static struct obstack dbg_obst;
+static set *module_set;
+
+struct _firm_dbg_module_t {
+ unsigned mask;
+ const char *name;
+ FILE *file;
+};
+
+static int module_cmp(const void *p1, const void *p2, size_t size)
+{
+ const firm_dbg_module_t *m1 = p1;
+ const firm_dbg_module_t *m2 = p2;
+ return strcmp(m1->name, m2->name);
+}
+
+static void firm_dbg_init(void)
+{
+ obstack_init(&dbg_obst);
+ module_set = new_set(module_cmp, 16);
+}
+
+firm_dbg_module_t *firm_dbg_register(const char *name)
+{
+ firm_dbg_module_t mod;
+ mod.mask = 0;
+ mod.name = name;
+ mod.file = stderr;
+
+ if(!module_set)
+ firm_dbg_init();
+
+ return set_insert(module_set, &mod, sizeof(mod), HASH_STR(name, strlen(name)));
+}
+
+void firm_dbg_set_mask(firm_dbg_module_t *module, unsigned mask)
+{
+ module->mask = mask;
+}
+
+unsigned firm_dbg_get_mask(const firm_dbg_module_t *module)
+{
+ return module->mask;
+}
+
+void firm_dbg_set_file(firm_dbg_module_t *module, FILE *file)
+{
+ module->file = file;
+}
+
+typedef struct _msg_info_t {
+ const char *msg;
+ const firm_dbg_module_t *mod;
+} msg_info_t;
+
+static void *make_msg_info(const firm_dbg_module_t *mod, const char *fmt, va_list args)
+{
+ static const char msg_header[] = "%s(%d) %s: ";
+ msg_info_t *res = obstack_alloc(&dbg_obst, sizeof(*res));
+
+ obstack_grow(&dbg_obst, msg_header, sizeof(msg_header) - 1);
+ ir_obst_vprintf(&dbg_obst, fmt, args);
+ res->msg = obstack_finish(&dbg_obst);
+ res->mod = mod;
+ return res;
+}
+
+void *_firm_dbg_make_msg(const firm_dbg_module_t *mod, unsigned mask, const char *fmt, ...)
+{
+ void *res = NULL;
+
+ if(mask == 0 || (mod->mask & mask)) {
+ va_list args;
+ va_start(args, fmt);
+ res = make_msg_info(mod, fmt, args);
+ va_end(args);
+ }
+
+ return res;
+}
+
+void _firm_dbg_print_msg(const char *filename, int line, const char *func, void *mi_ptr)
+{
+ msg_info_t *mi = mi_ptr;
+ if(mi) {
+ fprintf(mi->mod->file, mi->msg, filename, line, func);
+ obstack_free(&dbg_obst, mi);
+ }
+}
--- /dev/null
+/**
+ * Debug facility.
+ * @author Michael Beck, Sebastian Hack
+ * @date 15.12.2004
+ */
+
+#ifndef _FIRM_DEBUG_H
+#define _FIRM_DEBUG_H
+
+#include <stdio.h>
+
+enum firm_dbg_level_t {
+ LEVEL_DEFAULT = 0, /**< Prints always. Use with DBG(). */
+ LEVEL_1 = 1,
+ LEVEL_2 = 2,
+ LEVEL_3 = 4,
+ LEVEL_4 = 8,
+ LEVEL_5 = 16,
+
+ SET_LEVEL_1 = 1, /**< use with firm_dbg_set_mask(). */
+ SET_LEVEL_2 = 3,
+ SET_LEVEL_3 = 7,
+ SET_LEVEL_4 = 15,
+ SET_LEVEL_5 = 31
+};
+
+typedef struct _firm_dbg_module_t firm_dbg_module_t;
+
+/* Internal function to the debug module. */
+void *_firm_dbg_make_msg(const firm_dbg_module_t *mod, unsigned mask, const char *fmt, ...);
+
+/* Internal function to the debug module. */
+void _firm_dbg_print_msg(const char *filename, int line, const char *func, void *data);
+
+/**
+ * Register a module to the firm debug facility.
+ * If the module has already been registered, no new module is allocated
+ * but the handle is returned. By default, all messages go to @c stderr
+ * and the debug mask is set to 0, i.e. the module is muted.
+ * @param name The name of the module to register.
+ * @return The module handle.
+ */
+firm_dbg_module_t *firm_dbg_register(const char *name);
+
+/**
+ * Set the mask of a module.
+ * @param module The module.
+ * @param mask The new mask for the module.
+ */
+void firm_dbg_set_mask(firm_dbg_module_t *module, unsigned mask);
+
+/**
+ * Get the mask of a module.
+ * @param module The module handle.
+ * @return The mask currently used by the module.
+ */
+unsigned firm_dbg_get_mask(const firm_dbg_module_t *module);
+
+/**
+ * Set the output file of a module.
+ * @param module The module handle.
+ * @param file The new file to use by this handle.
+ */
+void firm_dbg_set_file(firm_dbg_module_t *module, FILE *file);
+
+
+/* If we have C99 use the __func__ variable for calling functions name. */
+#if defined(__STD_VERSION__) && __STD_VERSION >= 199901L
+#define _DBG(args) _firm_dbg_print_msg(__FILE__, __LINE__, __func__, _firm_dbg_make_msg args)
+#else
+
+/* Else, check for gcc and use the proprietary __FUNCTION__ macro. */
+#ifdef __GNUC__
+#define _DBG(args) _firm_dbg_print_msg(__FILE__, __LINE__, __FUNCTION__, _firm_dbg_make_msg args)
+#else
+
+/* Else go without the name of the calling function. */
+#define _DBG(args) _firm_dbg_print_msg(__FILE__, __LINE__, "", _firm_dbg_make_msg args)
+#endif
+#endif
+
+/**
+ * Debug messages issued with this macro are always printed, even in
+ * retail versions.
+ * @see DBG()
+ */
+#define DBG_RETAIL(args) _DBG(args)
+
+#ifdef DEBUG
+
+/**
+ * Issue a debug message.
+ * @param args The arguments.
+ *
+ * The arguments is a list surrounded by parentheses. The items
+ * of the list are:
+ * - The module handle as returned by firm_dbg_register().
+ * - The debug mask that you want associate with this message.
+ * - A format string for the message to pass to ir_printf().
+ * - Further optional arguments are passed to ir_printf().
+ *
+ * The mask is anded against the module's mask. If both have some bits
+ * in common, the message is issued. If the given mask is 0, the message
+ * is always dumped regardless of the module's mask. You can also use
+ * the mask in a level based manner, see firm_dbg_level_t.
+ *
+ * Here is an example:
+ * @code
+ * DBG((my_mod, MASK_ERR, "ir node %n is not green", node))
+ * ...
+ * DBG((my_mod, LEVEL_DEFAULT, "entity %e has type %t", ent, type))
+ * @endcode
+ */
+#define DBG(args) _DBG(args)
+
+#else
+#define DBG(args)
+#endif
+
+
+#endif