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