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