123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277 |
- #!@PYTHON@
- # Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
- #
- # Permission to use, copy, modify, and/or distribute this software for any
- # purpose with or without fee is hereby granted, provided that the above
- # copyright notice and this permission notice appear in all copies.
- #
- # THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
- # REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
- # AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
- # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
- # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
- # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- # PERFORMANCE OF THIS SOFTWARE.
- import os
- import re
- import sys
- import json
- from xml.etree import ElementTree
- item_list = []
- localstatedir = '@@LOCALSTATEDIR@@'
- builddir = '@builddir@'
- srcdir = '@srcdir@'
- pre_suffix = '.pre'
- xmldocument_command_name = 'b10-auth'
- def need_generate(filepath, mtime):
- '''Check if we need to generate the specified file.
- To avoid unnecessary compilation, we skip (re)generating the file when
- the file already exists and newer than the base file.
- '''
- if os.path.exists(filepath) and os.path.getmtime(filepath) > mtime:
- return False
- return True
- def import_definitions():
- global item_list
- items_definition_file = srcdir + os.sep + 'statistics_qr_items.def'
- item_definition = open(items_definition_file, 'r')
- re_splitter = re.compile('\t+')
- l = item_list
- lp = None
- for line in item_definition.readlines():
- element = re_splitter.split(line.rstrip())
- if element[0] == '':
- element.pop(0)
- if element[-1] == '=':
- l.append({'name': element[0], 'child': [], 'index': element[1],
- 'description': element[2], 'parent': lp})
- lp = l
- l = l[-1]['child']
- elif element[-1] == ';':
- l = lp
- lp = l[-1]['parent']
- else:
- l.append({'name': element[0], 'child': None, 'index': element[1],
- 'description': element[2], 'parent': lp})
- item_definition.close()
- return os.path.getmtime(items_definition_file)
- def generate_specfile(specfile, def_mtime):
- global item_list
- def convert_list(items, prefix = ''):
- spec_list = []
- default_map = {}
- for item in items:
- full_item_name = prefix + item['name']
- if item['child'] is None:
- default_map[item['name']] = 0
- spec_list.append({
- 'item_name': item['name'],
- 'item_optional': False,
- 'item_type': 'integer',
- 'item_default': 0,
- 'item_title': full_item_name,
- 'item_description': item['description'],
- })
- else:
- child_spec_list, child_default_map = \
- convert_list(item['child'], full_item_name + '.')
- spec_list.append({
- 'item_name': item['name'],
- 'item_type': 'map',
- 'item_optional': False,
- 'item_title': full_item_name,
- 'item_description': item['description'],
- 'item_default': child_default_map,
- 'map_item_spec': child_spec_list,
- })
- default_map[item['name']] = child_default_map
- return spec_list, default_map
- item_spec_list, item_default_map = convert_list(item_list)
- statistics_spec_list = [{
- 'item_name': 'zones',
- 'item_type': 'named_set',
- 'item_optional': False,
- 'item_title': 'Zone statistics',
- 'item_description':
- 'Zone statistics items. ' +
- "Items for all zones are stored in '_SERVER_'.",
- 'item_default': { '_SERVER_': item_default_map },
- 'named_set_item_spec': {
- 'item_name': 'zone',
- 'item_type': 'map',
- 'item_optional': False,
- 'item_default': {},
- 'map_item_spec': item_spec_list,
- },
- }]
- if need_generate(builddir+os.sep+specfile, def_mtime):
- stats_pre = open(builddir+os.sep+specfile+pre_suffix, 'r')
- stats_pre_json = json.loads(stats_pre.read().replace('@@LOCAL'+'STATEDIR@@',
- localstatedir))
- stats_pre.close()
- stats_pre_json['module_spec']['statistics'] = statistics_spec_list
- statistics_spec_json = json.dumps(stats_pre_json, sort_keys = True,
- indent = 2)
- stats_spec = open(builddir+os.sep+specfile, 'w')
- stats_spec.write(statistics_spec_json)
- stats_spec.close()
- else:
- print('skip generating ' + specfile)
- return
- def generate_docfile(docfile, def_mtime):
- global item_list
- def convert_list(items, tree, prefix = ''):
- for item in items:
- full_item_name = prefix + item['name']
- if item['child'] is None:
- child_element = ElementTree.SubElement(tree, 'varlistentry')
- term = ElementTree.SubElement(child_element, 'term')
- term.text = full_item_name
- list_item = ElementTree.SubElement(child_element, 'listitem')
- sim_para = ElementTree.SubElement(list_item, 'simpara')
- sim_para.text = ''
- prev = None
- for word in item['description'].split():
- if word == xmldocument_command_name:
- command = ElementTree.SubElement(sim_para, 'command')
- command.text = word
- para_tail = command
- command.tail = ' '
- prev = command
- else:
- if prev is None:
- sim_para.text += word + ' '
- else:
- prev.tail += word + ' '
- else:
- convert_list(item['child'], tree, full_item_name + '.')
- return
- if need_generate(builddir+os.sep+docfile, def_mtime):
- doc_pre = open(srcdir+os.sep+docfile+pre_suffix, 'r')
- doc_pre_xml = doc_pre.read().replace('@@LOCAL'+'STATEDIR@@',
- localstatedir)
- doc_pre.close
- variable_tree = ElementTree.Element('variablelist')
- convert_list(item_list, variable_tree)
- doc = open(builddir+os.sep+docfile, 'w')
- doc.write(doc_pre_xml.replace(
- '<!-- ### STATISTICS DATA PLACEHOLDER ### -->',
- str(ElementTree.tostring(variable_tree))))
- doc.close()
- else:
- print('skip generating ' + docfile)
- return
- def generate_cxx(itemsfile, ccfile, utfile, def_mtime):
- global item_list
- qr_counter_types = 'enum QRCounterType {\n'
- item_names = []
- def convert_list(items, qr_counter_types, item_names_current, item_names):
- for item in items:
- if item['child'] is None:
- qr_counter_types += ' ' + item['index'] + ', ' +\
- '///< ' + item['description'] + '\n'
- item_names_current.append(' { "' + item['name'] +
- '", NULL, ' + item['index'] + ' },\n'
- )
- else:
- item_names_current_ = ['const struct CounterTypeTree ' +
- item['index'] + '[] = {\n']
- qr_counter_types, item_names_current_, item_names = \
- convert_list(item['child'], qr_counter_types,
- item_names_current_, item_names)
- item_names_current_.append(' { NULL, NULL, -1 }\n' +
- '};\n')
- item_names.extend(item_names_current_)
- item_names_current.append(' { "' + item['name'] + '", ' +
- item['index'] + ', -1 },\n')
- return qr_counter_types, item_names_current, item_names
- qr_counter_types, item_names_current, item_names = \
- convert_list(item_list, qr_counter_types, [], item_names)
- item_names.append('const struct CounterTypeTree QRCounterTree[] = {\n')
- item_names.extend(item_names_current)
- item_names.append(' { NULL, NULL, -1 }\n' +
- '};\n')
- qr_counter_types += \
- ' // End of counter types\n' +\
- ' QR_COUNTER_TYPES ///< The number of defined counters\n' +\
- '};\n'
- item_defs = qr_counter_types
- item_decls = ''.join(item_names)
- if need_generate(builddir+os.sep+itemsfile, def_mtime):
- statistics_items_h_pre = open(srcdir+os.sep+itemsfile+pre_suffix, 'r')
- items_pre = statistics_items_h_pre.read()
- statistics_items_h_pre.close
- statistics_items_h = open(builddir+os.sep+itemsfile, 'w')
- statistics_items_h.write(items_pre.replace(
- '// ### STATISTICS ITEMS DECLARATION ###', item_defs))
- statistics_items_h.close()
- else:
- print('skip generating ' + itemsfile)
- if need_generate(builddir+os.sep+ccfile, def_mtime):
- statistics_cc_pre = open(srcdir+os.sep+ccfile+pre_suffix, 'r')
- items_pre = statistics_cc_pre.read()
- statistics_cc_pre.close
- statistics_cc = open(builddir+os.sep+ccfile, 'w')
- statistics_cc.write(items_pre.replace(
- '// ### STATISTICS ITEMS DEFINITION ###', item_decls))
- statistics_cc.close()
- else:
- print('skip generating ' + ccfile)
- if need_generate(builddir+os.sep+utfile, def_mtime):
- statistics_ut_cc_pre = open(srcdir+os.sep+utfile+pre_suffix, 'r')
- items_pre = statistics_ut_cc_pre.read()
- statistics_ut_cc_pre.close
- statistics_ut_cc = open(builddir+os.sep+utfile, 'w')
- statistics_ut_cc.write(items_pre.replace(
- '// ### STATISTICS ITEMS DEFINITION ###', item_decls))
- statistics_ut_cc.close()
- else:
- print('skip generating ' + utfile)
- return
- if __name__ == "__main__":
- try:
- def_mtime = import_definitions()
- generate_specfile('auth.spec', def_mtime)
- generate_docfile('b10-auth.xml', def_mtime)
- generate_cxx('statistics_items.h',
- 'statistics.cc',
- 'tests'+os.sep+'statistics_unittest.cc',
- def_mtime)
- except:
- sys.stderr.write('Code generation failed due to exception: %s\n' %
- sys.exc_info()[1])
- exit(1)
|