]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/bmake/enum.h
Update to bmake-20201101
[FreeBSD/FreeBSD.git] / contrib / bmake / enum.h
1 /*      $NetBSD: enum.h,v 1.12 2020/09/25 15:54:50 rillig Exp $ */
2
3 /*
4  Copyright (c) 2020 Roland Illig <rillig@NetBSD.org>
5  All rights reserved.
6
7  Redistribution and use in source and binary forms, with or without
8  modification, are permitted provided that the following conditions
9  are met:
10
11  1. Redistributions of source code must retain the above copyright
12     notice, this list of conditions and the following disclaimer.
13  2. Redistributions in binary form must reproduce the above copyright
14     notice, this list of conditions and the following disclaimer in the
15     documentation and/or other materials provided with the distribution.
16
17  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19  TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
21  BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  POSSIBILITY OF SUCH DAMAGE.
28  */
29
30 #ifndef MAKE_ENUM_H
31 #define MAKE_ENUM_H
32
33 /* Generate string representations for bitmasks and simple enums. */
34
35 #include <stddef.h>
36
37 typedef struct EnumToStringSpec {
38         int es_value;
39         const char *es_name;
40 } EnumToStringSpec;
41
42 const char *Enum_FlagsToString(char *, size_t, int, const EnumToStringSpec *);
43 const char *Enum_ValueToString(int, const EnumToStringSpec *);
44
45 /* For Enum_FlagsToString, the separator between flags. */
46 #define ENUM__SEP "|"
47
48 /* Generate the string that joins all possible flags, to see how large the
49  * buffer must be. */
50 #define ENUM__JOIN_STR_1(v1) \
51         #v1
52 #define ENUM__JOIN_STR_2(v1, v2) \
53         ENUM__JOIN_STR_1(v1) ENUM__SEP \
54         ENUM__JOIN_STR_1(v2)
55 #define ENUM__JOIN_STR_4(v1, v2, v3, v4) \
56         ENUM__JOIN_STR_2(v1, v2) ENUM__SEP \
57         ENUM__JOIN_STR_2(v3, v4)
58 #define ENUM__JOIN_STR_8(v1, v2, v3, v4, v5, v6, v7, v8) \
59         ENUM__JOIN_STR_4(v1, v2, v3, v4) ENUM__SEP \
60         ENUM__JOIN_STR_4(v5, v6, v7, v8)
61 #define ENUM__JOIN_STR_16(v01, v02, v03, v04, v05, v06, v07, v08, \
62                           v09, v10, v11, v12, v13, v14, v15, v16) \
63         ENUM__JOIN_STR_8(v01, v02, v03, v04, v05, v06, v07, v08) ENUM__SEP \
64         ENUM__JOIN_STR_8(v09, v10, v11, v12, v13, v14, v15, v16)
65
66 #define ENUM__JOIN_2(part1, part2) \
67         part1 ENUM__SEP part2
68 #define ENUM__JOIN_3(part1, part2, part3) \
69         part1 ENUM__SEP part2 ENUM__SEP part3
70 #define ENUM__JOIN_4(part1, part2, part3, part4) \
71         part1 ENUM__SEP part2 ENUM__SEP part3 ENUM__SEP part4
72 #define ENUM__JOIN_5(part1, part2, part3, part4, part5) \
73         part1 ENUM__SEP part2 ENUM__SEP part3 ENUM__SEP part4 ENUM__SEP part5
74
75 /* List the pairs of enum value and corresponding name. */
76 #define ENUM__SPEC_1(v1) \
77         { v1, #v1 }
78 #define ENUM__SPEC_2(v1, v2) \
79         ENUM__SPEC_1(v1), \
80         ENUM__SPEC_1(v2)
81 #define ENUM__SPEC_4(v1, v2, v3, v4) \
82         ENUM__SPEC_2(v1, v2), \
83         ENUM__SPEC_2(v3, v4)
84 #define ENUM__SPEC_8(v1, v2, v3, v4, v5, v6, v7, v8) \
85         ENUM__SPEC_4(v1, v2, v3, v4), \
86         ENUM__SPEC_4(v5, v6, v7, v8)
87 #define ENUM__SPEC_16(v01, v02, v03, v04, v05, v06, v07, v08, \
88                       v09, v10, v11, v12, v13, v14, v15, v16) \
89         ENUM__SPEC_8(v01, v02, v03, v04, v05, v06, v07, v08), \
90         ENUM__SPEC_8(v09, v10, v11, v12, v13, v14, v15, v16)
91
92 #define ENUM__SPECS_2(part1, part2) \
93         { part1, part2, { 0, "" } }
94 #define ENUM__SPECS_3(part1, part2, part3) \
95         { part1, part2, part3, { 0, "" } }
96 #define ENUM__SPECS_4(part1, part2, part3, part4) \
97         { part1, part2, part3, part4, { 0, "" } }
98 #define ENUM__SPECS_5(part1, part2, part3, part4, part5) \
99         { part1, part2, part3, part4, part5, { 0, "" } }
100
101 /* Declare the necessary data structures for calling Enum_ValueToString. */
102 #define ENUM__VALUE_RTTI(typnam, specs) \
103         static const EnumToStringSpec typnam ## _ ## ToStringSpecs[] = specs
104
105 /* Declare the necessary data structures for calling Enum_FlagsToString. */
106 #define ENUM__FLAGS_RTTI(typnam, specs, joined) \
107         static const EnumToStringSpec typnam ## _ ## ToStringSpecs[] = specs; \
108         enum { typnam ## _ ## ToStringSize = sizeof joined }
109
110 /* Declare the necessary data structures for calling Enum_FlagsToString
111  * for an enum with 2 flags. */
112 #define ENUM_FLAGS_RTTI_2(typnam, v1, v2) \
113         ENUM__FLAGS_RTTI(typnam, \
114             ENUM__SPECS_2( \
115                 ENUM__SPEC_1(v1), \
116                 ENUM__SPEC_1(v2)), \
117             ENUM__JOIN_2( \
118                 ENUM__JOIN_STR_1(v1), \
119                 ENUM__JOIN_STR_1(v2)))
120
121 /* Declare the necessary data structures for calling Enum_FlagsToString
122  * for an enum with 3 flags. */
123 #define ENUM_FLAGS_RTTI_3(typnam, v1, v2, v3) \
124         ENUM__FLAGS_RTTI(typnam, \
125             ENUM__SPECS_2( \
126                 ENUM__SPEC_2(v1, v2), \
127                 ENUM__SPEC_1(v3)), \
128             ENUM__JOIN_2( \
129                 ENUM__JOIN_STR_2(v1, v2), \
130                 ENUM__JOIN_STR_1(v3)))
131
132 /* Declare the necessary data structures for calling Enum_FlagsToString
133  * for an enum with 6 flags. */
134 #define ENUM_FLAGS_RTTI_6(typnam, v1, v2, v3, v4, v5, v6) \
135         ENUM__FLAGS_RTTI(typnam, \
136             ENUM__SPECS_2( \
137                 ENUM__SPEC_4(v1, v2, v3, v4), \
138                 ENUM__SPEC_2(v5, v6)), \
139             ENUM__JOIN_2( \
140                 ENUM__JOIN_STR_4(v1, v2, v3, v4), \
141                 ENUM__JOIN_STR_2(v5, v6)))
142
143 /* Declare the necessary data structures for calling Enum_FlagsToString
144  * for an enum with 8 flags. */
145 #define ENUM_FLAGS_RTTI_8(typnam, v1, v2, v3, v4, v5, v6, v7, v8) \
146         ENUM__FLAGS_RTTI(typnam, \
147             ENUM__SPECS_2( \
148                 ENUM__SPEC_4(v1, v2, v3, v4), \
149                 ENUM__SPEC_4(v5, v6, v7, v8)), \
150             ENUM__JOIN_2( \
151                 ENUM__JOIN_STR_4(v1, v2, v3, v4), \
152                 ENUM__JOIN_STR_4(v5, v6, v7, v8)))
153
154 /* Declare the necessary data structures for calling Enum_ValueToString
155  * for an enum with 8 constants. */
156 #define ENUM_VALUE_RTTI_8(typnam, v1, v2, v3, v4, v5, v6, v7, v8) \
157         ENUM__VALUE_RTTI(typnam, \
158             ENUM__SPECS_2( \
159                 ENUM__SPEC_4(v1, v2, v3, v4), \
160                 ENUM__SPEC_4(v5, v6, v7, v8)))
161
162 /* Declare the necessary data structures for calling Enum_FlagsToString
163  * for an enum with 10 flags. */
164 #define ENUM_FLAGS_RTTI_10(typnam, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10) \
165         ENUM__FLAGS_RTTI(typnam, \
166             ENUM__SPECS_2( \
167                 ENUM__SPEC_8(v1, v2, v3, v4, v5, v6, v7, v8), \
168                 ENUM__SPEC_2(v9, v10)), \
169             ENUM__JOIN_2( \
170                 ENUM__JOIN_STR_8(v1, v2, v3, v4, v5, v6, v7, v8), \
171                 ENUM__JOIN_STR_2(v9, v10)))
172
173 /* Declare the necessary data structures for calling Enum_FlagsToString
174  * for an enum with 31 flags. */
175 #define ENUM_FLAGS_RTTI_31(typnam, \
176                      v01, v02, v03, v04, v05, v06, v07, v08, \
177                      v09, v10, v11, v12, v13, v14, v15, v16, \
178                      v17, v18, v19, v20, v21, v22, v23, v24, \
179                      v25, v26, v27, v28, v29, v30, v31) \
180     ENUM__FLAGS_RTTI(typnam, \
181         ENUM__SPECS_5( \
182             ENUM__SPEC_16(v01, v02, v03, v04, v05, v06, v07, v08, \
183                           v09, v10, v11, v12, v13, v14, v15, v16), \
184             ENUM__SPEC_8(v17, v18, v19, v20, v21, v22, v23, v24), \
185             ENUM__SPEC_4(v25, v26, v27, v28), \
186             ENUM__SPEC_2(v29, v30), \
187             ENUM__SPEC_1(v31)), \
188         ENUM__JOIN_5( \
189             ENUM__JOIN_STR_16(v01, v02, v03, v04, v05, v06, v07, v08, \
190                               v09, v10, v11, v12, v13, v14, v15, v16), \
191             ENUM__JOIN_STR_8(v17, v18, v19, v20, v21, v22, v23, v24), \
192             ENUM__JOIN_STR_4(v25, v26, v27, v28), \
193             ENUM__JOIN_STR_2(v29, v30), \
194             ENUM__JOIN_STR_1(v31)))
195
196 /* Declare the necessary data structures for calling Enum_FlagsToString
197  * for an enum with 32 flags. */
198 #define ENUM_FLAGS_RTTI_32(typnam, \
199                      v01, v02, v03, v04, v05, v06, v07, v08, \
200                      v09, v10, v11, v12, v13, v14, v15, v16, \
201                      v17, v18, v19, v20, v21, v22, v23, v24, \
202                      v25, v26, v27, v28, v29, v30, v31, v32) \
203     ENUM__FLAGS_RTTI(typnam, \
204         ENUM__SPECS_2( \
205             ENUM__SPEC_16(v01, v02, v03, v04, v05, v06, v07, v08, \
206                           v09, v10, v11, v12, v13, v14, v15, v16), \
207             ENUM__SPEC_16(v17, v18, v19, v20, v21, v22, v23, v24, \
208                           v25, v26, v27, v28, v29, v30, v31, v32)), \
209         ENUM__JOIN_2( \
210             ENUM__JOIN_STR_16(v01, v02, v03, v04, v05, v06, v07, v08, \
211                               v09, v10, v11, v12, v13, v14, v15, v16), \
212             ENUM__JOIN_STR_16(v17, v18, v19, v20, v21, v22, v23, v24, \
213                               v25, v26, v27, v28, v29, v30, v31, v32)))
214
215 #endif