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