]>
git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/metaparse/tools/string_headers.py
43ef052f1a803b8f799ee08e1538306a6b127e8a
2 """Utility to generate the header files for BOOST_METAPARSE_STRING"""
4 # Copyright Abel Sinkovics (abel@sinkovics.hu) 2016.
5 # Distributed under the Boost Software License, Version 1.0.
6 # (See accompanying file LICENSE_1_0.txt or copy at
7 # http://www.boost.org/LICENSE_1_0.txt)
18 class Namespace(object):
19 """Generate namespace definition"""
21 def __init__(self
, out_f
, names
):
26 """Generate the beginning part"""
27 self
.out_f
.write('\n')
28 for depth
, name
in enumerate(self
.names
):
30 '{0}namespace {1}\n{0}{{\n'.format(self
.prefix(depth
), name
)
34 """Generate the closing part"""
35 for depth
in xrange(len(self
.names
) - 1, -1, -1):
36 self
.out_f
.write('{0}}}\n'.format(self
.prefix(depth
)))
38 def prefix(self
, depth
=None):
39 """Returns the prefix of a given depth. Returns the prefix code inside
40 the namespace should use when depth is None."""
42 depth
= len(self
.names
)
49 def __exit__(self
, typ
, value
, traceback
):
53 def write_autogen_info(out_f
):
54 """Write the comment about the file being autogenerated"""
57 '// This is an automatically generated header file.\n'
58 '// Generated with the tools/string_headers.py utility of\n'
59 '// Boost.Metaparse\n'
63 class IncludeGuard(object):
64 """Generate include guards"""
66 def __init__(self
, out_f
):
70 """Generate the beginning part"""
71 name
= 'BOOST_METAPARSE_V1_CPP11_IMPL_STRING_HPP'
72 self
.out_f
.write('#ifndef {0}\n#define {0}\n'.format(name
))
73 write_autogen_info(self
.out_f
)
76 """Generate the closing part"""
77 self
.out_f
.write('\n#endif\n')
83 def __exit__(self
, typ
, value
, traceback
):
88 """Generate the full macro name"""
89 return 'BOOST_METAPARSE_V{0}_{1}'.format(VERSION
, name
)
92 def define_macro(out_f
, (name
, args
, body
), undefine
=False, check
=True):
93 """Generate a macro definition or undefinition"""
97 .format(macro_name(name
))
101 arg_list
= '({0})'.format(', '.join(args
))
108 '# error {0} already defined.\n'
110 .format(macro_name(name
))
114 '#define {0}{1} {2}\n'.format(macro_name(name
), arg_list
, body
)
118 def filename(out_dir
, name
, undefine
=False):
119 """Generate the filename"""
124 return os
.path
.join(out_dir
, '{0}{1}.hpp'.format(prefix
, name
.lower()))
127 def length_limits(max_length_limit
, length_limit_step
):
128 """Generates the length limits"""
129 string_len
= len(str(max_length_limit
))
131 str(i
).zfill(string_len
) for i
in
134 max_length_limit
+ length_limit_step
- 1,
140 def unique_names(count
):
141 """Generate count unique variable name"""
142 return ('C{0}'.format(i
) for i
in xrange(0, count
))
145 def generate_take(out_f
, steps
, line_prefix
):
146 """Generate the take function"""
148 '{0}constexpr inline int take(int n_)\n'
150 '{0} return {1} 0 {2};\n'
154 ''.join('n_ >= {0} ? {0} : ('.format(s
) for s
in steps
),
160 def generate_make_string(out_f
, max_step
):
161 """Generate the make_string template"""
162 steps
= [2 ** n
for n
in xrange(int(math
.log(max_step
, 2)), -1, -1)]
166 ['boost', 'metaparse', 'v{0}'.format(VERSION
), 'impl']
168 generate_take(out_f
, steps
, nsp
.prefix())
171 '{0}template <int LenNow, int LenRemaining, char... Cs>\n'
172 '{0}struct make_string;\n'
174 '{0}template <char... Cs>'
175 ' struct make_string<0, 0, Cs...> : string<> {{}};\n'
176 .format(nsp
.prefix())
180 for i
in reversed(steps
):
181 if i
> 64 and not disable_sun
:
182 out_f
.write('#ifndef __SUNPRO_CC\n')
185 '{0}template <int LenRemaining,{1}char... Cs>'
186 ' struct make_string<{2},LenRemaining,{3}Cs...> :'
187 ' concat<string<{4}>,'
188 ' typename make_string<take(LenRemaining),'
189 'LenRemaining-take(LenRemaining),Cs...>::type> {{}};\n'
192 ''.join('char {0},'.format(n
) for n
in unique_names(i
)),
194 ''.join('{0},'.format(n
) for n
in unique_names(i
)),
195 ','.join(unique_names(i
))
199 out_f
.write('#endif\n')
202 def generate_string(out_dir
, limits
):
203 """Generate string.hpp"""
204 max_limit
= max((int(v
) for v
in limits
))
206 with
open(filename(out_dir
, 'string'), 'wb') as out_f
:
207 with
IncludeGuard(out_f
):
210 '#include <boost/metaparse/v{0}/cpp11/impl/concat.hpp>\n'
211 '#include <boost/preprocessor/cat.hpp>\n'
215 generate_make_string(out_f
, 512)
219 '#ifndef BOOST_METAPARSE_LIMIT_STRING_SIZE\n'
220 '# error BOOST_METAPARSE_LIMIT_STRING_SIZE not defined\n'
223 '#if BOOST_METAPARSE_LIMIT_STRING_SIZE > {0}\n'
224 '# error BOOST_METAPARSE_LIMIT_STRING_SIZE is greater than'
225 ' {0}. To increase the limit run tools/string_headers.py of'
226 ' Boost.Metaparse against your Boost headers.\n'
232 define_macro(out_f
, (
236 '{0}::take(sizeof(s)-1), sizeof(s)-1-{0}::take(sizeof(s)-1),'
237 'BOOST_PP_CAT({1}, BOOST_METAPARSE_LIMIT_STRING_SIZE)(s)'
240 '::boost::metaparse::v{0}::impl'.format(VERSION
),
246 for limit
in xrange(0, max_limit
+ 1):
250 macro_name('I{0}'.format(limit
)),
251 macro_name('INDEX_STR{0}'.format(
252 min(int(l
) for l
in limits
if int(l
) >= limit
)
260 for length_limit
in (int(l
) for l
in limits
):
261 this_macro
= macro_name('INDEX_STR{0}'.format(length_limit
))
263 '#define {0}(s) {1}{2}\n'
266 '{0}(s),'.format(prev_macro
) if prev_macro
else '',
269 .format(macro_name('STRING_AT'), i
)
270 for i
in xrange(prev_limit
, length_limit
)
274 prev_macro
= this_macro
275 prev_limit
= length_limit
278 def positive_integer(value
):
279 """Throws when the argument is not a positive integer"""
284 raise argparse
.ArgumentTypeError("A positive number is expected")
287 def existing_path(value
):
288 """Throws when the path does not exist"""
289 if os
.path
.exists(value
):
292 raise argparse
.ArgumentTypeError("Path {0} not found".format(value
))
296 """The main function of the script"""
297 parser
= argparse
.ArgumentParser(description
=__doc__
)
302 help='The path to the include/boost directory of Metaparse'
305 '--max_length_limit',
308 type=positive_integer
,
309 help='The maximum supported length limit'
312 '--length_limit_step',
315 type=positive_integer
,
316 help='The longest step at which headers are generated'
318 args
= parser
.parse_args()
320 if args
.boost_dir
is None:
321 tools_path
= os
.path
.dirname(os
.path
.abspath(__file__
))
322 boost_dir
= os
.path
.join(
323 os
.path
.dirname(tools_path
),
328 boost_dir
= args
.boost_dir
330 if args
.max_length_limit
< 1:
331 sys
.stderr
.write('Invalid maximum length limit')
338 'v{0}'.format(VERSION
),
342 length_limits(args
.max_length_limit
, args
.length_limit_step
)
346 if __name__
== '__main__':