7bbf9cbe7700ca7c454d1d75f62e8f81412b150d
[libfirm] / ir / ir / irprintf.c
1 /**
2  * A little printf helper funterstanding firm types.
3  * @author Sebastian Hack
4  * @date 29.11.2004
5  */
6
7 #include <stdio.h>
8 #include <stdarg.h>
9 #include <string.h>
10
11 #include "irmode.h"
12 #include "irnode.h"
13 #include "tv.h"
14 #include "irprintf.h"
15 #include "pset.h"
16 #include "iterator.h"
17
18
19
20 static void str_append_char(void *object, size_t n, char ch)
21 {
22         char buf[2];
23
24         buf[0] = ch;
25         buf[1] = 0;
26
27         strncat(object, buf, n);
28 }
29
30 static void str_append_str(void *object, size_t n, const char *str)
31 {
32         strncat(object, str, n);
33 }
34
35 static void file_append_char(void *object, size_t n, char ch)
36 {
37         fputc(ch, object);
38 }
39
40 static void file_append_str(void *object, size_t n, const char *str)
41 {
42         fputs(str, object);
43 }
44
45 static const appender_t file_appender = {
46         file_append_char,
47         file_append_str
48 };
49
50 static const appender_t str_appender = {
51         str_append_char,
52         str_append_str
53 };
54
55 static void ir_common_vprintf(const appender_t *app, void *object,
56                 size_t limit, const char *fmt, va_list args);
57
58 static INLINE void ir_common_printf(const appender_t *app, void *object,
59                 size_t limit, const char *fmt, ...)
60 {
61         va_list args;
62
63         va_start(args, fmt);
64         ir_common_vprintf(app, object, limit, fmt, args);
65         va_end(args);
66 }
67
68 /**
69  * A small printf helper routine for ir nodes.
70  * @param app An appender (this determines where the stuff is dumped
71  * to).
72  * @param object A target passed to the appender.
73  * @param limit The maximum number of characters to dump.
74  * @param fmt The format string.
75  * @param args A va_list.
76  */
77 static void ir_common_vprintf(const appender_t *app, void *object,
78                 size_t limit, const char *fmt, va_list args)
79 {
80         char buf[256];
81         int i, n;
82
83 #define DUMP_STR(s) app->append_str(object, limit, s)
84 #define DUMP_CH(ch) app->append_char(object, limit, ch)
85
86         for(i = 0, n = strlen(fmt); i < n; ++i) {
87                 char ch = fmt[i];
88
89                 if(ch == '%') {
90                         char next_ch = fmt[++i];
91
92                         /* Clear the temporary buffer */
93                         buf[0] = '\0';
94
95                         switch(next_ch) {
96                                 case '%':
97                                         DUMP_CH('%');
98                                         break;
99                                 case 's':
100                                         DUMP_STR(va_arg(args, const char *));
101                                         break;
102
103                                 case 'p':
104                                         snprintf(buf, sizeof(buf), "%p", va_arg(args, void *));
105                                         break;
106
107                                 case 't':
108                                         tarval_snprintf(buf, sizeof(buf), va_arg(args, tarval *));
109                                         break;
110
111                                 case 'n':
112                                         {
113                                                 ir_node *irn = va_arg(args, ir_node *);
114                                                 snprintf(buf, sizeof(buf), "%s%s:%ld",
115                                                                 get_irn_opname(irn), get_mode_name(get_irn_mode(irn)), get_irn_node_nr(irn));
116                                         }
117                                         break;
118
119                                 case 'o':
120                                         DUMP_STR(get_irn_opname(va_arg(args, ir_node *)));
121                                         break;
122
123                                 case 'N':
124                                         snprintf(buf, sizeof(buf), "%ld", get_irn_node_nr(va_arg(args, ir_node *)));
125                                         break;
126
127                                 case 'm':
128                                         DUMP_STR(get_mode_name(va_arg(args, ir_mode *)));
129                                         break;
130
131                                 case 'b':
132                                         snprintf(buf, sizeof(buf), "%ld",
133                                                         get_irn_node_nr(get_nodes_block(va_arg(args, ir_node *))));
134                                         break;
135
136                                 case '+':
137                                         {
138                                                 iterator_t *it = va_arg(args, iterator_t *);
139                                                 void *collection = va_arg(args, void *);
140                                                 void *curr;
141                                                 const char *prefix = "";
142                                                 char format = fmt[++i];
143                                                 ir_printf_cb_t *cb = format == 'C' ? va_arg(args, ir_printf_cb_t *) : NULL;
144
145                                                 assert(is_iterator(it) && "Pass an iterator interface and the collection");
146
147                                                 snprintf(buf, sizeof(buf), "%%%c", format);
148
149                                                 DUMP_CH('[');
150                                                 for(curr = it->start(collection); curr; curr = it->next(collection, curr)) {
151                                                         DUMP_STR(prefix);
152
153                                                         if(cb)
154                                                                 cb(app, object, limit, curr);
155                                                         else
156                                                                 ir_common_printf(app, object, limit, buf, curr);
157
158                                                         prefix = ", ";
159                                                 }
160                                                 it->finish(collection, curr);
161
162                                                 DUMP_CH(']');
163                                         }
164
165                                         /* clean the buffer again */
166                                         buf[0] = '\0';
167                                         break;
168                         }
169
170                         /* Dump the temporary buffer, if something is in it. */
171                         if(buf[0] != '\0')
172                                 DUMP_STR(buf);
173                 }
174
175                 else
176                         DUMP_CH(ch);
177         }
178
179 #undef DUMP_STR
180 #undef DUMP_CH
181 }
182
183 /**
184  * Convencience for stdout dumping.
185  */
186 void ir_printf(const char *fmt, ...)
187 {
188         va_list args;
189         va_start(args, fmt);
190         ir_common_vprintf(&file_appender, stdout, 0, fmt, args);
191         va_end(args);
192 }
193
194 /**
195  * Convencience for file dumping.
196  */
197 void ir_fprintf(FILE *f, const char *fmt, ...)
198 {
199         va_list args;
200         va_start(args, fmt);
201         ir_common_vprintf(&file_appender, f, 0, fmt, args);
202         va_end(args);
203 }
204
205 /**
206  * Convencience for string dumping.
207  */
208 void ir_snprintf(char *buf, size_t len, const char *fmt, ...)
209 {
210         va_list args;
211         va_start(args, fmt);
212         ir_common_vprintf(&str_appender, buf, len, fmt, args);
213         va_end(args);
214 }