mirror of
https://github.com/aantron/better-enums.git
synced 2025-12-06 16:56:42 +08:00
The documentation is now generated from markdown. Samples are generated from the tutorial pages. Testing is done by a Python script which runs the tests for a large number of compilers. This version is not very developer-friendly - the Python scripts need ways of limiting what compilers they try to run. If you don't have 15 compilers installed, you won't be able to run the tests in this commit. Fix coming soon.
142 lines
5.6 KiB
Python
Executable File
142 lines
5.6 KiB
Python
Executable File
#! /usr/bin/env python
|
|
|
|
# This file is part of Better Enums, released under the BSD 2-clause license.
|
|
# See LICENSE for details, or visit http://github.com/aantron/better-enums.
|
|
|
|
# This script generates the macros _ENUM_PP_MAP and _ENUM_ITERATE, used
|
|
# internally by enum.h. These are already inlined into enum.h. You only need
|
|
# this script if you are developing enum.h, or run into a limit.
|
|
#
|
|
# _ENUM_PP_MAP has a limit, which determines the maximum number of constants an
|
|
# enum can have. By default, this limit is 64 constants.
|
|
#
|
|
# _ENUM_ITERATE also has a limit. This one determines the maximum length of the
|
|
# name of a constant that is followed by an initializer (" = 2") when compiling
|
|
# an enum with constexpr to_string function (i.e. usually, this limit does not
|
|
# apply). By default, the limit is 23 characters (24 with the obligatory null
|
|
# terminator).
|
|
#
|
|
# If either of these limits is inadequate, you can still compile your code
|
|
# without changing enum.h. You need to generate an external macro file with
|
|
# definitions of these macros with relaxed limits, and tell enum.h to use the
|
|
# external macro file. Here is how this is done, supposing you want support for
|
|
# 512 constants of length up to 127 (128 with null terminator):
|
|
#
|
|
# 0. MACRO_FILE is the name of the external macro file. Make sure you put it
|
|
# somewhere in your include path.
|
|
# 1. Run python make_macros.py 512 128 > MACRO_FILE
|
|
# 2. Build your code with an additional compiler flag:
|
|
# - for gcc and clang, -DBETTER_ENUMS_MACRO_FILE='<MACRO_FILE>'
|
|
# - for VC++, /DBETTER_ENUMS_MACRO_FILE='<MACRO_FILE>'
|
|
# or use any other method of getting these macros declared.
|
|
# 3. Compile your code. Your macro file should be included, and enum.h should
|
|
# happily work with whatever limits you chose.
|
|
|
|
import os
|
|
import sys
|
|
|
|
class MultiLine(object):
|
|
def __init__(self, stream, indent = 4, columns = 80, initial_column = 0):
|
|
self._columns_left = columns - initial_column
|
|
self._indent = indent
|
|
self._columns = columns
|
|
self._stream = stream
|
|
|
|
def write(self, token, last = False):
|
|
break_line = False
|
|
if last:
|
|
if len(token) > self._columns_left:
|
|
break_line = True
|
|
else:
|
|
if len(token) > self._columns_left - 1:
|
|
break_line = True
|
|
|
|
if break_line:
|
|
print >> self._stream, ' ' * (self._columns_left - 1) + '\\'
|
|
self._stream.write(' ' * self._indent)
|
|
self._columns_left = self._columns - self._indent
|
|
token = token.lstrip()
|
|
|
|
self._stream.write(token)
|
|
self._columns_left -= len(token)
|
|
|
|
def generate(stream, constants, length, script):
|
|
print >> stream, '// This file was automatically generated by ' + script
|
|
|
|
print >> stream, ''
|
|
print >> stream, '#pragma once'
|
|
print >> stream, ''
|
|
print >> stream, '#ifndef _BETTER_ENUM_MACRO_FILE_H_'
|
|
print >> stream, '#define _BETTER_ENUM_MACRO_FILE_H_'
|
|
|
|
print >> stream, ''
|
|
print >> stream, '#define _ENUM_PP_MAP(macro, data, ...) \\'
|
|
print >> stream, ' _ENUM_A(_ENUM_PP_MAP_VAR_COUNT, ' + \
|
|
'_ENUM_PP_COUNT(__VA_ARGS__)) \\'
|
|
print >> stream, ' (macro, data, __VA_ARGS__)'
|
|
|
|
print >> stream, ''
|
|
print >> stream, '#define _ENUM_PP_MAP_VAR_COUNT(count) ' + \
|
|
'_ENUM_M ## count'
|
|
|
|
print >> stream, ''
|
|
print >> stream, '#define _ENUM_A(macro, ...) macro(__VA_ARGS__)'
|
|
|
|
print >> stream, ''
|
|
print >> stream, '#define _ENUM_M1(m, d, x) _ENUM_A(m, d, 0, x)'
|
|
for index in range(2, constants + 1):
|
|
print >> stream, '#define _ENUM_M' + str(index) + \
|
|
'(m,d,x,...) _ENUM_A(m,d,' + str(index - 1) + \
|
|
',x) _ENUM_M' + str(index - 1) + \
|
|
'(m,d,__VA_ARGS__)'
|
|
|
|
print >> stream, ''
|
|
pp_count_impl_prefix = '#define _ENUM_PP_COUNT_IMPL(_1,'
|
|
stream.write(pp_count_impl_prefix)
|
|
pp_count_impl = MultiLine(stream = stream, indent = 4,
|
|
initial_column = len(pp_count_impl_prefix))
|
|
for index in range(2, constants + 1):
|
|
pp_count_impl.write(' _' + str(index) + ',')
|
|
pp_count_impl.write(' count,')
|
|
pp_count_impl.write(' ...)')
|
|
pp_count_impl.write(' count', last = True)
|
|
print >> stream, ''
|
|
|
|
print >> stream, ''
|
|
pp_count_prefix = \
|
|
'#define _ENUM_PP_COUNT(...) _ENUM_PP_COUNT_IMPL(__VA_ARGS__,'
|
|
stream.write(pp_count_prefix)
|
|
pp_count = MultiLine(stream = stream, indent = 4,
|
|
initial_column = len(pp_count_prefix))
|
|
for index in range(0, constants - 1):
|
|
pp_count.write(' ' + str(constants - index) + ',')
|
|
pp_count.write(' 1)', last = True)
|
|
print >> stream, ''
|
|
|
|
print >> stream, ''
|
|
iterate_prefix = '#define _ENUM_ITERATE(X, f, l)'
|
|
stream.write(iterate_prefix)
|
|
iterate = MultiLine(stream = stream, indent = 4,
|
|
initial_column = len(iterate_prefix))
|
|
for index in range(0, length):
|
|
iterate.write(' X(f, l, %i)' % index)
|
|
print >> stream, ''
|
|
|
|
print >> stream, ''
|
|
print >> stream, '#endif // #ifndef _BETTER_ENUM_MACRO_FILE_H_'
|
|
|
|
if __name__ == '__main__':
|
|
if len(sys.argv) != 3:
|
|
print >> sys.stderr, \
|
|
'Usage: ' + sys.argv[0] + ' CONSTANTS LENGTH > FILE'
|
|
print >> sys.stderr, ''
|
|
print >> sys.stderr, 'Prints map macro definition to FILE.'
|
|
print >> sys.stderr, 'CONSTANTS is the number of constants to support.'
|
|
print >> sys.stderr, 'LENGTH is the maximum length of a constant name.'
|
|
sys.exit(1)
|
|
|
|
generate(sys.stdout, int(sys.argv[1]), int(sys.argv[2]),
|
|
os.path.basename(sys.argv[0]))
|
|
|
|
sys.exit(0)
|