]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/bmake/enum.h
less: upgrade to v590.
[FreeBSD/FreeBSD.git] / contrib / bmake / enum.h
1 /*      $NetBSD: enum.h,v 1.19 2021/03/15 16:00:05 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
43 const char *Enum_FlagsToString(char *, size_t, int, const EnumToStringSpec *);
44
45
46 /* For Enum_FlagsToString, the separator between flags. */
47 #define ENUM__SEP "|"
48
49 /*
50  * Generate the string that joins all possible flags, to see how large the
51  * buffer must be.
52  */
53 #define ENUM__JOIN_STR_1(v1) \
54         #v1
55 #define ENUM__JOIN_STR_2(v1, v2) \
56         ENUM__JOIN_STR_1(v1) ENUM__SEP \
57         ENUM__JOIN_STR_1(v2)
58 #define ENUM__JOIN_STR_4(v1, v2, v3, v4) \
59         ENUM__JOIN_STR_2(v1, v2) ENUM__SEP \
60         ENUM__JOIN_STR_2(v3, v4)
61 #define ENUM__JOIN_STR_8(v1, v2, v3, v4, v5, v6, v7, v8) \
62         ENUM__JOIN_STR_4(v1, v2, v3, v4) ENUM__SEP \
63         ENUM__JOIN_STR_4(v5, v6, v7, v8)
64 #define ENUM__JOIN_STR_16(v01, v02, v03, v04, v05, v06, v07, v08, \
65                           v09, v10, v11, v12, v13, v14, v15, v16) \
66         ENUM__JOIN_STR_8(v01, v02, v03, v04, v05, v06, v07, v08) ENUM__SEP \
67         ENUM__JOIN_STR_8(v09, v10, v11, v12, v13, v14, v15, v16)
68
69 #define ENUM__JOIN_2(part1, part2) \
70         part1 ENUM__SEP part2
71 #define ENUM__JOIN_3(part1, part2, part3) \
72         part1 ENUM__SEP part2 ENUM__SEP part3
73 #define ENUM__JOIN_4(part1, part2, part3, part4) \
74         part1 ENUM__SEP part2 ENUM__SEP part3 ENUM__SEP part4
75 #define ENUM__JOIN_5(part1, part2, part3, part4, part5) \
76         part1 ENUM__SEP part2 ENUM__SEP part3 ENUM__SEP part4 ENUM__SEP part5
77
78 /* List the pairs of enum value and corresponding name. */
79 #define ENUM__SPEC_1(v1) \
80         { v1, #v1 }
81 #define ENUM__SPEC_2(v1, v2) \
82         ENUM__SPEC_1(v1), \
83         ENUM__SPEC_1(v2)
84 #define ENUM__SPEC_4(v1, v2, v3, v4) \
85         ENUM__SPEC_2(v1, v2), \
86         ENUM__SPEC_2(v3, v4)
87 #define ENUM__SPEC_8(v1, v2, v3, v4, v5, v6, v7, v8) \
88         ENUM__SPEC_4(v1, v2, v3, v4), \
89         ENUM__SPEC_4(v5, v6, v7, v8)
90 #define ENUM__SPEC_16(v01, v02, v03, v04, v05, v06, v07, v08, \
91                       v09, v10, v11, v12, v13, v14, v15, v16) \
92         ENUM__SPEC_8(v01, v02, v03, v04, v05, v06, v07, v08), \
93         ENUM__SPEC_8(v09, v10, v11, v12, v13, v14, v15, v16)
94
95 #define ENUM__SPECS_2(part1, part2) \
96         { part1, part2, { 0, "" } }
97 #define ENUM__SPECS_3(part1, part2, part3) \
98         { part1, part2, part3, { 0, "" } }
99 #define ENUM__SPECS_4(part1, part2, part3, part4) \
100         { part1, part2, part3, part4, { 0, "" } }
101 #define ENUM__SPECS_5(part1, part2, part3, part4, part5) \
102         { part1, part2, part3, part4, part5, { 0, "" } }
103
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         MAKE_INLINE const char *typnam ## _ToString(char *buf, typnam value) \
110         { return Enum_FlagsToString(buf, typnam ## _ ## ToStringSize, \
111             value, typnam ## _ ## ToStringSpecs); \
112         } \
113         extern void enum_flags_rtti_dummy(void)
114
115 /*
116  * Declare the necessary data structures for calling Enum_FlagsToString
117  * for an enum with 3 flags.
118  */
119 #define ENUM_FLAGS_RTTI_3(typnam, v1, v2, v3) \
120         ENUM__FLAGS_RTTI(typnam, \
121             ENUM__SPECS_2( \
122                 ENUM__SPEC_2(v1, v2), \
123                 ENUM__SPEC_1(v3)), \
124             ENUM__JOIN_2( \
125                 ENUM__JOIN_STR_2(v1, v2), \
126                 ENUM__JOIN_STR_1(v3)))
127
128 /*
129  * Declare the necessary data structures for calling Enum_FlagsToString
130  * for an enum with 6 flags.
131  */
132 #define ENUM_FLAGS_RTTI_6(typnam, v1, v2, v3, v4, v5, v6) \
133         ENUM__FLAGS_RTTI(typnam, \
134             ENUM__SPECS_2( \
135                 ENUM__SPEC_4(v1, v2, v3, v4), \
136                 ENUM__SPEC_2(v5, v6)), \
137             ENUM__JOIN_2( \
138                 ENUM__JOIN_STR_4(v1, v2, v3, v4), \
139                 ENUM__JOIN_STR_2(v5, v6)))
140
141 /*
142  * Declare the necessary data structures for calling Enum_FlagsToString
143  * for an enum with 9 flags.
144  */
145 #define ENUM_FLAGS_RTTI_9(typnam, v1, v2, v3, v4, v5, v6, v7, v8, v9) \
146         ENUM__FLAGS_RTTI(typnam, \
147             ENUM__SPECS_2( \
148                 ENUM__SPEC_8(v1, v2, v3, v4, v5, v6, v7, v8), \
149                 ENUM__SPEC_1(v9)), \
150             ENUM__JOIN_2( \
151                 ENUM__JOIN_STR_8(v1, v2, v3, v4, v5, v6, v7, v8), \
152                 ENUM__JOIN_STR_1(v9)))
153
154 /*
155  * Declare the necessary data structures for calling Enum_FlagsToString
156  * for an enum with 31 flags.
157  */
158 #define ENUM_FLAGS_RTTI_31(typnam, \
159                      v01, v02, v03, v04, v05, v06, v07, v08, \
160                      v09, v10, v11, v12, v13, v14, v15, v16, \
161                      v17, v18, v19, v20, v21, v22, v23, v24, \
162                      v25, v26, v27, v28, v29, v30, v31) \
163     ENUM__FLAGS_RTTI(typnam, \
164         ENUM__SPECS_5( \
165             ENUM__SPEC_16(v01, v02, v03, v04, v05, v06, v07, v08, \
166                           v09, v10, v11, v12, v13, v14, v15, v16), \
167             ENUM__SPEC_8(v17, v18, v19, v20, v21, v22, v23, v24), \
168             ENUM__SPEC_4(v25, v26, v27, v28), \
169             ENUM__SPEC_2(v29, v30), \
170             ENUM__SPEC_1(v31)), \
171         ENUM__JOIN_5( \
172             ENUM__JOIN_STR_16(v01, v02, v03, v04, v05, v06, v07, v08, \
173                               v09, v10, v11, v12, v13, v14, v15, v16), \
174             ENUM__JOIN_STR_8(v17, v18, v19, v20, v21, v22, v23, v24), \
175             ENUM__JOIN_STR_4(v25, v26, v27, v28), \
176             ENUM__JOIN_STR_2(v29, v30), \
177             ENUM__JOIN_STR_1(v31)))
178
179 #endif