va_args_gen.py 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. #!/usr/bin/env python
  2. """
  3. Generates some handy macros for preprocessor metaprogramming.
  4. """
  5. from __future__ import print_function
  6. import sys
  7. import textwrap
  8. if sys.version_info >= (3, 0, 0):
  9. xrange = range
  10. def generate(limit):
  11. print('#pragma once')
  12. print(textwrap.dedent('''
  13. /// @file va_args.h
  14. ///
  15. /// Some handy macros for preprocessor metaprogramming.
  16. '''.rstrip()))
  17. print('')
  18. command = ' '.join(sys.argv)
  19. print('// NOTE: this file has been generated with "{}", do not edit -- use the generator instead'.format(command))
  20. print('')
  21. print('// DO_NOT_STYLE')
  22. print('')
  23. print('#include <util/system/defaults.h>')
  24. print('')
  25. pass_va_args()
  26. count(limit)
  27. get_elem(limit)
  28. map_args(limit)
  29. map_args_n(limit)
  30. map_args_with_last(limit)
  31. map_args_with_last_n(limit)
  32. all_but_last(limit)
  33. last(limit)
  34. impl_dispatcher()
  35. def pass_va_args():
  36. print(textwrap.dedent('''
  37. /**
  38. * Triggers another level of macro expansion, use whenever passing __VA_ARGS__ to another macro.
  39. *
  40. * Used merely for working around an MSVC++ bug.
  41. * See http://stackoverflow.com/questions/5134523/msvc-doesnt-expand-va-args-correctly
  42. */
  43. '''.rstrip()))
  44. print('#define Y_PASS_VA_ARGS(x) x')
  45. def count(limit):
  46. print(textwrap.dedent('''
  47. /**
  48. * Count number of arguments in `__VA_ARGS__`.
  49. * Doesn't work with empty arguments list.
  50. */
  51. '''.rstrip()))
  52. numbers = ', '.join(map(str, xrange(limit, -1, -1)))
  53. u_numbers = ', '.join(map('_{}'.format, xrange(limit, 0, -1)))
  54. print('#define Y_COUNT_ARGS(...) Y_PASS_VA_ARGS('
  55. '__Y_COUNT_ARGS(__VA_ARGS__, {}))'.format(numbers))
  56. print('#define __Y_COUNT_ARGS({}, N, ...) N'.format(u_numbers))
  57. def get_elem(limit):
  58. print(textwrap.dedent('''
  59. /**
  60. * Get the i-th element from `__VA_ARGS__`.
  61. */
  62. '''.rstrip()))
  63. print('#define Y_GET_ARG(N, ...) Y_PASS_VA_ARGS(Y_PASS_VA_ARGS(Y_CAT(__Y_GET_ARG_, '
  64. 'N))(__VA_ARGS__))')
  65. for i in xrange(0, limit + 1):
  66. args = ', '.join(map('_{}'.format, xrange(i + 1)))
  67. print('#define __Y_GET_ARG_{}({}, ...) _{}'.format(i, args, i))
  68. def map_args(limit):
  69. print(textwrap.dedent('''
  70. /**
  71. * Expands a macro for each of the variable arguments.
  72. * Doesn't work with empty arguments list.
  73. */
  74. '''.rstrip()))
  75. print('#define Y_MAP_ARGS(ACTION, ...) Y_PASS_VA_ARGS(Y_PASS_VA_ARGS(Y_CAT('
  76. '__Y_MAP_ARGS_, Y_COUNT_ARGS(__VA_ARGS__)))(ACTION, __VA_ARGS__))')
  77. print('#define __Y_MAP_ARGS_0(...)')
  78. print('#define __Y_MAP_ARGS_1(ACTION, x, ...) ACTION(x)')
  79. for i in xrange(2, limit + 1):
  80. print('#define __Y_MAP_ARGS_{}(ACTION, x, ...) ACTION(x) Y_PASS_VA_ARGS(__Y_MAP_ARGS_{}('
  81. 'ACTION, __VA_ARGS__))'.format(i, i - 1))
  82. def map_args_n(limit):
  83. print(textwrap.dedent('''
  84. /**
  85. * Expands a macro for each of the variable arguments with it's sequence number and value.
  86. * Corresponding sequence numbers will expand in descending order.
  87. * Doesn't work with empty arguments list.
  88. */
  89. '''.rstrip()))
  90. print('#define Y_MAP_ARGS_N(ACTION, ...) Y_PASS_VA_ARGS(Y_PASS_VA_ARGS(Y_CAT('
  91. '__Y_MAP_ARGS_N_, Y_COUNT_ARGS(__VA_ARGS__)))(ACTION, __VA_ARGS__))')
  92. print('#define __Y_MAP_ARGS_N_0(...)')
  93. print('#define __Y_MAP_ARGS_N_1(ACTION, x, ...) ACTION(1, x)')
  94. for i in xrange(2, limit + 1):
  95. print('#define __Y_MAP_ARGS_N_{}(ACTION, x, ...) ACTION({}, x) Y_PASS_VA_ARGS(__Y_MAP_ARGS_N_{}('
  96. 'ACTION, __VA_ARGS__))'.format(i, i, i - 1))
  97. def map_args_with_last(limit):
  98. print(textwrap.dedent('''
  99. /**
  100. * Expands a macro for each of the variable arguments.
  101. * Doesn't work with empty arguments list.
  102. */
  103. '''.rstrip()))
  104. print('#define Y_MAP_ARGS_WITH_LAST(ACTION, LAST_ACTION, ...) Y_PASS_VA_ARGS(Y_PASS_VA_ARGS('
  105. 'Y_CAT(__Y_MAP_ARGS_WITH_LAST_, Y_COUNT_ARGS(__VA_ARGS__)))(ACTION, LAST_ACTION, '
  106. '__VA_ARGS__))')
  107. print('#define __Y_MAP_ARGS_WITH_LAST_0(...)')
  108. print('#define __Y_MAP_ARGS_WITH_LAST_1(ACTION, LAST_ACTION, x, ...) LAST_ACTION(x)')
  109. for i in xrange(2, limit + 1):
  110. print('#define __Y_MAP_ARGS_WITH_LAST_{}(ACTION, LAST_ACTION, x, ...) ACTION(x) Y_PASS_VA_ARGS('
  111. '__Y_MAP_ARGS_WITH_LAST_{}(ACTION, LAST_ACTION, __VA_ARGS__))'.format(i, i - 1))
  112. def map_args_with_last_n(limit):
  113. print(textwrap.dedent('''
  114. /**
  115. * Expands a macro for each of the variable arguments with it's sequence number and value.
  116. * Corresponding sequence numbers will expand in descending order.
  117. * Doesn't work with empty arguments list.
  118. */
  119. '''.rstrip()))
  120. print('#define Y_MAP_ARGS_WITH_LAST_N(ACTION, LAST_ACTION, ...) Y_PASS_VA_ARGS(Y_PASS_VA_ARGS('
  121. 'Y_CAT(__Y_MAP_ARGS_WITH_LAST_N_, Y_COUNT_ARGS(__VA_ARGS__)))(ACTION, LAST_ACTION, '
  122. '__VA_ARGS__))')
  123. print('#define __Y_MAP_ARGS_WITH_LAST_N_0(...)')
  124. print('#define __Y_MAP_ARGS_WITH_LAST_N_1(ACTION, LAST_ACTION, x, ...) LAST_ACTION(1, x)')
  125. for i in xrange(2, limit + 1):
  126. print('#define __Y_MAP_ARGS_WITH_LAST_N_{}(ACTION, LAST_ACTION, x, ...) ACTION({}, x) Y_PASS_VA_ARGS('
  127. '__Y_MAP_ARGS_WITH_LAST_N_{}(ACTION, LAST_ACTION, __VA_ARGS__))'.format(i, i, i - 1))
  128. def all_but_last(limit):
  129. print(textwrap.dedent('''
  130. /**
  131. * Get all elements but the last one from `__VA_ARGS__`.
  132. * Doesn't work with empty arguments list.
  133. */
  134. '''.rstrip()))
  135. print('#define Y_ALL_BUT_LAST(...) Y_PASS_VA_ARGS(Y_PASS_VA_ARGS(Y_CAT(__Y_ALL_BUT_LAST_, '
  136. 'Y_COUNT_ARGS(__VA_ARGS__)))(__VA_ARGS__))')
  137. print('#define __Y_ALL_BUT_LAST_0(...)')
  138. print('#define __Y_ALL_BUT_LAST_1(...)')
  139. for i in xrange(2, limit + 1):
  140. args = ', '.join(map('_{}'.format, xrange(i - 1)))
  141. print('#define __Y_ALL_BUT_LAST_{}({}, ...) {}'.format(i, args, args))
  142. def last(limit):
  143. print(textwrap.dedent('''
  144. /**
  145. * Get the last element from `__VA_ARGS__`.
  146. * Doesn't work with empty arguments list.
  147. */
  148. '''.rstrip()))
  149. print('#define Y_LAST(...) Y_PASS_VA_ARGS('
  150. 'Y_GET_ARG(Y_COUNT_ARGS(__VA_ARGS__), , __VA_ARGS__, {}))'.format(',' * limit))
  151. def impl_dispatcher():
  152. print(textwrap.dedent('''
  153. /**
  154. * Macros for implementing overload by number of arguments.
  155. *
  156. * Example usage:
  157. *
  158. * @code{cpp}
  159. * #define I1(arg1) Cout << Y_STRINGIZE(arg1) << Endl;
  160. * #define I2(arg1, arg2) Cout << Y_STRINGIZE(arg1) << ';' << Y_STRINGIZE(arg2) << Endl;
  161. *
  162. * #define Y_PRINT(...) Y_PASS_VA_ARGS(Y_MACRO_IMPL_DISPATCHER_2(__VA_ARGS__, I2, I1)(__VA_ARGS__))
  163. * @endcode
  164. */
  165. '''.rstrip()))
  166. print('/// @{')
  167. for i in xrange(2, 11):
  168. args = ', '.join(map('_{}'.format, xrange(i)))
  169. print('#define Y_MACRO_IMPL_DISPATCHER_{}({}, IMPL, ...) IMPL'.format(i, args))
  170. print('/// }@')
  171. def main():
  172. if len(sys.argv) > 2:
  173. sys.stderr.write('Usage: {} [limit=50]\n'.format(sys.argv[0]))
  174. sys.exit(1)
  175. limit = 50
  176. if len(sys.argv) == 2:
  177. limit = int(sys.argv[1])
  178. generate(limit)
  179. if __name__ == '__main__':
  180. main()