NetBSD/usr.bin/make/enum.h
rillig fa70c4fdc5 make(1): in debug mode, print GNode details in symbols
A string like OP_DEPENDS|OP_OPTIONAL|OP_PRECIOUS is much easier to read
and understand than the bit pattern 00000089.

The implementation in enum.h looks really bloated and ugly, but using
this API is as simple and natural as possible.  That's the trade-off.

In enum.h, I thought about choosing the numbers in the macros such that
it is always possible to combine two of them in order to reach an
arbitrary number, because of the "part1, part2" in the ENUM__SPEC macro.
The powers of 2 are not these numbers, as 7 cannot be expressed as the
sum of two of them.  Neither are the fibonacci numbers since 12 cannot
be expressed as the sum of 2 fibonacci numbers.  I tried to find a
general pattern to generate these minimal 2-sum numbers, but failed.
2020-08-24 20:15:51 +00:00

136 lines
4.9 KiB
C

/* $NetBSD: enum.h,v 1.7 2020/08/24 20:15:51 rillig Exp $ */
/*
Copyright (c) 2020 Roland Illig <rillig@NetBSD.org>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef MAKE_ENUM_H
#define MAKE_ENUM_H
/*
* Generate string representation for bitmasks.
*/
#include <stddef.h>
typedef struct {
int es_value;
const char *es_name;
} EnumToStringSpec;
const char *Enum_FlagsToString(char *, size_t, int, const EnumToStringSpec *);
const char *Enum_ValueToString(int, const EnumToStringSpec *);
#define ENUM__SEP "|"
#define ENUM__JOIN_1(v1) \
#v1
#define ENUM__JOIN_2(v1, v2) \
#v1 ENUM__SEP #v2
#define ENUM__JOIN_4(v1, v2, v3, v4) \
ENUM__JOIN_2(v1, v2) ENUM__SEP ENUM__JOIN_2(v3, v4)
#define ENUM__JOIN_8(v1, v2, v3, v4, v5, v6, v7, v8) \
ENUM__JOIN_4(v1, v2, v3, v4) ENUM__SEP ENUM__JOIN_4(v5, v6, v7, v8)
#define ENUM__JOIN_16(v01, v02, v03, v04, v05, v06, v07, v08, \
v09, v10, v11, v12, v13, v14, v15, v16) \
ENUM__JOIN_8(v01, v02, v03, v04, v05, v06, v07, v08) ENUM__SEP \
ENUM__JOIN_8(v09, v10, v11, v12, v13, v14, v15, v16)
#define ENUM__JOIN_32(v01, v02, v03, v04, v05, v06, v07, v08, \
v09, v10, v11, v12, v13, v14, v15, v16, \
v17, v18, v19, v20, v21, v22, v23, v24, \
v25, v26, v27, v28, v29, v30, v31, v32) \
ENUM__JOIN_16(v01, v02, v03, v04, v05, v06, v07, v08, \
v09, v10, v11, v12, v13, v14, v15, v16) ENUM__SEP \
ENUM__JOIN_16(v17, v18, v19, v20, v21, v22, v23, v24, \
v25, v26, v27, v28, v29, v30, v31, v32)
#define ENUM__JOIN(part1, part2) \
part1 ENUM__SEP part2
#define ENUM__RTTI(typnam, specs, joined) \
static const EnumToStringSpec typnam ## _ ## ToStringSpecs[] = specs; \
enum { typnam ## _ ## ToStringSize = sizeof joined }
#define ENUM__SPEC_1(v1) { v1, #v1 }
#define ENUM__SPEC_2(v1, v2) \
ENUM__SPEC_1(v1), \
ENUM__SPEC_1(v2)
#define ENUM__SPEC_4(v1, v2, v3, v4) \
ENUM__SPEC_2(v1, v2), \
ENUM__SPEC_2(v3, v4)
#define ENUM__SPEC_8(v1, v2, v3, v4, v5, v6, v7, v8) \
ENUM__SPEC_4(v1, v2, v3, v4), \
ENUM__SPEC_4(v5, v6, v7, v8)
#define ENUM__SPEC_16(v01, v02, v03, v04, v05, v06, v07, v08, \
v09, v10, v11, v12, v13, v14, v15, v16) \
ENUM__SPEC_8(v01, v02, v03, v04, v05, v06, v07, v08), \
ENUM__SPEC_8(v09, v10, v11, v12, v13, v14, v15, v16)
#define ENUM__SPEC(part1, part2) \
{ part1, part2, { 0, "" } }
#define ENUM_RTTI_3(typnam, v1, v2, v3) \
ENUM__RTTI(typnam, \
ENUM__SPEC(ENUM__SPEC_2(v1, v2), ENUM__SPEC_1(v3)), \
ENUM__JOIN_2(ENUM__JOIN_2(v1, v2), ENUM__JOIN_1(v3)))
#define ENUM_RTTI_8(typnam, v1, v2, v3, v4, v5, v6, v7, v8) \
ENUM__RTTI(typnam, \
ENUM__SPEC( \
ENUM__SPEC_4(v1, v2, v3, v4), \
ENUM__SPEC_4(v5, v6, v7, v8)), \
ENUM__JOIN( \
ENUM__JOIN_4(v1, v2, v3, v4), \
ENUM__JOIN_4(v5, v6, v7, v8)))
#define ENUM_RTTI_10(typnam, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10) \
ENUM__RTTI(typnam, \
ENUM__SPEC( \
ENUM__SPEC_8(v1, v2, v3, v4, v5, v6, v7, v8), \
ENUM__SPEC_2(v9, v10)), \
ENUM__JOIN( \
ENUM__JOIN_8(v1, v2, v3, v4, v5, v6, v7, v8), \
ENUM__JOIN_2(v9, v10)))
#define ENUM_RTTI_32( \
typnam, \
v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, \
v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, \
v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, \
v31, v32) \
ENUM__RTTI( \
typnam, \
ENUM__SPEC( \
ENUM__SPEC_16(v01, v02, v03, v04, v05, v06, v07, v08, \
v09, v10, v11, v12, v13, v14, v15, v16), \
ENUM__SPEC_16(v17, v18, v19, v20, v21, v22, v23, v24, \
v25, v26, v27, v28, v29, v30, v31, v32)), \
ENUM__JOIN_32( \
v01, v02, v03, v04, v05, v06, v07, v08, \
v09, v10, v11, v12, v13, v14, v15, v16, \
v17, v18, v19, v20, v21, v22, v23, v24, \
v25, v26, v27, v28, v29, v30, v31, v32))
#endif