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