26 /**************************************************************************
27 * THIS FILE WAS GENERATED *
28 * Script: utility/generate_specenum.py *
29 * DO NOT CHANGE THIS FILE *
30 **************************************************************************/
32/***********************************************************************
33 Freeciv - Copyright (C) 2009
34 This program is free software; you can redistribute it and/or modify
35 it under the terms of the GNU General Public License as published by
36 the Free Software Foundation; either version 2, or (at your option)
39 This program is distributed in the hope that it will be useful,
40 but WITHOUT ANY WARRANTY; without even the implied warranty of
41 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
42 GNU General Public License for more details.
43***********************************************************************/
49 * Include this file to define tools to manage enumerators. First of all,
50 * before including this file, you *MUST* define the following macros:
51 * - SPECENUM_NAME: is the name of the enumeration (e.g. 'foo' for defining
53 * - SPECENUM_VALUE%d: define like this all values of your enumeration type
54 * (e.g. '#define SPECENUM_VALUE0 FOO_FIRST').
56 * The following macros *CAN* be defined:
57 * - SPECENUM_INVALID: specifies a value that your 'foo_invalid()' function
58 * will return. Note it cannot be a declared value with SPECENUM_VALUE%d.
59 * - SPECENUM_BITWISE: defines if the enumeration should be like
60 * [1, 2, 4, 8, etc...] instead of the default of [0, 1, 2, 3, etc...].
61 * - SPECENUM_ZERO: can be defined only if SPECENUM_BITWISE was also defined.
62 * It defines a 0 value. Note that if you don't declare this value, 0 passed
63 * to the 'foo_is_valid()' function will return FALSE.
64 * - SPECENUM_COUNT: a name for the maximum enumeration number plus 1. For
65 * enums where every element from 0 to the maximum is defined, this is the
66 * number of elements in the enum. This value is suitable to size an array
67 * indexed by the enum. It can not be used in combination with
68 * SPECENUM_BITWISE. SPECENUM_is_valid() will return the invalid element
71 * SPECENUM_VALUE%dNAME, SPECENUM_ZERONAME, SPECENUM_COUNTNAME: Can be used
72 * to bind a string to the particular enumerator to be returned by
73 * SPECENUM_name(), etc. If not defined, the default name for 'FOO_FIRST'
74 * is '"FOO_FIRST"'. A name can be qualified. The qualification will only
75 * be used for its translation. The returned name will be unqualified. To
76 * mark a name as translatable use N_().
78 * SPECENUM_NAMEOVERRIDE: call callback function foo_name_cb(enum foo),
79 * defined by specenum user, to get name of the enum value. If the function
80 * returns nullptr, compiled in names are used.
82 * SPECENUM_NAME_UPDATER: call callback function foo_name_update_cb(old_name),
83 * defined by specenum user, to get current name to search enum value with.
85 * SPECENUM_BITVECTOR: specifies the name of a bit vector for the enum
86 * values. It can not be used in combination with SPECENUM_BITWISE.
88 * Assuming SPECENUM_NAME were 'foo', including this file would provide
89 * the definition for the enumeration type 'enum foo', and prototypes for
90 * the following functions:
91 * bool foo_is_bitwise(void);
92 * enum foo foo_min(void);
93 * enum foo foo_max(void);
94 * enum foo foo_invalid(void);
95 * bool foo_is_valid(enum foo);
97 * enum foo foo_begin(void);
98 * enum foo foo_end(void);
99 * enum foo foo_next(enum foo);
101 * const char *foo_name(enum foo);
102 * const char *foo_translated_name(enum foo);
103 * enum foo foo_by_name(const char *name,
104 * int (*strcmp_func)(const char *, const char *));
107 * #define SPECENUM_NAME test
108 * #define SPECENUM_BITWISE
109 * #define SPECENUM_VALUE0 TEST0
110 * #define SPECENUM_VALUE1 TEST1
111 * #define SPECENUM_VALUE3 TEST3
112 * #include "specenum_gen.h"
115 * static const char *strings[] = {
116 * "TEST1", "test3", "fghdf", nullptr
121 * log_verbose("enum test [%d; %d]%s",
122 * test_min(), test_max(), test_bitwise ? " bitwise" : "");
124 * for (e = test_begin(); e != test_end(); e = test_next(e)) {
125 * log_verbose("Value %d is %s", e, test_name(e));
128 * for (i = 0; strings[i]; i++) {
129 * e = test_by_name(strings[i], fc_strcasecmp);
130 * if (test_is_valid(e)) {
131 * log_verbose("Value is %d for %s", e, strings[i]);
133 * log_verbose("%s is not a valid name", strings[i]);
139 * enum test [1, 8] bitwise
143 * Value is 2 for TEST1
144 * Value is 8 for test3
145 * fghdf is not a valid name
153#endif /* __cplusplus */
156#include "fcintl.h" /* translation */
157#include "log.h" /* fc_assert. */
158#include "support.h" /* bool type. */
161#error Must define a SPECENUM_NAME to use this header
164#define SPECENUM_PASTE_(x, y) x ## y
165#define SPECENUM_PASTE(x, y) SPECENUM_PASTE_(x, y)
167#define SPECENUM_STRING_(x) #x
168#define SPECENUM_STRING(x) SPECENUM_STRING_(x)
170#define SPECENUM_FOO(suffix) SPECENUM_PASTE(SPECENUM_NAME, suffix)
172#ifndef SPECENUM_INVALID
173#define SPECENUM_INVALID ((enum SPECENUM_NAME) -1)
176#ifdef SPECENUM_BITWISE
178#error Cannot define SPECENUM_COUNT when SPECENUM_BITWISE is defined.
180#define SPECENUM_VALUE(value) (1 << value)
181#else /* SPECENUM_BITWISE */
183#error Cannot define SPECENUM_ZERO when SPECENUM_BITWISE is not defined.
185#define SPECENUM_VALUE(value) (value)
186#endif /* SPECENUM_BITWISE */
188#ifdef SPECENUM_BITVECTOR
189#include "bitvector.h"
190#ifdef SPECENUM_BITWISE
191#error SPECENUM_BITWISE and SPECENUM_BITVECTOR cannot both be defined.
192#endif /* SPECENUM_BITWISE */
193#endif /* SPECENUM_BITVECTOR */
195#undef SPECENUM_MIN_VALUE
196#undef SPECENUM_MAX_VALUE
217/* Enumeration definition. */
224 for i
in range(max_enum_values):
226#ifdef SPECENUM_VALUE%d
227 SPECENUM_VALUE%d = SPECENUM_VALUE(%d),
228# ifndef SPECENUM_MIN_VALUE
229# define SPECENUM_MIN_VALUE SPECENUM_VALUE%d
231# ifdef SPECENUM_MAX_VALUE
232# undef SPECENUM_MAX_VALUE
234# define SPECENUM_MAX_VALUE SPECENUM_VALUE%d
238# define SPECENUM_SIZE (%d + 1)
239#endif /* SPECENUM_VALUE%d */
244 SPECENUM_COUNT = (SPECENUM_MAX_VALUE + 1),
245#endif /* SPECENUM_COUNT */
250 for i
in range(max_enum_values):
255/**********************************************************************//**
256 Returns TRUE if this enumeration is in bitwise mode.
257**************************************************************************/
258fc__attribute((const))
259static inline bool SPECENUM_FOO(_is_bitwise)(void)
261#ifdef SPECENUM_BITWISE
271/**********************************************************************//**
272 Returns the value of the minimal enumerator.
273**************************************************************************/
274fc__attribute((const))
275static inline enum SPECENUM_NAME SPECENUM_FOO(_min)(void)
277 return SPECENUM_MIN_VALUE;
283/**********************************************************************//**
284 Returns the value of the maximal enumerator.
285**************************************************************************/
286fc__attribute((const))
287static inline enum SPECENUM_NAME SPECENUM_FOO(_max)(void)
289 return SPECENUM_MAX_VALUE;
295/**********************************************************************//**
296 Returns TRUE if this enumerator was defined.
297**************************************************************************/
298fc__attribute((const))
299static inline bool SPECENUM_FOO(_is_valid)(enum SPECENUM_NAME enumerator)
301#ifdef SPECENUM_BITWISE
302 static const unsigned long valid = (
305 for i
in range(max_enum_values):
307# ifdef SPECENUM_VALUE%d
314 FC_STATIC_ASSERT(sizeof(valid) * 8 >= SPECENUM_SIZE,
318 if (enumerator == SPECENUM_ZERO) {
322 return (enumerator & valid) == enumerator;
324 static const bool valid[] = {''')
326 for i
in range(max_enum_values):
328# if %d < SPECENUM_SIZE
329# ifdef SPECENUM_VALUE%d
339 FC_STATIC_ASSERT(ARRAY_SIZE(valid) == SPECENUM_SIZE,
340 valid_array_size_check);
342 return ((unsigned)enumerator < ARRAY_SIZE(valid)
343 && valid[enumerator]);
344#endif /* SPECENUM_BITWISE */
350/**********************************************************************//**
351 Returns an invalid enumerator value.
352**************************************************************************/
353fc__attribute((const))
354static inline enum SPECENUM_NAME SPECENUM_FOO(_invalid)(void)
356 fc_assert(!SPECENUM_FOO(_is_valid(SPECENUM_INVALID)));
357 return SPECENUM_INVALID;
363/**********************************************************************//**
364 Beginning of the iteration of the enumerators.
365**************************************************************************/
366fc__attribute((const))
367static inline enum SPECENUM_NAME SPECENUM_FOO(_begin)(void)
369 return SPECENUM_FOO(_min)();
375/**********************************************************************//**
376 End of the iteration of the enumerators.
377**************************************************************************/
378fc__attribute((const))
379static inline enum SPECENUM_NAME SPECENUM_FOO(_end)(void)
381 return SPECENUM_FOO(_invalid)();
387/**********************************************************************//**
388 Find the next valid enumerator value.
389**************************************************************************/
390fc__attribute((const))
391static inline enum SPECENUM_NAME SPECENUM_FOO(_next)(enum SPECENUM_NAME e)
394#ifdef SPECENUM_BITWISE
395 e = (enum SPECENUM_NAME)(e << 1);
397 e = (enum SPECENUM_NAME)(e + 1);
400 if (e > SPECENUM_FOO(_max)()) {
401 /* End of the iteration. */
402 return SPECENUM_FOO(_invalid)();
404 } while (!SPECENUM_FOO(_is_valid)(e));
412#ifdef SPECENUM_NAMEOVERRIDE
413const char *SPECENUM_FOO(_name_cb)(enum SPECENUM_NAME value);
414#endif /* SPECENUM_NAMEOVERRIDE */
416/**********************************************************************//**
417 Returns the name of the enumerator.
418**************************************************************************/
419#ifndef SPECENUM_NAMEOVERRIDE
420fc__attribute((const))
422static inline const char *SPECENUM_FOO(_name)(enum SPECENUM_NAME enumerator)
425 static const char *names[SPECENUM_SIZE + 1];
427 static const char *names[SPECENUM_SIZE];
429 static bool initialized = FALSE;
431#ifdef SPECENUM_NAMEOVERRIDE
433 const char *name = SPECENUM_FOO(_name_cb)(enumerator);
435 if (name != nullptr) {
439#endif /* SPECENUM_NAMEOVERRIDE */
441 if (!initialized) {''')
443 for i
in range(max_enum_values):
445#if %d < SPECENUM_SIZE
446# ifndef SPECENUM_VALUE%d
448# elif defined(SPECENUM_VALUE%dNAME)
449 names[%d] = Qn_(SPECENUM_VALUE%dNAME);
451 names[%d] = SPECENUM_STRING(SPECENUM_VALUE%d);
453#endif'''%(i,i,i,i,i,i,i,i))
458# ifdef SPECENUM_COUNTNAME
459 names[SPECENUM_COUNT] = Qn_(SPECENUM_COUNTNAME);
461 names[SPECENUM_COUNT] = SPECENUM_STRING(SPECENUM_COUNT);
467#ifdef SPECENUM_BITWISE
469 if (enumerator == SPECENUM_ZERO) {
470# ifdef SPECENUM_ZERONAME
471 return Qn_(SPECENUM_ZERONAME);
473 return SPECENUM_STRING(SPECENUM_ZERO);
480 for (i = 0; i < ARRAY_SIZE(names); i++) {
481 if (1 << i == enumerator) {
487 if ((unsigned)enumerator < ARRAY_SIZE(names)) {
488 return names[enumerator];
490#endif /* SPECENUM_BITWISE */
499/**********************************************************************//**
500 Returns the enumerator for the name or *_invalid() if not found.
501**************************************************************************/
502static inline enum SPECENUM_NAME SPECENUM_FOO(_by_name)
503 (const char *name, int (*strcmp_func)(const char *, const char *))
505 enum SPECENUM_NAME e;
506 const char *enum_name;
507 const char *current_name = name;
509#ifdef SPECENUM_NAME_UPDATER
510 current_name = SPECENUM_FOO(_name_update_cb)(name);
513 for (e = SPECENUM_FOO(_begin)(); e != SPECENUM_FOO(_end)();
514 e = SPECENUM_FOO(_next)(e)) {
515 if ((enum_name = SPECENUM_FOO(_name)(e))
516 && 0 == strcmp_func(current_name, enum_name)) {
521 return SPECENUM_FOO(_invalid)();
527/**********************************************************************//**
528 Returns the translated name of the enumerator.
529**************************************************************************/
530#ifndef SPECENUM_NAMEOVERRIDE
531fc__attribute((const))
533static inline const char *
534SPECENUM_FOO(_translated_name)(enum SPECENUM_NAME enumerator)
537 static const char *names[SPECENUM_SIZE + 1];
539 static const char *names[SPECENUM_SIZE];
541 static bool initialized = FALSE;
543#ifdef SPECENUM_NAMEOVERRIDE
545 const char *name = SPECENUM_FOO(_name_cb)(enumerator);
547 if (name != nullptr) {
551#endif /* SPECENUM_NAMEOVERRIDE */
553 if (!initialized) {''')
555 for i
in range(max_enum_values):
557#if %d < SPECENUM_SIZE
558# ifndef SPECENUM_VALUE%d
560# elif defined(SPECENUM_VALUE%dNAME)
561 names[%d] = Q_(SPECENUM_VALUE%dNAME);
563 names[%d] = SPECENUM_STRING(SPECENUM_VALUE%d);
565#endif'''%(i,i,i,i,i,i,i,i))
570# ifdef SPECENUM_COUNTNAME
571 names[SPECENUM_COUNT] = Q_(SPECENUM_COUNTNAME);
573 names[SPECENUM_COUNT] = SPECENUM_STRING(SPECENUM_COUNT);
579#ifdef SPECENUM_BITWISE
581 if (enumerator == SPECENUM_ZERO) {
582# ifdef SPECENUM_ZERONAME
583 return Q_(SPECENUM_ZERONAME);
585 return SPECENUM_STRING(SPECENUM_ZERO);
592 for (i = 0; i < ARRAY_SIZE(names); i++) {
593 if (1 << i == enumerator) {
599 if ((unsigned)enumerator < ARRAY_SIZE(names)) {
600 return names[enumerator];
602#endif /* SPECENUM_BITWISE */
609#ifdef SPECENUM_BITVECTOR
610BV_DEFINE(SPECENUM_BITVECTOR, (SPECENUM_MAX_VALUE + 1));
611#endif /* SPECENUM_BITVECTOR */
626 with open(target_name,
"w")
as output:
649#endif /* __cplusplus */
make_translated_name(file)