diff options
Diffstat (limited to 'src/util/merge_driinfo.py')
-rw-r--r-- | src/util/merge_driinfo.py | 222 |
1 files changed, 222 insertions, 0 deletions
diff --git a/src/util/merge_driinfo.py b/src/util/merge_driinfo.py new file mode 100644 index 00000000000..e6ccca5e0f3 --- /dev/null +++ b/src/util/merge_driinfo.py @@ -0,0 +1,222 @@ +# +# Copyright 2017 Advanced Micro Devices, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# on the rights to use, copy, modify, merge, publish, distribute, sub +# license, and/or sell copies of the Software, and to permit persons to whom +# the Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice (including the next +# paragraph) shall be included in all copies or substantial portions of the +# Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +# THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +# OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +# USE OR OTHER DEALINGS IN THE SOFTWARE. + +""" +usage: merge_driinfo.py <list of input files> + +Generates a source file which contains the DRI_CONF_xxx macros for generating +the driinfo XML that describes the available DriConf options for a driver and +its supported state trackers, based on the merged information from the input +files. +""" + +from __future__ import print_function + +import mako.template +import re +import sys + + +# Some regexps used during input parsing +RE_section_begin = re.compile(r'DRI_CONF_SECTION_(.*)') +RE_option = re.compile(r'DRI_CONF_(.*)\((.*)\)') + + +class Option(object): + """ + Represent a config option as: + * name: the xxx part of the DRI_CONF_xxx macro + * defaults: the defaults parameters that are passed into the macro + """ + def __init__(self, name, defaults): + self.name = name + self.defaults = defaults + + +class Section(object): + """ + Represent a config section description as: + * name: the xxx part of the DRI_CONF_SECTION_xxx macro + * options: list of options + """ + def __init__(self, name): + self.name = name + self.options = [] + + +def parse_inputs(input_filenames): + success = True + sections_lists = [] + + for input_filename in input_filenames: + with open(input_filename, 'r') as infile: + sections = [] + sections_lists.append(sections) + + section = None + + linenum = 0 + for line in infile: + linenum += 1 + line = line.strip() + if not line: + continue + + if line.startswith('//'): + continue + + if line == 'DRI_CONF_SECTION_END': + if section is None: + print('{}:{}: no open section' + .format(input_filename, linenum)) + success = False + continue + section = None + continue + + m = RE_section_begin.match(line) + if m: + if section is not None: + print('{}:{}: nested sections are not supported' + .format(input_filename, linenum)) + success = False + continue + if sections is None: + print('{}:{}: missing DRIINFO line' + .format(input_filename, linenum)) + success = False + break # parsing the rest really makes no sense + section = Section(m.group(1)) + sections.append(section) + continue + + m = RE_option.match(line) + if m: + if section is None: + print('{}:{}: no open section' + .format(input_filename, linenum)) + success = False + break + section.options.append(Option(m.group(1), m.group(2))) + continue + + print('{}:{}: do not understand this line' + .format(input_filename, linenum)) + success = False + + if section is not None: + print('{}:end-of-file: missing end of section' + .format(input_filename)) + success = False + + if success: + return sections_lists + return None + + +def merge_sections(section_list): + """ + section_list: list of Section objects to be merged, all of the same name + Return a merged Section object (everything is deeply copied) + """ + merged_section = Section(section_list[0].name) + + for section in section_list: + assert section.name == merged_section.name + + for orig_option in section.options: + for merged_option in merged_section.options: + if orig_option.name == merged_option.name: + merged_option.defaults = orig_option.defaults + break + else: + merged_section.options.append(Option(orig_option.name, orig_option.defaults)) + + return merged_section + + +def merge_sections_lists(sections_lists): + """ + sections_lists: list of lists of Section objects to be merged + Return a merged list of merged Section objects; everything is deeply copied. + Default values for options in later lists override earlier default values. + """ + merged_sections = [] + + for idx,sections in enumerate(sections_lists): + for base_section in sections: + original_sections = [base_section] + for next_sections in sections_lists[idx+1:]: + for j,section in enumerate(next_sections): + if section.name == base_section.name: + original_sections.append(section) + del next_sections[j] + break + + merged_section = merge_sections(original_sections) + + merged_sections.append(merged_section) + + return merged_sections + + +def main(input_filenames): + sections_lists = parse_inputs(input_filenames) + if sections_lists is None: + return False + + merged_sections_list = merge_sections_lists(sections_lists) + + driinfo_h_template = mako.template.Template("""\ +// DO NOT EDIT - this file is automatically generated by merge_driinfo.py + +/* +Use as: + +#include "xmlpool.h" + +static const char driinfo_xml[] = +#include "this_file" +; +*/ + +DRI_CONF_BEGIN +% for section in sections: + DRI_CONF_SECTION_${section.name} +% for option in section.options: + DRI_CONF_${option.name}(${option.defaults}) +% endfor + DRI_CONF_SECTION_END +% endfor +DRI_CONF_END""") + + print(driinfo_h_template.render(sections=merged_sections_list)) + return True + + +if __name__ == '__main__': + if len(sys.argv) <= 1: + print('Missing arguments') + sys.exit(1) + + if not main(sys.argv[1:]): + sys.exit(1) |