fixed config.h include
[libfirm] / ir / ir / irprintf.c
1 /*
2  * Project:     libFIRM
3  * File name:   ir/ir/irprintf.c
4  * Purpose:     A little printf helper unterstanding firm types
5  * Author:      Sebastian Hack
6  * Created:     29.11.2004
7  * CVS-ID:      $Id$
8  * Copyright:   (c) 1998-2004 Universität Karlsruhe
9  * Licence:     This file protected by GPL -  GNU GENERAL PUBLIC LICENSE.
10  */
11
12 /**
13  * @file irprinf.c
14  *
15  * A little printf helper unterstanding firm types.
16  * @author Sebastian Hack
17  * @date 29.11.2004
18  */
19
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 #include <stdio.h>
25 #include <stdarg.h>
26
27 #ifdef HAVE_STRING_H
28 # include <string.h>
29 #endif
30
31 #include "ident.h"
32 #include "irmode_t.h"
33 #include "irnode_t.h"
34 #include "entity_t.h"
35 #include "tv.h"
36 #include "irprintf.h"
37 #include "pset.h"
38 #include "iterator.h"
39
40
41 /**
42  * append a char to a string buffer
43  */
44 static void str_append_char(void *object, size_t n, char ch)
45 {
46         char buf[2];
47
48         buf[0] = ch;
49         buf[1] = 0;
50
51         strncat(object, buf, n);
52 }
53
54 /**
55  * append a string to a string buffer
56  */
57 static void str_append_str(void *object, size_t n, const char *str)
58 {
59         strncat(object, str, n);
60 }
61
62 /**
63  * append a char to a file
64  */
65 static void file_append_char(void *object, size_t n, char ch)
66 {
67         fputc(ch, object);
68 }
69
70 /**
71  * append a string to a file
72  */
73 static void file_append_str(void *object, size_t n, const char *str)
74 {
75         fputs(str, object);
76 }
77
78 /**
79  * the file appender
80  */
81 static const appender_t file_appender = {
82         file_append_char,
83         file_append_str
84 };
85
86 /**
87  * the string buffer appender
88  */
89 static const appender_t str_appender = {
90         str_append_char,
91         str_append_str
92 };
93
94 static void ir_common_vprintf(const appender_t *app, void *object,
95                 size_t limit, const char *fmt, va_list args);
96
97 static INLINE void ir_common_printf(const appender_t *app, void *object,
98                 size_t limit, const char *fmt, ...)
99 {
100         va_list args;
101
102         va_start(args, fmt);
103         ir_common_vprintf(app, object, limit, fmt, args);
104         va_end(args);
105 }
106
107 /**
108  * A small printf helper routine for ir nodes.
109  * @param app An appender (this determines where the stuff is dumped
110  * to).
111  * @param object A target passed to the appender.
112  * @param limit The maximum number of characters to dump.
113  * @param fmt The format string.
114  * @param args A va_list.
115  */
116 static void ir_common_vprintf(const appender_t *app, void *object,
117                 size_t limit, const char *fmt, va_list args)
118 {
119         char buf[256];
120         int i, n;
121
122 #define DUMP_STR(s) app->append_str(object, limit, s)
123 #define DUMP_CH(ch) app->append_char(object, limit, ch)
124
125         for(i = 0, n = strlen(fmt); i < n; ++i) {
126                 char ch = fmt[i];
127
128                 if(ch == '%') {
129                         char next_ch = fmt[++i];
130
131                         /* Clear the temporary buffer */
132                         buf[0] = '\0';
133
134                         switch(next_ch) {
135                                 case '%':
136                                         DUMP_CH('%');
137                                         break;
138                                 case 's':
139                                         DUMP_STR(va_arg(args, const char *));
140                                         break;
141
142                                 case 'I':
143                                         DUMP_STR(get_id_str(va_arg(args, ident *)));
144                                         break;
145
146                                 case 'e':
147                                         DUMP_STR(get_entity_name(va_arg(args, entity *)));
148                                         break;
149
150                                 case 'E':
151                                         DUMP_STR(get_entity_ld_name(va_arg(args, entity *)));
152                                         break;
153
154                                 case 'p':
155                                         snprintf(buf, sizeof(buf), "%p", va_arg(args, void *));
156                                         break;
157
158                                 case 't':
159                                         tarval_snprintf(buf, sizeof(buf), va_arg(args, tarval *));
160                                         break;
161
162                                 case 'n':
163                                         {
164                                                 ir_node *irn = va_arg(args, ir_node *);
165                                                 snprintf(buf, sizeof(buf), "%s%s:%ld",
166                                                                 get_irn_opname(irn), get_mode_name(get_irn_mode(irn)), get_irn_node_nr(irn));
167                                         }
168                                         break;
169
170                                 case 'o':
171                                         DUMP_STR(get_irn_opname(va_arg(args, ir_node *)));
172                                         break;
173
174                                 case 'N':
175                                         snprintf(buf, sizeof(buf), "%ld", get_irn_node_nr(va_arg(args, ir_node *)));
176                                         break;
177
178                                 case 'm':
179                                         DUMP_STR(get_mode_name(va_arg(args, ir_mode *)));
180                                         break;
181
182                                 case 'b':
183                                         snprintf(buf, sizeof(buf), "%ld",
184                                                         get_irn_node_nr(get_nodes_block(va_arg(args, ir_node *))));
185                                         break;
186
187                                 case '+':
188                                         {
189                                                 iterator_t *it = va_arg(args, iterator_t *);
190                                                 void *collection = va_arg(args, void *);
191                                                 void *curr;
192                                                 const char *prefix = "";
193                                                 char format = fmt[++i];
194                                                 ir_printf_cb_t *cb = format == 'C' ? va_arg(args, ir_printf_cb_t *) : NULL;
195
196                                                 assert(is_iterator(it) && "Pass an iterator interface and the collection");
197
198                                                 snprintf(buf, sizeof(buf), "%%%c", format);
199
200                                                 DUMP_CH('[');
201                                                 for(curr = it->start(collection); curr; curr = it->next(collection, curr)) {
202                                                         DUMP_STR(prefix);
203
204                                                         if(cb)
205                                                                 cb(app, object, limit, curr);
206                                                         else
207                                                                 ir_common_printf(app, object, limit, buf, curr);
208
209                                                         prefix = ", ";
210                                                 }
211                                                 it->finish(collection, curr);
212
213                                                 DUMP_CH(']');
214                                         }
215
216                                         /* clean the buffer again */
217                                         buf[0] = '\0';
218                                         break;
219                         }
220
221                         /* Dump the temporary buffer, if something is in it. */
222                         if(buf[0] != '\0')
223                                 DUMP_STR(buf);
224                 }
225
226                 else
227                         DUMP_CH(ch);
228         }
229
230 #undef DUMP_STR
231 #undef DUMP_CH
232 }
233
234 /**
235  * Convencience for stdout dumping.
236  */
237 void ir_printf(const char *fmt, ...)
238 {
239         va_list args;
240         va_start(args, fmt);
241         ir_common_vprintf(&file_appender, stdout, 0, fmt, args);
242         va_end(args);
243 }
244
245 /**
246  * Convencience for file dumping.
247  */
248 void ir_fprintf(FILE *f, const char *fmt, ...)
249 {
250         va_list args;
251         va_start(args, fmt);
252         ir_common_vprintf(&file_appender, f, 0, fmt, args);
253         va_end(args);
254 }
255
256 /**
257  * Convencience for string dumping.
258  */
259 void ir_snprintf(char *buf, size_t len, const char *fmt, ...)
260 {
261         va_list args;
262         va_start(args, fmt);
263         ir_common_vprintf(&str_appender, buf, len, fmt, args);
264         va_end(args);
265 }