Remove the unused parameter const arch_env_t *arch_env from be_spill().
[libfirm] / ir / libcore / lc_printf.c
1 /*
2   libcore: library for basic data structures and algorithms.
3   Copyright (C) 2005  IPD Goos, Universit"at Karlsruhe, Germany
4
5   This library is free software; you can redistribute it and/or
6   modify it under the terms of the GNU Lesser General Public
7   License as published by the Free Software Foundation; either
8   version 2.1 of the License, or (at your option) any later version.
9
10   This library is distributed in the hope that it will be useful,
11   but WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13   Lesser General Public License for more details.
14
15   You should have received a copy of the GNU Lesser General Public
16   License along with this library; if not, write to the Free Software
17   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18 */
19
20
21 /**
22  * A customizable printf clone.
23  * @author Sebastian Hack
24  * @date 4.12.2005
25  */
26 #ifdef HAVE_CONFIG_H
27 #include "config.h"
28 #endif
29
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <stddef.h>
33 #include <stdarg.h>
34 #include <string.h>
35 #include <assert.h>
36 #include <ctype.h>
37
38 #include "lc_common_t.h"
39 #include "xmalloc.h"
40 #include "lc_printf.h"
41 #include "lc_defines.h"
42 #include "hashptr.h"
43 #include "set.h"
44
45 /* printf implementation */
46
47 typedef struct _lc_arg_t {
48         struct _lc_arg_t *next;
49         const char *name;
50         char letter;
51         int lc_arg_type;
52         const lc_arg_handler_t *handler;
53 } lc_arg_t;
54
55 struct _lc_arg_env_t {
56         set *args;                                      /**< Map for named arguments. */
57         lc_arg_t *lower[26];            /**< Map for lower conversion specifiers. */
58         lc_arg_t *upper[26];            /**< Map for upper conversion specifiers. */
59 };
60
61 /** The default argument environment. */
62 static lc_arg_env_t *default_env = NULL;
63
64 static INLINE lc_arg_env_t *_lc_arg_get_default_env(void)
65 {
66         if(!default_env)
67                 default_env = lc_arg_add_std(lc_arg_new_env());
68
69         return default_env;
70 }
71
72 lc_arg_env_t *lc_arg_get_default_env(void)
73 {
74         return _lc_arg_get_default_env();
75 }
76
77 static int lc_arg_cmp(const void *p1, const void *p2, UNUSED(size_t size))
78 {
79         const lc_arg_t *a1 = p1;
80         const lc_arg_t *a2 = p2;
81         return strcmp(a1->name, a2->name);
82 }
83
84
85 lc_arg_env_t *lc_arg_new_env(void)
86 {
87         lc_arg_env_t *env = XMALLOCZ(lc_arg_env_t);
88         env->args = new_set(lc_arg_cmp, 16);
89         return env;
90 }
91
92 void lc_arg_free_env(lc_arg_env_t *env)
93 {
94         del_set(env->args);
95         free(env);
96 }
97
98 int lc_arg_register(lc_arg_env_t *env, const char *name, char letter, const lc_arg_handler_t *handler)
99 {
100         lc_arg_t arg;
101         lc_arg_t *ent;
102         int base = 0;
103         lc_arg_t **map = NULL;
104
105         arg.name = name;
106         arg.letter = letter;
107         arg.handler = handler;
108
109         if(isupper(letter)) {
110                 map = env->upper;
111                 base = 'A';
112         }
113         else if(islower(letter)) {
114                 map = env->lower;
115                 base = 'a';
116         }
117
118         ent = set_insert(env->args, &arg, sizeof(arg), HASH_STR(name, strlen(name)));
119
120         if(ent && base != 0)
121                 map[letter - base] = ent;
122
123         return ent != NULL;
124 }
125
126 void lc_arg_unregister(UNUSED(lc_arg_env_t *env), UNUSED(const char *name))
127 {
128 }
129
130 int lc_arg_append(lc_appendable_t *app, const lc_arg_occ_t *occ, const char *str, size_t len)
131 {
132         char pad = ' ';
133
134         /* Set the padding to zero, if the zero is given and we are not left
135          * justified. (A minus overrides the zero). See printf(3). */
136         if(!occ->flag_minus && occ->flag_zero)
137                 pad = '0';
138
139         return lc_appendable_snwadd(app, str, len, LC_MAX(0, occ->width), occ->flag_minus, pad);
140 }
141
142
143 static int dispatch_snprintf(char *buf, size_t len, const char *fmt,
144                 int lc_arg_type, const lc_arg_value_t *val)
145 {
146         int res = 0;
147
148         switch(lc_arg_type) {
149 #define LC_ARG_TYPE(type,name) \
150                 case lc_arg_type_ ## name: res = snprintf(buf, len, fmt, val->v_ ## name); break;
151 #include "lc_printf_arg_types.def"
152 #undef LC_ARG_TYPE
153         }
154
155         return res;
156 }
157
158 static char *make_fmt(char *buf, size_t len, const lc_arg_occ_t *occ)
159 {
160         char mod[64];
161         char prec[16];
162         char width[16];
163
164         prec[0] = '\0';
165         width[0] = '\0';
166
167         if(occ->precision > 0)
168                 snprintf(prec, sizeof(prec), ".%d", occ->precision);
169
170         if(occ->width > 0)
171                 snprintf(width, sizeof(width), "%d", occ->width);
172
173         assert(occ->modifier && "modifier must not be NULL");
174         strncpy(mod, occ->modifier, sizeof(mod) - 1);
175         mod[LC_MIN(sizeof(mod) - 1, occ->modifier_length)] = '\0';
176
177         snprintf(buf, len, "%%%s%s%s%s%s%s%s%s%c",
178                         occ->flag_space ? "#" : "",
179                         occ->flag_hash ? "#" : "",
180                         occ->flag_plus ? "+" : "",
181                         occ->flag_minus ? "-" : "",
182                         occ->flag_zero ? "0" : "",
183                         width, prec,
184                         mod, occ->conversion);
185
186         return buf;
187 }
188
189 /**
190  * Standard argument handler.
191  */
192 static int std_get_lc_arg_type(const lc_arg_occ_t *occ)
193 {
194         int modlen = occ->modifier_length;
195
196         /* check, if the type can be derived from the modifier */
197         if (modlen > 0) {
198                 const char *mod = occ->modifier;
199                 switch (mod[0]) {
200                         case 'l':
201                                 return modlen > 1 && mod[1] == 'l' ? lc_arg_type_long_long : lc_arg_type_long;
202 #define TYPE_CASE(letter,type) case letter: return lc_arg_type_ ## type;
203 #if 0
204                         TYPE_CASE('j', intmax_t);
205                         TYPE_CASE('z', size_t);
206                         TYPE_CASE('t', ptrdiff_t);
207 #endif
208                         TYPE_CASE('L', long_double);
209 #undef TYPE_CASE
210                 }
211         }
212
213         /* The type is given by the conversion specifier and cannot be
214          * determined from the modifier. */
215         switch (occ->conversion) {
216                 case 'e':
217                 case 'E':
218                 case 'f':
219                 case 'F':
220                 case 'g':
221                 case 'G':
222                         return lc_arg_type_double;
223                 case 's':
224                 case 'n':
225                 case 'p':
226                         return lc_arg_type_ptr;
227                 default:
228                         return lc_arg_type_int;
229         }
230 }
231
232 static int std_emit(lc_appendable_t *app, const lc_arg_occ_t *occ, const lc_arg_value_t *val)
233 {
234         char fmt[32];
235         int res = 0;
236
237         make_fmt(fmt, sizeof(fmt), occ);
238
239         switch(occ->conversion) {
240
241                 /* Store the number of written characters in the given
242                  * int pointer location */
243                 case 'n':
244                         {
245                                 int *num = val->v_ptr;
246                                 *num = app->written;
247                         }
248                         break;
249
250                 /* strings are dumped directly, since they can get really big. A
251                  * buffer of 128 letters for all other types should be enough. */
252                 case 's':
253                         {
254                                 const char *str = val->v_ptr;
255                                 res = lc_arg_append(app, occ, str, strlen(str));
256                         }
257                         break;
258
259                 default:
260                         {
261                                 int len = LC_MAX(128, occ->width + 1);
262                                 char *buf = XMALLOCN(char, len);
263                                 res = dispatch_snprintf(buf, len, fmt, occ->lc_arg_type, val);
264                                 res = lc_appendable_snadd(app, buf, res);
265                                 xfree(buf);
266                         }
267         }
268
269         return res;
270 }
271
272 static const lc_arg_handler_t std_handler = {
273         std_get_lc_arg_type,
274         std_emit
275 };
276
277 lc_arg_env_t *lc_arg_add_std(lc_arg_env_t *env)
278 {
279         lc_arg_register(env, "std:c", 'c', &std_handler);
280         lc_arg_register(env, "std:i", 'i', &std_handler);
281         lc_arg_register(env, "std:d", 'd', &std_handler);
282         lc_arg_register(env, "std:o", 'o', &std_handler);
283         lc_arg_register(env, "std:u", 'u', &std_handler);
284         lc_arg_register(env, "std:x", 'x', &std_handler);
285         lc_arg_register(env, "std:X", 'X', &std_handler);
286
287         lc_arg_register(env, "std:e", 'e', &std_handler);
288         lc_arg_register(env, "std:E", 'E', &std_handler);
289         lc_arg_register(env, "std:f", 'f', &std_handler);
290         lc_arg_register(env, "std:F", 'F', &std_handler);
291         lc_arg_register(env, "std:g", 'g', &std_handler);
292         lc_arg_register(env, "std:G", 'G', &std_handler);
293
294         lc_arg_register(env, "std:s", 's', &std_handler);
295         lc_arg_register(env, "std:p", 'p', &std_handler);
296         lc_arg_register(env, "std:n", 'n', &std_handler);
297
298         return env;
299 }
300
301 static char *read_int(const char *s, int *value)
302 {
303         char *endptr;
304         int res = (int) strtol(s, &endptr, 10);
305         *value = endptr == s ? -1 : res;
306         return endptr;
307 }
308
309 /* Generic printf() function. */
310
311 int lc_evpprintf(const lc_arg_env_t *env, lc_appendable_t *app, const char *fmt, va_list args)
312 {
313         int res = 0;
314         const char *s;
315         const char *last = fmt + strlen(fmt);
316
317         /* Find the first % */
318         s = strchr(fmt, '%');
319
320         /* Emit the text before the first % was found */
321         lc_appendable_snadd(app, fmt, (s ? s : last) - fmt);
322
323         while(s != NULL) {
324                 lc_arg_occ_t occ;
325                 lc_arg_value_t val;
326                 const lc_arg_t *arg = NULL;
327                 const char *old;
328                 char ch;
329
330                 /* We must be at a '%' */
331                 assert(*s == '%');
332
333                 /* Reset the occurrence structure */
334                 memset(&occ, 0, sizeof(occ));
335
336                 /* Eat all flags and set the corresponding flags in the occ struct */
337                 for(++s; strchr("#0-+", *s); ++s) {
338                         switch(*s) {
339                                 case '#':
340                                         occ.flag_hash = 1;
341                                         break;
342                                 case '0':
343                                         occ.flag_zero = 1;
344                                         break;
345                                 case '-':
346                                         occ.flag_minus = 1;
347                                         break;
348                                 case '+':
349                                         occ.flag_plus = 1;
350                                         break;
351                                 case ' ':
352                                         occ.flag_space = 1;
353                                         break;
354                         }
355                 }
356
357                 /* Read the width if given */
358                 s = read_int(s, &occ.width);
359
360                 occ.precision = -1;
361
362                 /* read the precision if given */
363                 if(*s == '.') {
364                         int val;
365                         s = read_int(s + 1, &val);
366
367                         /* Negative or lacking precision after a '.' is treated as
368                          * precision 0. */
369                         occ.precision = LC_MAX(0, val);
370                 }
371
372                 /*
373                  * Now, we can either have:
374                  * - a named argument like {node}
375                  * - some modifiers followed by a conversion specifier
376                  * - or some other character, which ends this format invalidly
377                  */
378                 ch = *s;
379                 switch(ch) {
380                         case '%':
381                                 s++;
382                                 res += lc_appendable_chadd(app, '%');
383                                 break;
384                         case '{':
385                                 {
386                                         const char *named = ++s;
387
388                                         /* Read until the closing brace or end of the string. */
389                                         for(ch = *s; ch != '}' && ch != '\0'; ch = *++s);
390
391                                         if(s - named) {
392                                                 int n = s - named;
393                                                 char *name;
394                                                 lc_arg_t tmp;
395
396                                                 name = malloc(sizeof(char) * (n + 1));
397                                                 memcpy(name, named, sizeof(char) * n);
398                                                 name[n] = '\0';
399                                                 tmp.name = name;
400
401                                                 arg = set_find(env->args, &tmp, sizeof(tmp), HASH_STR(named, n));
402                                                 occ.modifier = "";
403                                                 occ.modifier_length = 0;
404
405                                                 /* Set the conversion specifier of the occurrence to the
406                                                  * letter specified in the argument description. */
407                                                 if(arg)
408                                                         occ.conversion = arg->letter;
409
410                                                 free(name);
411
412                                                 /* If we ended with a closing brace, move the current
413                                                  * pointer after it, since it is not to be dumped. */
414                                                 if(ch == '}')
415                                                         s++;
416                                         }
417                                 }
418                                 break;
419
420                         default:
421                                 {
422                                         const char *mod = s;
423
424                                         /* Read, as long there are letters */
425                                         while(isalpha(ch) && !arg) {
426                                                 int base = 'a';
427                                                 lc_arg_t * const *map = env->lower;
428
429                                                 /* If uppercase, select the uppercase map from the environment */
430                                                 if(isupper(ch)) {
431                                                         base = 'A';
432                                                         map = env->upper;
433                                                 }
434
435                                                 if(map[ch - base] != NULL) {
436                                                         occ.modifier = mod;
437                                                         occ.modifier_length = s - mod;
438                                                         occ.conversion = ch;
439                                                         arg = map[ch - base];
440                                                 }
441
442                                                 ch = *++s;
443                                         }
444                                 }
445                 }
446
447                 /* Call the handler if an argument was determined */
448                 if(arg != NULL && arg->handler != NULL) {
449                         const lc_arg_handler_t *handler = arg->handler;
450
451                         /* Let the handler determine the type of the argument based on the
452                          * information gathered. */
453                         occ.lc_arg_type = handler->get_lc_arg_type(&occ);
454
455                         /* Store the value according to argument information */
456                         switch(occ.lc_arg_type) {
457 #define LC_ARG_TYPE(type,name) case lc_arg_type_ ## name: val.v_ ## name = va_arg(args, type); break;
458 #include "lc_printf_arg_types.def"
459 #undef LC_ARG_TYPE
460                         }
461
462                         /* Finally, call the handler. */
463                         res += handler->emit(app, &occ, &val);
464                 }
465
466                 old = s;
467                 s = strchr(s, '%');
468                 res += lc_appendable_snadd(app, old, (s ? s : last) - old);
469         }
470
471         return res;
472 }
473
474 /* Convenience implementations */
475
476 int lc_epprintf(const lc_arg_env_t *env, lc_appendable_t *app, const char *fmt, ...)
477 {
478         int res;
479         va_list args;
480         va_start(args, fmt);
481         res = lc_evpprintf(env, app, fmt, args);
482         va_end(args);
483         return res;
484 }
485
486 int lc_pprintf(lc_appendable_t *app, const char *fmt, ...)
487 {
488         int res;
489         va_list args;
490         va_start(args, fmt);
491         res = lc_vpprintf(app, fmt, args);
492         va_end(args);
493         return res;
494 }
495
496 int lc_vpprintf(lc_appendable_t *app, const char *fmt, va_list args)
497 {
498         return lc_evpprintf(_lc_arg_get_default_env(), app, fmt, args);
499 }
500
501 int lc_eprintf(const lc_arg_env_t *env, const char *fmt, ...)
502 {
503         int res;
504         va_list args;
505         va_start(args, fmt);
506         res = lc_efprintf(env, stdout, fmt, args);
507         va_end(args);
508         return res;
509 }
510
511 int lc_esnprintf(const lc_arg_env_t *env, char *buf, size_t len, const char *fmt, ...)
512 {
513         int res;
514         va_list args;
515         va_start(args, fmt);
516         res = lc_evsnprintf(env, buf, len, fmt, args);
517         va_end(args);
518         return res;
519 }
520
521 int lc_efprintf(const lc_arg_env_t *env, FILE *file, const char *fmt, ...)
522 {
523         int res;
524         va_list args;
525         va_start(args, fmt);
526         res = lc_evfprintf(env, file, fmt, args);
527         va_end(args);
528         return res;
529 }
530
531 int lc_eoprintf(const lc_arg_env_t *env, struct obstack *obst, const char *fmt, ...)
532 {
533         int res;
534         va_list args;
535         va_start(args, fmt);
536         res = lc_evoprintf(env, obst, fmt, args);
537         va_end(args);
538         return res;
539 }
540
541 int lc_evprintf(const lc_arg_env_t *env, const char *fmt, va_list args)
542 {
543         return lc_evfprintf(env, stdout, fmt, args);
544 }
545
546 int lc_evsnprintf(const lc_arg_env_t *env, char *buf, size_t len, const char *fmt, va_list args)
547 {
548         int res;
549         lc_appendable_t app;
550
551         lc_appendable_init(&app, lc_appendable_string, buf, len);
552         res = lc_evpprintf(env, &app, fmt, args);
553         lc_appendable_finish(&app);
554         return res;
555 }
556
557 int lc_evfprintf(const lc_arg_env_t *env, FILE *f, const char *fmt, va_list args)
558 {
559         int res;
560         lc_appendable_t app;
561
562         lc_appendable_init(&app, lc_appendable_file, f, 0);
563         res = lc_evpprintf(env, &app, fmt, args);
564         lc_appendable_finish(&app);
565         return res;
566 }
567
568 int lc_evoprintf(const lc_arg_env_t *env, struct obstack *obst, const char *fmt, va_list args)
569 {
570         int res;
571         lc_appendable_t app;
572
573         lc_appendable_init(&app, lc_appendable_obstack, obst, 0);
574         res = lc_evpprintf(env, &app, fmt, args);
575         lc_appendable_finish(&app);
576         return res;
577 }
578
579
580 int lc_printf(const char *fmt, ...)
581 {
582         int res;
583         va_list args;
584         va_start(args, fmt);
585         res = lc_vprintf(fmt, args);
586         va_end(args);
587         return res;
588 }
589
590 int lc_snprintf(char *buf, size_t len, const char *fmt, ...)
591 {
592         int res;
593         va_list args;
594         va_start(args, fmt);
595         res = lc_vsnprintf(buf, len, fmt, args);
596         va_end(args);
597         return res;
598 }
599
600 int lc_fprintf(FILE *f, const char *fmt, ...)
601 {
602         int res;
603         va_list args;
604         va_start(args, fmt);
605         res = lc_vfprintf(f, fmt, args);
606         va_end(args);
607         return res;
608 }
609
610 int lc_oprintf(struct obstack *obst, const char *fmt, ...)
611 {
612         int res;
613         va_list args;
614         va_start(args, fmt);
615         res = lc_voprintf(obst, fmt, args);
616         va_end(args);
617         return res;
618 }
619
620
621 int lc_vprintf(const char *fmt, va_list args)
622 {
623         return lc_evprintf(_lc_arg_get_default_env(), fmt, args);
624 }
625
626 int lc_vsnprintf(char *buf, size_t len, const char *fmt, va_list args)
627 {
628         return lc_evsnprintf(_lc_arg_get_default_env(), buf, len, fmt, args);
629 }
630
631 int lc_vfprintf(FILE *f, const char *fmt, va_list args)
632 {
633         return lc_evfprintf(_lc_arg_get_default_env(), f, fmt, args);
634 }
635
636 int lc_voprintf(struct obstack *obst, const char *fmt, va_list args)
637 {
638         return lc_evoprintf(_lc_arg_get_default_env(), obst, fmt, args);
639 }