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