]>
git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/metaparse/tools/string_headers.py
2676f3f21e92b443edde8bafda3dcc8124cf79c0
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
, name
):
68 self
.name
= name
.upper()
71 """Generate the beginning part"""
72 name
= 'BOOST_METAPARSE_V1_IMPL_{0}_HPP'.format(self
.name
)
73 self
.out_f
.write('#ifndef {0}\n#define {0}\n'.format(name
))
74 write_autogen_info(self
.out_f
)
77 """Generate the closing part"""
78 self
.out_f
.write('\n#endif\n')
84 def __exit__(self
, typ
, value
, traceback
):
89 """Generate the full macro name"""
90 return 'BOOST_METAPARSE_V{0}_{1}'.format(VERSION
, name
)
93 def define_macro(out_f
, (name
, args
, body
), undefine
=False, check
=True):
94 """Generate a macro definition or undefinition"""
98 .format(macro_name(name
))
102 arg_list
= '({0})'.format(', '.join(args
))
109 '# error {0} already defined.\n'
111 .format(macro_name(name
))
115 '#define {0}{1} {2}\n'.format(macro_name(name
), arg_list
, body
)
119 def filename(out_dir
, name
, undefine
=False):
120 """Generate the filename"""
125 return os
.path
.join(out_dir
, '{0}{1}.hpp'.format(prefix
, name
.lower()))
128 def length_limits(max_length_limit
, length_limit_step
):
129 """Generates the length limits"""
130 string_len
= len(str(max_length_limit
))
132 str(i
).zfill(string_len
) for i
in
135 max_length_limit
+ length_limit_step
- 1,
141 def unique_names(count
):
142 """Generate count unique variable name"""
143 return ('C{0}'.format(i
) for i
in xrange(0, count
))
146 def generate_take(out_f
, steps
, line_prefix
):
147 """Generate the take function"""
149 '{0}constexpr inline int take(int n_)\n'
151 '{0} return {1} 0 {2};\n'
155 ''.join('n_ >= {0} ? {0} : ('.format(s
) for s
in steps
),
161 def generate_make_string(out_f
, max_step
):
162 """Generate the make_string template"""
163 steps
= [2 ** n
for n
in xrange(int(math
.log(max_step
, 2)), -1, -1)]
167 ['boost', 'metaparse', 'v{0}'.format(VERSION
), 'impl']
169 generate_take(out_f
, steps
, nsp
.prefix())
172 '{0}template <int LenNow, int LenRemaining, char... Cs>\n'
173 '{0}struct make_string;\n'
175 '{0}template <char... Cs>'
176 ' struct make_string<0, 0, Cs...> : string<> {{}};\n'
177 .format(nsp
.prefix())
181 for i
in reversed(steps
):
182 if i
> 64 and not disable_sun
:
183 out_f
.write('#ifndef __SUNPRO_CC\n')
186 '{0}template <int LenRemaining,{1}char... Cs>'
187 ' struct make_string<{2},LenRemaining,{3}Cs...> :'
188 ' concat<string<{4}>,'
189 ' typename make_string<take(LenRemaining),'
190 'LenRemaining-take(LenRemaining),Cs...>::type> {{}};\n'
193 ''.join('char {0},'.format(n
) for n
in unique_names(i
)),
195 ''.join('{0},'.format(n
) for n
in unique_names(i
)),
196 ','.join(unique_names(i
))
200 out_f
.write('#endif\n')
203 def generate_string(out_dir
, limits
):
204 """Generate string.hpp"""
205 max_limit
= max((int(v
) for v
in limits
))
207 with
open(filename(out_dir
, 'string'), 'wb') as out_f
:
208 with
IncludeGuard(out_f
, ''):
211 '#include <boost/metaparse/v{0}/impl/concat.hpp>\n'
212 '#include <boost/preprocessor/cat.hpp>\n'
216 generate_make_string(out_f
, 512)
220 '#ifndef BOOST_METAPARSE_LIMIT_STRING_SIZE\n'
221 '# error BOOST_METAPARSE_LIMIT_STRING_SIZE not defined\n'
224 '#if BOOST_METAPARSE_LIMIT_STRING_SIZE > {0}\n'
225 '# error BOOST_METAPARSE_LIMIT_STRING_SIZE is greater than'
226 ' {0}. To increase the limit run tools/string_headers.py of'
227 ' Boost.Metaparse against your Boost headers.\n'
233 define_macro(out_f
, (
237 '{0}::take(sizeof(s)-1), sizeof(s)-1-{0}::take(sizeof(s)-1),'
238 'BOOST_PP_CAT({1}, BOOST_METAPARSE_LIMIT_STRING_SIZE)(s)'
241 '::boost::metaparse::v{0}::impl'.format(VERSION
),
247 for limit
in xrange(0, max_limit
+ 1):
251 macro_name('I{0}'.format(limit
)),
252 macro_name('INDEX_STR{0}'.format(
253 min(int(l
) for l
in limits
if int(l
) >= limit
)
261 for length_limit
in (int(l
) for l
in limits
):
262 this_macro
= macro_name('INDEX_STR{0}'.format(length_limit
))
264 '#define {0}(s) {1}{2}\n'
267 '{0}(s),'.format(prev_macro
) if prev_macro
else '',
270 .format(macro_name('STRING_AT'), i
)
271 for i
in xrange(prev_limit
, length_limit
)
275 prev_macro
= this_macro
276 prev_limit
= length_limit
279 def positive_integer(value
):
280 """Throws when the argument is not a positive integer"""
285 raise argparse
.ArgumentTypeError("A positive number is expected")
288 def existing_path(value
):
289 """Throws when the path does not exist"""
290 if os
.path
.exists(value
):
293 raise argparse
.ArgumentTypeError("Path {0} not found".format(value
))
297 """The main function of the script"""
298 parser
= argparse
.ArgumentParser(description
=__doc__
)
303 help='The path to the include/boost directory of Metaparse'
306 '--max_length_limit',
309 type=positive_integer
,
310 help='The maximum supported length limit'
313 '--length_limit_step',
316 type=positive_integer
,
317 help='The longest step at which headers are generated'
319 args
= parser
.parse_args()
321 if args
.boost_dir
is None:
322 tools_path
= os
.path
.dirname(os
.path
.abspath(__file__
))
323 boost_dir
= os
.path
.join(
324 os
.path
.dirname(tools_path
),
329 boost_dir
= args
.boost_dir
331 if args
.max_length_limit
< 1:
332 sys
.stderr
.write('Invalid maximum length limit')
336 os
.path
.join(boost_dir
, 'metaparse', 'v{0}'.format(VERSION
), 'impl'),
337 length_limits(args
.max_length_limit
, args
.length_limit_step
)
341 if __name__
== '__main__':