BugFix: mode_b lowering might create new control flow (if ir_create_cond_set() is...
[libfirm] / ir / libcore / lc_opts_enum.c
1 /**
2  * @file   lc_opts_enum.c
3  * @date   24.11.2005
4  * @author Sebastian Hack
5  *
6  * Copyright (C) 2005 Universitaet Karlsruhe
7  * Released under the GPL
8  *
9  * Enum callback and dump implementation.
10  */
11 #include "config.h"
12
13 #include <stdlib.h>
14 #include <stdarg.h>
15 #include <stdio.h>
16 #include <string.h>
17
18 #ifdef _WIN32
19 #include <malloc.h>
20 #endif
21
22 #include "lc_opts_t.h"
23 #include "lc_opts_enum.h"
24
25 static const char *delim = " \t|,";
26
27 #define DECL_CB(N, op) \
28 int lc_opt_enum_ ## N ## _cb(LC_UNUSED(const char *name), LC_UNUSED(lc_opt_type_t type), void *data, size_t len, ...) \
29 { \
30         lc_opt_enum_ ## N ## _var_t *var           = (lc_opt_enum_ ## N ## _var_t*)data; \
31         const lc_opt_enum_ ## N ## _items_t *items = var->items; \
32  \
33         va_list args; \
34         char *s, *tmp; \
35         size_t begin, end; \
36         const char *arg; \
37         int res = 0; \
38  \
39         va_start(args, len); \
40         arg = va_arg(args, const char *); \
41         va_end(args); \
42         \
43         end     = strlen(arg); \
44         tmp = s = (char*)malloc((end + 1) * sizeof(arg[0])); \
45         strcpy(s, arg); \
46         s[end]  = '\0'; \
47         \
48         end = 0; \
49         while (arg[end] != '\0') { \
50                 unsigned int i; \
51                 \
52                 begin  = end + strspn(arg + end, delim); \
53                 end    = begin + strcspn(arg + begin, delim); \
54                 s      = tmp + begin; \
55                 s[end - begin] = '\0'; \
56                 \
57                 for (i = 0; items[i].name != NULL; ++i) { \
58                         if (strcmp(s, items[i].name) == 0) { \
59                                 *var->value op items[i].value; \
60                                 res = 1; \
61                         } \
62                 } \
63         } \
64         free(tmp); \
65         return res; \
66 } \
67
68 DECL_CB(int, =)
69 DECL_CB(mask, |=)
70 DECL_CB(ptr, =)
71 DECL_CB(const_ptr, =)
72 DECL_CB(func_ptr, =)
73
74 #define DECL_DUMP(T, N, cond) \
75 int lc_opt_enum_ ## N ## _dump(char *buf, size_t n, LC_UNUSED(const char *name), LC_UNUSED(lc_opt_type_t type), void *data, LC_UNUSED(size_t len)) \
76 { \
77         lc_opt_enum_ ## N ## _var_t *var           = (lc_opt_enum_ ## N ## _var_t*)data;       \
78         const lc_opt_enum_ ## N ## _items_t *items = var->items; \
79         const char *prefix                         = "";         \
80         TYPE(value) = *var->value; \
81         int i; \
82         size_t l = strlen(buf); \
83  \
84         if (l >= n) \
85                 return (int)l; \
86         n -= l; \
87         n += 2; \
88         for (i = 0; items[i].name != NULL; ++i) { \
89                 TYPE(item_value) = items[i].value; \
90                 if (cond) { \
91                         if (n <= 2) \
92                                 break; \
93                         strcat(buf, prefix); \
94                         l = strlen(items[i].name); \
95                         if (n <= l) \
96                                 break; \
97                         strcat(buf, items[i].name); \
98                         prefix = ", "; \
99                 } \
100         } \
101  \
102         return (int)strlen(buf); \
103 } \
104
105
106 #define DECL_DUMP_VALS(T, N) \
107 int lc_opt_enum_ ## N ## _dump_vals(char *buf, size_t n, LC_UNUSED(const char *name), LC_UNUSED(lc_opt_type_t type), void *data, LC_UNUSED(size_t len)) \
108 { \
109         lc_opt_enum_ ## N ## _var_t *var           = (lc_opt_enum_ ## N ## _var_t*) data;       \
110         const lc_opt_enum_ ## N ## _items_t *items = var->items; \
111         const char *prefix                         = "";         \
112         int i; \
113         size_t l = strlen(buf); \
114  \
115         if (l >= n) \
116                 return (int)l; \
117         n -= l; \
118         n += 2; \
119         for (i = 0; items[i].name != NULL; ++i) { \
120                 if (n <= 2) \
121                         break; \
122                 strcat(buf, prefix); n -= 2; \
123                 l = strlen(items[i].name); \
124                 if (n <= l) \
125                         break; \
126                 strcat(buf, items[i].name); \
127                 n -= l; \
128                 prefix = ", "; \
129         } \
130  \
131         return (int)strlen(buf); \
132 } \
133
134
135
136 #define TYPE(x) int x
137 DECL_DUMP(int, int, item_value == value)
138 DECL_DUMP_VALS(int, int)
139 #undef TYPE
140
141 #define TYPE(x) unsigned x
142 DECL_DUMP(unsigned, mask, (item_value & value) == item_value)
143 DECL_DUMP_VALS(unsigned, mask)
144 #undef TYPE
145
146 #define TYPE(x) void *x
147 DECL_DUMP(void *, ptr, item_value == value)
148 DECL_DUMP_VALS(void *, ptr)
149 #undef TYPE
150
151 #define TYPE(x) const void *x
152 DECL_DUMP(const void *, const_ptr, item_value == value)
153 DECL_DUMP_VALS(const void *, const_ptr)
154 #undef TYPE
155
156 #define TYPE(x) int (*x)(void)
157 DECL_DUMP(int (*)(void), func_ptr, item_value == value)
158 DECL_DUMP_VALS(int (*)(void), func_ptr)
159 #undef TYPE