Small modifications. Swapped %n and %N
[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
16 /**
17  * Something that can append strings and chars to somewhere.
18  */
19 typedef struct _appender_t {
20         void (*append_char)(void *subject, size_t n, char ch);
21         void (*append_str)(void *subject, size_t n, const char *str);
22 } appender_t;
23
24 static void str_append_char(void *subject, size_t n, char ch)
25 {
26         char buf[2];
27
28         buf[0] = ch;
29         buf[1] = 0;
30
31         strncat(subject, buf, n);
32 }
33
34 static void str_append_str(void *subject, size_t n, const char *str)
35 {
36         strncat(subject, str, n);
37 }
38
39 static void file_append_char(void *subject, size_t n, char ch)
40 {
41         fputc(ch, subject);
42 }
43
44 static void file_append_str(void *subject, size_t n, const char *str)
45 {
46         fputs(str, subject);
47 }
48
49 static const appender_t file_appender = {
50         file_append_char,
51         file_append_str
52 };
53
54 static const appender_t str_appender = {
55         str_append_char,
56         str_append_str
57 };
58
59
60 /**
61  * A small printf helper routine for ir nodes.
62  * @param app An appender (this determines where the stuff is dumped
63  * to).
64  * @param subject A target passed to the appender.
65  * @param limit The maximum number of characters to dump.
66  * @param fmt The format string.
67  * @param args A va_list.
68  */
69 static void ir_common_vprintf(const appender_t *app, void *subject,
70                 size_t limit, const char *fmt, va_list args)
71 {
72         char buf[256];
73         int i, n;
74
75 #define DUMP_STR(s) app->append_str(subject, limit, s)
76 #define DUMP_CH(ch) app->append_char(subject, limit, ch)
77
78         for(i = 0, n = strlen(fmt); i < n; ++i) {
79                 char ch = fmt[i];
80
81                 if(ch == '%') {
82                         char next_ch = fmt[++i];
83
84                         /* Clear the temporary buffer */
85                         buf[0] = '\0';
86
87                         switch(next_ch) {
88                                 case '%':
89                                         DUMP_CH('%');
90                                         break;
91                                 case 's':
92                                         DUMP_STR(va_arg(args, const char *));
93                                         break;
94
95                                 case 'p':
96                                         snprintf(buf, sizeof(buf), "%p", va_arg(args, void *));
97                                         break;
98
99                                 case 't':
100                                         tarval_snprintf(buf, sizeof(buf), va_arg(args, tarval *));
101                                         break;
102
103                                 case 'n':
104                                         {
105                                                 ir_node *irn = va_arg(args, ir_node *);
106                                                 snprintf(buf, sizeof(buf), "%s%s:%ld",
107                                                                 get_irn_opname(irn), get_mode_name(get_irn_mode(irn)), get_irn_node_nr(irn));
108                                         }
109                                         break;
110
111                                 case 'o':
112                                         DUMP_STR(get_irn_opname(va_arg(args, ir_node *)));
113                                         break;
114
115                                 case 'N':
116                                         snprintf(buf, sizeof(buf), "%ld", get_irn_node_nr(va_arg(args, ir_node *)));
117                                         break;
118
119                                 case 'm':
120                                         DUMP_STR(get_mode_name(va_arg(args, ir_mode *)));
121                                         break;
122
123                                 case 'b':
124                                         snprintf(buf, sizeof(buf), "%ld",
125                                                         get_irn_node_nr(get_nodes_block(va_arg(args, ir_node *))));
126                                         break;
127                         }
128
129                         /* Dump the temporary buffer, if something is in it. */
130                         if(buf[0] != '\0')
131                                 DUMP_STR(buf);
132                 }
133
134                 else
135                         DUMP_CH(ch);
136         }
137
138 #undef DUMP_STR
139 #undef DUMP_CH
140 }
141
142 /**
143  * Convencience for stdout dumping.
144  */
145 void ir_printf(const char *fmt, ...)
146 {
147         va_list args;
148         va_start(args, fmt);
149         ir_common_vprintf(&file_appender, stdout, 0, fmt, args);
150         va_end(args);
151 }
152
153 /**
154  * Convencience for file dumping.
155  */
156 void ir_fprintf(FILE *f, const char *fmt, ...)
157 {
158         va_list args;
159         va_start(args, fmt);
160         ir_common_vprintf(&file_appender, f, 0, fmt, args);
161         va_end(args);
162 }
163
164 /**
165  * Convencience for string dumping.
166  */
167 void ir_snprintf(char *buf, size_t len, const char *fmt, ...)
168 {
169         va_list args;
170         va_start(args, fmt);
171         ir_common_vprintf(&str_appender, buf, len, fmt, args);
172         va_end(args);
173 }