Add is_Conv().
[libfirm] / ir / ir / irprintf.c
1 /*
2  * Copyright (C) 1995-2007 University of Karlsruhe.  All right reserved.
3  *
4  * This file is part of libFirm.
5  *
6  * This file may be distributed and/or modified under the terms of the
7  * GNU General Public License version 2 as published by the Free Software
8  * Foundation and appearing in the file LICENSE.GPL included in the
9  * packaging of this file.
10  *
11  * Licensees holding valid libFirm Professional Edition licenses may use
12  * this file in accordance with the libFirm Commercial License.
13  * Agreement provided with the Software.
14  *
15  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE.
18  */
19
20 /**
21  * @file
22  * @brief   A little printf helper unterstanding firm types
23  * @author  Sebastian Hack
24  * @date    29.11.2004
25  * @version $Id$
26  */
27 #ifdef HAVE_CONFIG_H
28 #include "config.h"
29 #endif
30
31 #ifdef HAVE_STRING_H
32 #include <string.h>
33 #endif
34 #ifdef HAVE_INTTYPES_H
35 #include <inttypes.h>
36 #endif
37
38 #include <stdlib.h>
39 #include <stdio.h>
40 #include <stdarg.h>
41
42 #include <ctype.h>
43
44 #include "firm_config.h"
45 #include "ident.h"
46 #include "irmode_t.h"
47 #include "irnode_t.h"
48 #include "entity_t.h"
49 #include "type_t.h"
50 #include "tv_t.h"
51 #include "irprintf.h"
52 #include "obst.h"
53 #include "pset.h"
54 #include "iterator.h"
55 #include "bitset.h"
56 #include "dbginfo_t.h"
57
58 #define STRNIL "(nil)"
59
60 /**
61  * Init the string.
62  */
63 static void str_init(void *object, size_t n)
64 {
65   strcpy(object, "");
66 }
67
68 /**
69  * append a char to a string buffer.
70  */
71 static void str_append_char(void *object, size_t n, char ch)
72 {
73   char buf[2];
74
75   buf[0] = ch;
76   buf[1] = 0;
77
78   strncat(object, buf, n);
79 }
80
81 /**
82  * append a string to a string buffer.
83  */
84 static void str_append_str(void *object, size_t n, const char *str)
85 {
86   strncat(object, str, n);
87 }
88
89
90 /**
91  * Init the file. i.e. do nothing.
92  */
93 static void file_init(void *object, size_t n)
94 {
95 }
96
97 /**
98  * append a char to a file.
99  */
100 static void file_append_char(void *object, size_t n, char ch)
101 {
102   fputc(ch, object);
103 }
104
105 /**
106  * append a string to a file.
107  */
108 static void file_append_str(void *object, size_t n, const char *str)
109 {
110   fputs(str, object);
111 }
112
113 /**
114  * Init the obstack. i.e. do nothing.
115  */
116 static void obst_init(void *object, size_t n)
117 {
118 }
119
120 /**
121  * append a char to a obstack.
122  */
123 static void obst_append_char(void *object, size_t n, char ch)
124 {
125   struct obstack *obst = object;
126   obstack_1grow(obst, ch);
127 }
128
129 /**
130  * append a string to a obstack.
131  */
132 static void obst_append_str(void *object, size_t n, const char *str)
133 {
134   struct obstack *obst = object;
135   obstack_grow(obst, str, strlen(str));
136 }
137
138
139 /**
140  * the file appender
141  */
142 static const appender_t file_appender = {
143   file_init,
144   file_append_char,
145   file_append_str
146 };
147
148 /**
149  * the string buffer appender
150  */
151 static const appender_t str_appender = {
152   str_init,
153   str_append_char,
154   str_append_str
155 };
156
157 /**
158  * the obstack appender.
159  */
160 static const appender_t obst_appender = {
161   obst_init,
162   obst_append_char,
163   obst_append_str
164 };
165
166 #ifndef WITH_LIBCORE
167
168 static void ir_common_vprintf(const appender_t *app, void *object,
169                 size_t limit, const char *fmt, va_list args);
170
171 static INLINE void ir_common_printf(const appender_t *app, void *object,
172                 size_t limit, const char *fmt, ...)
173 {
174   va_list args;
175
176   va_start(args, fmt);
177   ir_common_vprintf(app, object, limit, fmt, args);
178   va_end(args);
179 }
180
181 #if 0
182 static int is_std_fmt(const char *fmt)
183 {
184   static const char *fmt_re_str =
185           "^[0 -+#']?[1-9]*(\\.[1-9]*)?[hlLqjzt]?[diouxXeEfFgGaAc]";
186
187   static regex_t fmt_re;
188   static int preapred_re = 0;
189
190   regmatch_t match[1];
191   int res;
192
193   if(!preapred_re) {
194     int res = regcomp(&fmt_re, fmt_re_str, REG_EXTENDED);
195     assert(res == 0 && "Could not prepare regex");
196     preapred_re = 1;
197   }
198
199   res = regexec(&fmt_re, fmt, 1, &match[0], 0);
200
201 #if 0
202   if(res != 0) {
203     char buf[256];
204     regerror(res, &fmt_re, buf, sizeof(buf));
205     printf("%s ", buf);
206   }
207
208   printf("res: %d, start: %d, end: %d\n",
209           res, match[0].rm_so, match[0].rm_eo);
210 #endif
211
212   return res == 0 ? match[0].rm_eo : -1;
213 }
214 #endif
215
216 struct settings {
217   char flag_zero;
218   int width;
219   int flag_minus;
220   int flag_plus;
221   int flag_hash;
222 };
223
224 /* Length specifiers. */
225 enum {
226   len_char,
227   len_short,
228   len_int,
229   len_long,
230   len_long_long
231 };
232
233
234 #define MIN(x,y) ((x) < (y) ? (x) : (y))
235 #define MAX(x,y) ((x) > (y) ? (x) : (y))
236
237 static void dump_with_settings(const appender_t *app, void *object, size_t limit,
238                 const struct settings *settings, const char *str)
239 {
240   if (settings->width >= 0) {
241     int i;
242     size_t n = strlen(str);
243     int lim = MIN(settings->width, (int)limit);
244     int to_print = MIN(lim, (int)n);
245     int to_pad = to_print - lim;
246
247     if (!settings->flag_minus)
248       for(i = 0; i < to_pad; ++i)
249         app->append_char(object, lim, settings->flag_zero);
250
251     app->append_str(object, to_print, str);
252
253     if (!settings->flag_minus)
254       for(i = 0; i < to_pad; ++i)
255         app->append_char(object, lim, settings->flag_zero);
256   }
257
258   else
259     app->append_str(object, limit, str);
260 }
261
262 /**
263  * Beware: do not set the entity ld_name
264  */
265 static const char *get_entity_ld_name_ex(ir_entity *ent) {
266   if (ent->ld_name)
267     return get_entity_ld_name(ent);
268   return get_entity_name(ent);
269 }
270
271 /**
272  * emit a Firm object. Backported from irargs.
273  */
274 static void firm_emit(char *buf, int buflen, char conversion,
275     const struct settings *occ, void *X)
276 {
277 #define A(s)    occ->flag_hash ? s " ": ""
278
279   firm_kind *obj = X;
280   int i, n;
281   ir_node *block;
282   char add[64];
283   char tv_buf[256];
284   ir_entity *ent;
285
286   buf[0] = '\0';
287   add[0] = '\0';
288
289   if (! X)
290     strncpy(buf, "(null)", buflen);
291   else {
292     switch (*obj) {
293     case k_BAD:
294       snprintf(buf, buflen, "BAD");
295       snprintf(add, sizeof(add), "[%p]", X);
296       break;
297     case k_entity:
298       snprintf(buf, buflen, "%s%s", A("ent"),
299           isupper(conversion) ? get_entity_ld_name_ex(X): get_entity_name(X));
300       snprintf(add, sizeof(add), "[%ld]", get_entity_nr(X));
301       break;
302     case k_type:
303       snprintf(buf, buflen, "%s%s:%s", A("type"), get_type_tpop_name(X), get_type_name(X));
304       snprintf(add, sizeof(add), "[%ld]", get_type_nr(X));
305       break;
306     case k_ir_graph:
307       if (X == get_const_code_irg())
308         snprintf(buf, buflen, "const_code_irg ");
309       else
310         snprintf(buf, buflen, "%s%s", A("irg"), get_entity_name(get_irg_entity(X)));
311       snprintf(add, sizeof(add), "[%ld]", get_irg_graph_nr(X));
312       break;
313     case k_ir_node:
314       switch (conversion) {
315       case 'B':
316         block = is_no_Block(X) ? get_nodes_block(X) : X;
317         snprintf(buf, buflen, "%s%s%s", A("irn"), get_irn_opname(block),
318             get_mode_name(get_irn_mode(block)));
319         snprintf(add, sizeof(add), "[%ld]", get_irn_node_nr(block));
320         break;
321       case 'N':
322         snprintf(buf, buflen, "%ld", get_irn_node_nr(X));
323         break;
324       default:
325         if (is_Const(X)) {
326           tarval *tv = get_Const_tarval(X);
327
328           if (tv)
329             tarval_snprintf(tv_buf, sizeof(tv_buf), tv);
330           snprintf(buf, buflen, "%s%s%s<%s>", A("irn"), get_irn_opname(X),
331             get_mode_name(get_irn_mode(X)), tv ? tv_buf : ">NULL<");
332         }
333         else if (get_irn_op(X) == op_SymConst) {
334           switch (get_SymConst_kind(X)) {
335           case symconst_type_tag:    /* type tag */
336             snprintf(tv_buf, sizeof(tv_buf), "<ID:%s>", get_type_name(get_SymConst_type(X)));
337             break;
338           case symconst_type_size:   /* type size */
339             snprintf(tv_buf, sizeof(tv_buf), "<SIZE:%s>", get_type_name(get_SymConst_type(X)));
340             break;
341           case symconst_type_align:  /* type alignment */
342             snprintf(tv_buf, sizeof(tv_buf), "<ALIGN:%s>", get_type_name(get_SymConst_type(X)));
343             break;
344           case symconst_addr_name:   /* linker name */
345             snprintf(tv_buf, sizeof(tv_buf), "<EXT:%s>", get_id_str(get_SymConst_name(X)));
346             break;
347           case symconst_addr_ent:    /* entity name */
348             snprintf(tv_buf, sizeof(tv_buf), "<%s>", get_entity_name(get_SymConst_entity(X)));
349             break;
350           case symconst_enum_const:  /* enumeration constant */
351             snprintf(tv_buf, sizeof(tv_buf), "<ENUM:%s>", get_enumeration_name(get_SymConst_enum(X)));
352             break;
353           default:
354             tv_buf[0] = '\0';
355           }
356           snprintf(buf, buflen, "%s%s%s%s", A("irn"), get_irn_opname(X),
357             get_mode_name(get_irn_mode(X)), tv_buf);
358         }
359         else
360           snprintf(buf, buflen, "%s%s%s", A("irn"), get_irn_opname(X),
361             get_mode_name(get_irn_mode(X)));
362         snprintf(add, sizeof(add), "[%ld:%d]", get_irn_node_nr(X), get_irn_idx(X));
363       }
364       break;
365     case k_ir_mode:
366       snprintf(buf, buflen, "%s%s", A("mode"), get_mode_name(X));
367       break;
368     case k_tarval:
369       tarval_snprintf(tv_buf, sizeof(tv_buf), X);
370       snprintf(buf, buflen, "%s%s", A("tv"), tv_buf);
371       break;
372     case k_ir_loop:
373       snprintf(buf, sizeof(buf), "loop[%d:%d]", get_loop_loop_nr(X), get_loop_depth(X));
374       break;
375     case k_ir_op:
376       snprintf(buf, buflen, "%s%s", A("op"), get_op_name(X));
377       break;
378     case k_ir_compound_graph_path:
379       n = get_compound_graph_path_length(X);
380
381       for (i = 0; i < n; ++i) {
382         ent = get_compound_graph_path_node(X, i);
383
384         strncat(buf, ".", buflen);
385         strncat(buf, get_entity_name(ent), buflen);
386         if (is_Array_type(get_entity_owner(ent))) {
387           snprintf(add, sizeof(add), "[%d]",
388             get_compound_graph_path_array_index(X, i));
389           strncat(buf, add, buflen);
390         }
391       }
392       add[0] = '\0';
393       break;
394
395     default:
396       snprintf(buf, buflen, "UNKWN");
397       snprintf(add, sizeof(add), "[%p]", X);
398     }
399   }
400
401   if (occ->flag_plus)
402         strncat(buf, add, buflen);
403
404 #undef A
405 }
406
407 /**
408  * A small printf helper routine for ir nodes.
409  * @param app An appender (this determines where the stuff is dumped to).
410  * @param object A target passed to the appender.
411  * @param limit The maximum number of characters to dump.
412  * @param fmt The format string.
413  * @param args A va_list.
414  */
415 static void ir_common_vprintf(const appender_t *app, void *object,
416                 size_t limit, const char *fmt, va_list args)
417 {
418         const char *str;
419         char buf[4096];
420         int i, n;
421
422 #define DUMP_STR(s) app->append_str(object, limit, s)
423 #define DUMP_CH(ch) app->append_char(object, limit, ch)
424
425         app->init(object, limit);
426
427         for (i = 0, n = strlen(fmt); i < n; ++i) {
428                 char ch = fmt[i];
429
430                 if (ch == '%') {
431                         int len;
432                         const char *len_str = "";
433
434                         struct settings settings;
435
436                         settings.flag_hash = 0;
437                         settings.flag_zero = ' ';
438                         settings.width = -1;
439                         settings.flag_minus = 0;
440                         settings.flag_plus  = 0;
441
442                         ch = fmt[++i];
443
444                         /* Clear the temporary buffer */
445                         buf[0] = '\0';
446
447                         /* Set the string to print to the buffer by default. */
448                         str = buf;
449
450                         while (strchr("#0-+", ch)) {
451                                 switch(ch) {
452                                         case '#':
453                                                 settings.flag_hash = 1;
454                                                 break;
455                                         case '0':
456                                                 settings.flag_zero = '0';
457                                                 break;
458                                         case '-':
459                                                 settings.flag_minus = 1;
460                                                 break;
461                                         case '+':
462                                                 settings.flag_plus = 1;
463                                                 break;
464                                 }
465
466                                 ch = fmt[++i];
467                         }
468
469
470                         /* Read the field width */
471                         {
472                                 char *endptr;
473                                 int increase;
474
475                                 settings.width = (int) strtol(&fmt[i], &endptr, 10);
476                                 increase = (char *) endptr - &fmt[i];
477                                 ch = fmt[i += increase];
478                                 if(increase == 0)
479                                         settings.width = -1;
480                         }
481
482                         /* Ignore the precision */
483                         if (ch == '.')
484                                 while(isdigit(ch = fmt[++i]));
485
486                         /* read the length modifier. */
487                         switch(ch) {
488                                 case 'h':
489                                         len_str = "h";
490                                         len = len_short;
491                                         ++i;
492                                         if((ch = fmt[i]) == 'h') {
493                                                 len_str = "hh";
494                                                 len = len_char;
495                                                 ++i;
496                                         }
497                                         break;
498
499                                 case 'l':
500                                         len_str = "l";
501                                         len = len_long;
502                                         ++i;
503                                         if ((ch = fmt[i]) == 'l') {
504                                                 len_str = "ll";
505                                                 len = len_long_long;
506                                                 ++i;
507                                         }
508                                         else if ((ch = fmt[i]) == 'u') {
509                                                 len_str = "lu";
510                                                 len = len_long_long;
511                                                 ++i;
512                                         }
513                                         break;
514
515                                 default:
516                                         len = len_int;
517                         }
518
519                         /* Do the conversion specifier. */
520                         switch (ch) {
521
522                                 /* The percent itself */
523                                 case '%':
524                                         buf[0] = '%';
525                                         buf[1] = '\0';
526                                         break;
527
528                                 /* Indent */
529                                 case '>':
530                                         {
531                                                 int i, n = va_arg(args, int);
532                                                 for(i = 0; i < n && i < sizeof(buf) - 1; ++i)
533                                                         buf[i] = ' ';
534
535                                                 buf[i] = '\0';
536                                         }
537                                         break;
538
539                                 case 'c':
540                                         buf[0] = va_arg(args, int);
541                                         buf[1] = '\0';
542                                         break;
543
544                                 case 's':
545                                         str = va_arg(args, const char *);
546                                         break;
547
548                                 case 'p':
549                                         snprintf(buf, sizeof(buf), "%p", va_arg(args, void *));
550                                         break;
551
552                                 case 'i':
553                                 case 'd':
554                                 case 'u':
555                                 case 'x':
556                                 case 'X':
557                                 case 'o':
558                                         {
559                                                 char fmt_str[16];
560                                                 snprintf(fmt_str, sizeof(fmt_str), "%%%s%c", len_str, ch);
561
562                                                 switch(len) {
563                                                         case len_char:
564                                                         case len_short:
565                                                         case len_int:
566                                                                 {
567                                                                         int arg = va_arg(args, int);
568                                                                         snprintf(buf, sizeof(buf), fmt_str, arg);
569                                                                 }
570                                                                 break;
571
572                                                         case len_long:
573                                                                 {
574                                                                         long arg = va_arg(args, long);
575                                                                         snprintf(buf, sizeof(buf), fmt_str, arg);
576                                                                 }
577                                                                 break;
578
579                                                         case len_long_long:
580                                                                 {
581                                                                         int64_t arg = va_arg(args, int64_t);
582                                                                         snprintf(buf, sizeof(buf), fmt_str, arg);
583                                                                 }
584                                                                 break;
585                                                 }
586                                         }
587                                         break;
588
589                                 case 'I':
590                                         str = get_id_str(va_arg(args, ident *));
591                                         break;
592
593                                 case 't':
594         case 'e':
595         case 'E':
596         case 'T':
597         case 'n':
598         case 'O':
599         case 'm':
600         case 'B':
601         case 'P':
602         case 'F':
603         case 'f':
604           firm_emit(buf, sizeof(buf), ch, &settings, va_arg(args, void *));
605                                         break;
606
607                                 case 'b':
608                                         {
609                                                 const bitset_t *bs = va_arg(args, const bitset_t *);
610                                                 const char *prefix = "";
611                                                 unsigned long i;
612
613                                                 DUMP_CH('[');
614                                                 for(i = bitset_next_set(bs, 0); i != -1; i = bitset_next_set(bs, i + 1)) {
615                                                         snprintf(buf, sizeof(buf), "%ld", i);
616                                                         DUMP_STR(prefix);
617                                                         DUMP_STR(buf);
618                                                         prefix = ", ";
619                                                 }
620                                                 DUMP_CH(']');
621                                                 buf[0] = '\0';
622                                         }
623                                         break;
624
625                                 case '*':
626                                         {
627                                                 iterator_t *it = va_arg(args, iterator_t *);
628                                                 void *collection = va_arg(args, void *);
629                                                 void *curr;
630                                                 const char *prefix = "";
631                                                 char format = fmt[++i];
632                                                 ir_printf_cb_t *cb = format == 'C' ? va_arg(args, ir_printf_cb_t *) : NULL;
633
634                                                 assert(is_iterator(it) && "Pass an iterator interface and the collection");
635
636                                                 snprintf(buf, sizeof(buf), "%%%c", format);
637
638                                                 DUMP_CH('[');
639                                                 for(curr = it->start(collection); curr; curr = it->next(collection, curr)) {
640                                                         DUMP_STR(prefix);
641
642                                                         if(cb)
643                                                                 cb(app, object, limit, curr);
644                                                         else
645                                                                 ir_common_printf(app, object, limit, buf, curr);
646
647                                                         prefix = ", ";
648                                                 }
649                                                 it->finish(collection, curr);
650
651                                                 DUMP_CH(']');
652                                         }
653
654                                         /* clean the buffer again */
655                                         buf[0] = '\0';
656                                         break;
657
658                                 case '=':
659                                         str = get_pnc_string(va_arg(args, int));
660                                         break;
661                                 case 'G':
662                                         {
663                                                 ir_node *irn = va_arg(args, ir_node *);
664                                                 dbg_info *dbg = get_irn_dbg_info(irn);
665                                                 buf[0] = '\0';
666                                                 if (dbg && __dbg_info_snprint) {
667                                                         if (__dbg_info_snprint(buf, sizeof(buf), dbg) <= 0)
668                                                                 buf[0] = '\0';
669                                                 }
670                                                 break;
671                                         }
672                         }
673
674                         dump_with_settings(app, object, limit, &settings, str);
675                 }
676                 else
677                         DUMP_CH(ch);
678         }
679
680 #undef DUMP_STR
681 #undef DUMP_CH
682 }
683
684 /**
685  * Convenience for stdout dumping.
686  */
687 void ir_printf(const char *fmt, ...)
688 {
689         va_list args;
690         va_start(args, fmt);
691         ir_common_vprintf(&file_appender, stdout, 0, fmt, args);
692         va_end(args);
693 }
694
695 /**
696  * Convenience for file dumping.
697  */
698 void ir_fprintf(FILE *f, const char *fmt, ...)
699 {
700         va_list args;
701         va_start(args, fmt);
702         ir_common_vprintf(&file_appender, f, 0, fmt, args);
703         va_end(args);
704 }
705
706 /**
707  * Convenience for string dumping.
708  */
709 void ir_snprintf(char *buf, size_t len, const char *fmt, ...)
710 {
711         va_list args;
712         va_start(args, fmt);
713         ir_common_vprintf(&str_appender, buf, len, fmt, args);
714         va_end(args);
715 }
716
717 /**
718  * Convenience for string dumping.
719  */
720 void ir_obst_printf(struct obstack *obst, const char *fmt, ...)
721 {
722         va_list args;
723         va_start(args, fmt);
724         ir_common_vprintf(&obst_appender, obst, 0, fmt, args);
725         va_end(args);
726 }
727
728 void ir_vprintf(const char *fmt, va_list args)
729 {
730         ir_common_vprintf(&file_appender, stdout, 0, fmt, args);
731 }
732
733 void ir_vfprintf(FILE *f, const char *fmt, va_list args)
734 {
735         ir_common_vprintf(&file_appender, f, 0, fmt, args);
736 }
737
738 void ir_vsnprintf(char *buf, size_t len, const char *fmt, va_list args)
739 {
740         ir_common_vprintf(&str_appender, buf, len, fmt, args);
741 }
742
743 void ir_obst_vprintf(struct obstack *obst, const char *fmt, va_list args)
744 {
745         ir_common_vprintf(&obst_appender, obst, 0, fmt, args);
746 }
747
748 #else /* WITH_LIBCORE */
749
750 #include "irargs_t.h"
751
752 void ir_printf(const char *fmt, ...)
753 {
754         va_list args;
755
756         va_start(args, fmt);
757         lc_evprintf(firm_get_arg_env(), fmt, args);
758         va_end(args);
759 }
760
761 void ir_fprintf(FILE *f, const char *fmt, ...)
762 {
763         va_list args;
764
765         va_start(args, fmt);
766         lc_evfprintf(firm_get_arg_env(), f, fmt, args);
767         va_end(args);
768 }
769
770 void ir_snprintf(char *buf, size_t n, const char *fmt, ...)
771 {
772         va_list args;
773
774         va_start(args, fmt);
775         lc_evsnprintf(firm_get_arg_env(), buf, n, fmt, args);
776         va_end(args);
777 }
778
779 void ir_vprintf(const char *fmt, va_list args)
780 {
781         lc_evprintf(firm_get_arg_env(), fmt, args);
782 }
783
784 void ir_vfprintf(FILE *f, const char *fmt, va_list args)
785 {
786         lc_evfprintf(firm_get_arg_env(), f, fmt, args);
787 }
788
789 void ir_vsnprintf(char *buf, size_t len, const char *fmt, va_list args)
790 {
791         lc_evsnprintf(firm_get_arg_env(), buf, len, fmt, args);
792 }
793
794 void ir_obst_vprintf(struct obstack *obst, const char *fmt, va_list args)
795 {
796         lc_evoprintf(firm_get_arg_env(), obst, fmt, args);
797 }
798
799 #endif