some cleanups in preparation for a new tarval_from_str interface
[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 #ifdef HAVE_ALLOCA_H
22 #include <alloca.h>
23 #endif
24
25 #include "lc_opts_t.h"
26 #include "lc_opts_enum.h"
27
28 static const char *delim                        = " \t|,";
29
30 #define DECL_CB(N, op) \
31 int lc_opt_enum_ ## N ## _cb(LC_UNUSED(const char *name), LC_UNUSED(lc_opt_type_t type), void *data, size_t len, ...) \
32 { \
33         lc_opt_enum_ ## N ## _var_t *var                                                = data; \
34         const lc_opt_enum_ ## N ## _items_t *items      = var->items; \
35  \
36         va_list args; \
37         char *s, *tmp; \
38         size_t begin, end; \
39         const char *arg; \
40         int res = 0; \
41  \
42         va_start(args, len); \
43         arg = va_arg(args, const char *); \
44         va_end(args); \
45         \
46         end     = strlen(arg); \
47         tmp = s = malloc((end + 1) * sizeof(arg[0])); \
48         strcpy(s, arg); \
49         s[end]  = '\0'; \
50         \
51         end = 0; \
52         while (arg[end] != '\0') { \
53                 unsigned int i; \
54                 \
55                 begin  = end + strspn(arg + end, delim); \
56                 end    = begin + strcspn(arg + begin, delim); \
57                 s      = tmp + begin; \
58                 s[end - begin] = '\0'; \
59                 \
60                 for (i = 0; items[i].name != NULL; ++i) { \
61                         if (strcmp(s, items[i].name) == 0) { \
62                                 *var->value op items[i].value; \
63                                 res = 1; \
64                         } \
65                 } \
66         } \
67         free(tmp); \
68         return res; \
69 } \
70
71 DECL_CB(int, =)
72 DECL_CB(mask, |=)
73 DECL_CB(ptr, =)
74 DECL_CB(const_ptr, =)
75 DECL_CB(func_ptr, =)
76
77 #define DECL_DUMP(T, N, cond) \
78 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)) \
79 { \
80         lc_opt_enum_ ## N ## _var_t *var                                                = data; \
81         const lc_opt_enum_ ## N ## _items_t *items      = var->items; \
82         const char *prefix                                                              = "";                    \
83         TYPE(value) = *var->value; \
84         int i; \
85         size_t l = strlen(buf); \
86  \
87         if (l >= n) \
88                 return (int)l; \
89         n -= l; \
90         n += 2; \
91         for (i = 0; items[i].name != NULL; ++i) { \
92                 TYPE(item_value) = items[i].value; \
93                 if (cond) { \
94                         if (n <= 2) \
95                                 break; \
96                         strcat(buf, prefix); \
97                         l = strlen(items[i].name); \
98                         if (n <= l) \
99                                 break; \
100                         strcat(buf, items[i].name); \
101                         prefix = ", "; \
102                 } \
103         } \
104  \
105         return strlen(buf); \
106 } \
107
108
109 #define DECL_DUMP_VALS(T, N) \
110 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)) \
111 { \
112         lc_opt_enum_ ## N ## _var_t *var                                                = data; \
113         const lc_opt_enum_ ## N ## _items_t *items      = var->items; \
114         const char *prefix                                                              = "";                    \
115         int i; \
116         size_t l = strlen(buf); \
117  \
118         if (l >= n) \
119                 return (int)l; \
120         n -= l; \
121         n += 2; \
122         for (i = 0; items[i].name != NULL; ++i) { \
123                 if (n <= 2) \
124                         break; \
125                 strcat(buf, prefix); n -= 2; \
126                 l = strlen(items[i].name); \
127                 if (n <= l) \
128                         break; \
129                 strcat(buf, items[i].name); \
130                 n -= l; \
131                 prefix = ", "; \
132         } \
133  \
134         return strlen(buf); \
135 } \
136
137
138
139 #define TYPE(x) int x
140 DECL_DUMP(int, int, item_value == value)
141 DECL_DUMP_VALS(int, int)
142 #undef TYPE
143
144 #define TYPE(x) unsigned x
145 DECL_DUMP(unsigned, mask, (item_value & value) == item_value)
146 DECL_DUMP_VALS(unsigned, mask)
147 #undef TYPE
148
149 #define TYPE(x) void *x
150 DECL_DUMP(void *, ptr, item_value == value)
151 DECL_DUMP_VALS(void *, ptr)
152 #undef TYPE
153
154 #define TYPE(x) const void *x
155 DECL_DUMP(const void *, const_ptr, item_value == value)
156 DECL_DUMP_VALS(const void *, const_ptr)
157 #undef TYPE
158
159 #define TYPE(x) int (*x)(void)
160 DECL_DUMP(int (*)(void), func_ptr, item_value == value)
161 DECL_DUMP_VALS(int (*)(void), func_ptr)
162 #undef TYPE