1b8e80941Smrg# 2b8e80941Smrg# Copyright 2017 Advanced Micro Devices, Inc. 3b8e80941Smrg# 4b8e80941Smrg# Permission is hereby granted, free of charge, to any person obtaining a 5b8e80941Smrg# copy of this software and associated documentation files (the "Software"), 6b8e80941Smrg# to deal in the Software without restriction, including without limitation 7b8e80941Smrg# on the rights to use, copy, modify, merge, publish, distribute, sub 8b8e80941Smrg# license, and/or sell copies of the Software, and to permit persons to whom 9b8e80941Smrg# the Software is furnished to do so, subject to the following conditions: 10b8e80941Smrg# 11b8e80941Smrg# The above copyright notice and this permission notice (including the next 12b8e80941Smrg# paragraph) shall be included in all copies or substantial portions of the 13b8e80941Smrg# Software. 14b8e80941Smrg# 15b8e80941Smrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16b8e80941Smrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17b8e80941Smrg# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 18b8e80941Smrg# THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, 19b8e80941Smrg# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 20b8e80941Smrg# OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 21b8e80941Smrg# USE OR OTHER DEALINGS IN THE SOFTWARE. 22b8e80941Smrg 23b8e80941Smrg""" 24b8e80941Smrgusage: merge_driinfo.py <list of input files> 25b8e80941Smrg 26b8e80941SmrgGenerates a source file which contains the DRI_CONF_xxx macros for generating 27b8e80941Smrgthe driinfo XML that describes the available DriConf options for a driver and 28b8e80941Smrgits supported state trackers, based on the merged information from the input 29b8e80941Smrgfiles. 30b8e80941Smrg""" 31b8e80941Smrg 32b8e80941Smrgfrom __future__ import print_function 33b8e80941Smrg 34b8e80941Smrgimport mako.template 35b8e80941Smrgimport re 36b8e80941Smrgimport sys 37b8e80941Smrg 38b8e80941Smrg 39b8e80941Smrg# Some regexps used during input parsing 40b8e80941SmrgRE_section_begin = re.compile(r'DRI_CONF_SECTION_(.*)') 41b8e80941SmrgRE_option = re.compile(r'DRI_CONF_(.*)\((.*)\)') 42b8e80941Smrg 43b8e80941Smrg 44b8e80941Smrgclass Option(object): 45b8e80941Smrg """ 46b8e80941Smrg Represent a config option as: 47b8e80941Smrg * name: the xxx part of the DRI_CONF_xxx macro 48b8e80941Smrg * defaults: the defaults parameters that are passed into the macro 49b8e80941Smrg """ 50b8e80941Smrg def __init__(self, name, defaults): 51b8e80941Smrg self.name = name 52b8e80941Smrg self.defaults = defaults 53b8e80941Smrg 54b8e80941Smrg 55b8e80941Smrgclass Verbatim(object): 56b8e80941Smrg """ 57b8e80941Smrg Represent a chunk of code that is copied into the result file verbatim. 58b8e80941Smrg """ 59b8e80941Smrg def __init__(self): 60b8e80941Smrg self.string = '' 61b8e80941Smrg 62b8e80941Smrg 63b8e80941Smrgclass Section(object): 64b8e80941Smrg """ 65b8e80941Smrg Represent a config section description as: 66b8e80941Smrg * name: the xxx part of the DRI_CONF_SECTION_xxx macro 67b8e80941Smrg * options: list of options 68b8e80941Smrg """ 69b8e80941Smrg def __init__(self, name): 70b8e80941Smrg self.name = name 71b8e80941Smrg self.options = [] 72b8e80941Smrg 73b8e80941Smrg 74b8e80941Smrgdef parse_inputs(input_filenames): 75b8e80941Smrg success = True 76b8e80941Smrg sections_lists = [] 77b8e80941Smrg 78b8e80941Smrg for input_filename in input_filenames: 79b8e80941Smrg with open(input_filename, 'r') as infile: 80b8e80941Smrg sections = [] 81b8e80941Smrg sections_lists.append(sections) 82b8e80941Smrg 83b8e80941Smrg section = None 84b8e80941Smrg 85b8e80941Smrg linenum = 0 86b8e80941Smrg verbatim = None 87b8e80941Smrg for line in infile: 88b8e80941Smrg linenum += 1 89b8e80941Smrg 90b8e80941Smrg if line.startswith('//= BEGIN VERBATIM'): 91b8e80941Smrg if verbatim is not None: 92b8e80941Smrg print('{}:{}: nested verbatim' 93b8e80941Smrg .format(input_filename, linenum)) 94b8e80941Smrg success = False 95b8e80941Smrg continue 96b8e80941Smrg verbatim = Verbatim() 97b8e80941Smrg 98b8e80941Smrg if verbatim is not None: 99b8e80941Smrg verbatim.string += line 100b8e80941Smrg 101b8e80941Smrg if line.startswith('//= END VERBATIM'): 102b8e80941Smrg if section is None: 103b8e80941Smrg sections.append(verbatim) 104b8e80941Smrg else: 105b8e80941Smrg section.options.append(verbatim) 106b8e80941Smrg verbatim = None 107b8e80941Smrg continue 108b8e80941Smrg 109b8e80941Smrg line = line.strip() 110b8e80941Smrg if not line: 111b8e80941Smrg continue 112b8e80941Smrg 113b8e80941Smrg if line.startswith('//'): 114b8e80941Smrg continue 115b8e80941Smrg 116b8e80941Smrg if line == 'DRI_CONF_SECTION_END': 117b8e80941Smrg if section is None: 118b8e80941Smrg print('{}:{}: no open section' 119b8e80941Smrg .format(input_filename, linenum)) 120b8e80941Smrg success = False 121b8e80941Smrg continue 122b8e80941Smrg section = None 123b8e80941Smrg continue 124b8e80941Smrg 125b8e80941Smrg m = RE_section_begin.match(line) 126b8e80941Smrg if m: 127b8e80941Smrg if section is not None: 128b8e80941Smrg print('{}:{}: nested sections are not supported' 129b8e80941Smrg .format(input_filename, linenum)) 130b8e80941Smrg success = False 131b8e80941Smrg continue 132b8e80941Smrg if sections is None: 133b8e80941Smrg print('{}:{}: missing DRIINFO line' 134b8e80941Smrg .format(input_filename, linenum)) 135b8e80941Smrg success = False 136b8e80941Smrg break # parsing the rest really makes no sense 137b8e80941Smrg section = Section(m.group(1)) 138b8e80941Smrg sections.append(section) 139b8e80941Smrg continue 140b8e80941Smrg 141b8e80941Smrg m = RE_option.match(line) 142b8e80941Smrg if m: 143b8e80941Smrg if section is None: 144b8e80941Smrg print('{}:{}: no open section' 145b8e80941Smrg .format(input_filename, linenum)) 146b8e80941Smrg success = False 147b8e80941Smrg break 148b8e80941Smrg section.options.append(Option(m.group(1), m.group(2))) 149b8e80941Smrg continue 150b8e80941Smrg 151b8e80941Smrg print('{}:{}: do not understand this line' 152b8e80941Smrg .format(input_filename, linenum)) 153b8e80941Smrg success = False 154b8e80941Smrg 155b8e80941Smrg if section is not None: 156b8e80941Smrg print('{}:end-of-file: missing end of section' 157b8e80941Smrg .format(input_filename)) 158b8e80941Smrg success = False 159b8e80941Smrg 160b8e80941Smrg if success: 161b8e80941Smrg return sections_lists 162b8e80941Smrg return None 163b8e80941Smrg 164b8e80941Smrg 165b8e80941Smrgdef merge_sections(section_list): 166b8e80941Smrg """ 167b8e80941Smrg section_list: list of Section objects to be merged, all of the same name 168b8e80941Smrg Return a merged Section object (everything is deeply copied) 169b8e80941Smrg """ 170b8e80941Smrg merged_section = Section(section_list[0].name) 171b8e80941Smrg 172b8e80941Smrg for section in section_list: 173b8e80941Smrg assert section.name == merged_section.name 174b8e80941Smrg 175b8e80941Smrg for orig_option in section.options: 176b8e80941Smrg if isinstance(orig_option, Option): 177b8e80941Smrg for merged_option in merged_section.options: 178b8e80941Smrg if not isinstance(merged_option, Option): 179b8e80941Smrg continue 180b8e80941Smrg if orig_option.name == merged_option.name: 181b8e80941Smrg merged_option.defaults = orig_option.defaults 182b8e80941Smrg break 183b8e80941Smrg else: 184b8e80941Smrg merged_section.options.append(Option(orig_option.name, orig_option.defaults)) 185b8e80941Smrg else: 186b8e80941Smrg merged_section.options.append(orig_option) 187b8e80941Smrg 188b8e80941Smrg return merged_section 189b8e80941Smrg 190b8e80941Smrg 191b8e80941Smrgdef merge_sections_lists(sections_lists): 192b8e80941Smrg """ 193b8e80941Smrg sections_lists: list of lists of Section objects to be merged 194b8e80941Smrg Return a merged list of merged Section objects; everything is deeply copied. 195b8e80941Smrg Default values for options in later lists override earlier default values. 196b8e80941Smrg """ 197b8e80941Smrg merged_sections = [] 198b8e80941Smrg 199b8e80941Smrg for idx,sections in enumerate(sections_lists): 200b8e80941Smrg for base_section in sections: 201b8e80941Smrg if not isinstance(base_section, Section): 202b8e80941Smrg merged_sections.append(base_section) 203b8e80941Smrg continue 204b8e80941Smrg 205b8e80941Smrg original_sections = [base_section] 206b8e80941Smrg for next_sections in sections_lists[idx+1:]: 207b8e80941Smrg for j,section in enumerate(next_sections): 208b8e80941Smrg if section.name == base_section.name: 209b8e80941Smrg original_sections.append(section) 210b8e80941Smrg del next_sections[j] 211b8e80941Smrg break 212b8e80941Smrg 213b8e80941Smrg merged_section = merge_sections(original_sections) 214b8e80941Smrg 215b8e80941Smrg merged_sections.append(merged_section) 216b8e80941Smrg 217b8e80941Smrg return merged_sections 218b8e80941Smrg 219b8e80941Smrg 220b8e80941Smrgdef main(input_filenames): 221b8e80941Smrg sections_lists = parse_inputs(input_filenames) 222b8e80941Smrg if sections_lists is None: 223b8e80941Smrg return False 224b8e80941Smrg 225b8e80941Smrg merged_sections_list = merge_sections_lists(sections_lists) 226b8e80941Smrg 227b8e80941Smrg driinfo_h_template = mako.template.Template("""\ 228b8e80941Smrg// DO NOT EDIT - this file is automatically generated by merge_driinfo.py 229b8e80941Smrg 230b8e80941Smrg/* 231b8e80941SmrgUse as: 232b8e80941Smrg 233b8e80941Smrg#include "xmlpool.h" 234b8e80941Smrg 235b8e80941Smrgstatic const char driinfo_xml[] = 236b8e80941Smrg#include "this_file" 237b8e80941Smrg; 238b8e80941Smrg*/ 239b8e80941Smrg 240b8e80941SmrgDRI_CONF_BEGIN 241b8e80941Smrg% for section in sections: 242b8e80941Smrg% if isinstance(section, Section): 243b8e80941Smrg DRI_CONF_SECTION_${section.name} 244b8e80941Smrg% for option in section.options: 245b8e80941Smrg% if isinstance(option, Option): 246b8e80941Smrg DRI_CONF_${option.name}(${option.defaults}) 247b8e80941Smrg% else: 248b8e80941Smrg${option.string} 249b8e80941Smrg% endif 250b8e80941Smrg% endfor 251b8e80941Smrg DRI_CONF_SECTION_END 252b8e80941Smrg% else: 253b8e80941Smrg${section.string} 254b8e80941Smrg% endif 255b8e80941Smrg% endfor 256b8e80941SmrgDRI_CONF_END""") 257b8e80941Smrg 258b8e80941Smrg print(driinfo_h_template.render(sections=merged_sections_list, Section=Section, Option=Option)) 259b8e80941Smrg return True 260b8e80941Smrg 261b8e80941Smrg 262b8e80941Smrgif __name__ == '__main__': 263b8e80941Smrg if len(sys.argv) <= 1: 264b8e80941Smrg print('Missing arguments') 265b8e80941Smrg sys.exit(1) 266b8e80941Smrg 267b8e80941Smrg if not main(sys.argv[1:]): 268b8e80941Smrg sys.exit(1) 269