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