blob: 73bc07d16759cd443e5ad2750716e5ffba74a8e3 [file] [log] [blame]
Tobin Ehlis3ed06942014-11-10 16:03:19 -07001#!/usr/bin/env python3
2#
3# XGL
4#
5# Copyright (C) 2014 LunarG, Inc.
6#
7# Permission is hereby granted, free of charge, to any person obtaining a
8# copy of this software and associated documentation files (the "Software"),
9# to deal in the Software without restriction, including without limitation
10# the rights to use, copy, modify, merge, publish, distribute, sublicense,
11# and/or sell copies of the Software, and to permit persons to whom the
12# Software is furnished to do so, subject to the following conditions:
13#
14# The above copyright notice and this permission notice shall be included
15# in all copies or substantial portions of the Software.
16#
17# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23# DEALINGS IN THE SOFTWARE.
Tobin Ehlisee33fa52014-10-22 15:13:53 -060024import argparse
25import os
26import sys
27
28# code_gen.py overview
29# This script generates code based on input headers
30# Initially it's intended to support Mantle and XGL headers and
31# generate wrappers functions that can be used to display
32# structs in a human-readable txt format, as well as utility functions
33# to print enum values as strings
34
35
36def handle_args():
37 parser = argparse.ArgumentParser(description='Perform analysis of vogl trace.')
38 parser.add_argument('input_file', help='The input header file from which code will be generated.')
39 parser.add_argument('--rel_out_dir', required=False, default='glave_gen', help='Path relative to exec path to write output files. Will be created if needed.')
40 parser.add_argument('--abs_out_dir', required=False, default=None, help='Absolute path to write output files. Will be created if needed.')
41 parser.add_argument('--gen_enum_string_helper', required=False, action='store_true', default=False, help='Enable generation of helper header file to print string versions of enums.')
42 parser.add_argument('--gen_struct_wrappers', required=False, action='store_true', default=False, help='Enable generation of struct wrapper classes.')
43 parser.add_argument('--gen_cmake', required=False, action='store_true', default=False, help='Enable generation of cmake file for generated code.')
44 parser.add_argument('--gen_graphviz', required=False, action='store_true', default=False, help='Enable generation of graphviz dot file.')
45 #parser.add_argument('--test', action='store_true', default=False, help='Run simple test.')
46 return parser.parse_args()
47
48# TODO : Ideally these data structs would be opaque to user and could be wrapped
49# in their own class(es) to make them friendly for data look-up
50# Dicts for Data storage
51# enum_val_dict[value_name] = dict keys are the string enum value names for all enums
52# |-------->['type'] = the type of enum class into which the value falls
53# |-------->['val'] = the value assigned to this particular value_name
54# '-------->['unique'] = bool designating if this enum 'val' is unique within this enum 'type'
55enum_val_dict = {}
56# enum_type_dict['type'] = the type or class of of enum
57# '----->['val_name1', 'val_name2'...] = each type references a list of val_names within this type
58enum_type_dict = {}
59# struct_dict['struct_basename'] = the base (non-typedef'd) name of the struct
60# |->[<member_num>] = members are stored via their integer placement in the struct
61# | |->['name'] = string name of this struct member
62# ... |->['full_type'] = complete type qualifier for this member
63# |->['type'] = base type for this member
64# |->['ptr'] = bool indicating if this member is ptr
65# |->['const'] = bool indicating if this member is const
66# |->['struct'] = bool indicating if this member is a struct type
67# |->['array'] = bool indicating if this member is an array
68# '->['array_size'] = int indicating size of array members (0 by default)
69struct_dict = {}
70# typedef_fwd_dict stores mapping from orig_type_name -> new_type_name
71typedef_fwd_dict = {}
72# typedef_rev_dict stores mapping from new_type_name -> orig_type_name
73typedef_rev_dict = {} # store new_name -> orig_name mapping
74# types_dict['id_name'] = identifier name will map to it's type
75# '---->'type' = currently either 'struct' or 'enum'
76types_dict = {} # store orig_name -> type mapping
77
78
79# Class that parses header file and generates data structures that can
80# Then be used for other tasks
81class HeaderFileParser:
82 def __init__(self, header_file=None):
83 self.header_file = header_file
84 # store header data in various formats, see above for more info
85 self.enum_val_dict = {}
86 self.enum_type_dict = {}
87 self.struct_dict = {}
88 self.typedef_fwd_dict = {}
89 self.typedef_rev_dict = {}
90 self.types_dict = {}
91
92 def setHeaderFile(self, header_file):
93 self.header_file = header_file
94
95 def get_enum_val_dict(self):
96 return self.enum_val_dict
97
98 def get_enum_type_dict(self):
99 return self.enum_type_dict
100
101 def get_struct_dict(self):
102 return self.struct_dict
103
104 def get_typedef_fwd_dict(self):
105 return self.typedef_fwd_dict
106
107 def get_typedef_rev_dict(self):
108 return self.typedef_rev_dict
109
110 def get_types_dict(self):
111 return self.types_dict
112
113 # Parse header file into data structures
114 def parse(self):
115 # parse through the file, identifying different sections
116 parse_enum = False
117 parse_struct = False
118 member_num = 0
119 # TODO : Comment parsing is very fragile but handles 2 known files
120 block_comment = False
121 with open(self.header_file) as f:
122 for line in f:
123 if block_comment:
124 if '*/' in line:
125 block_comment = False
126 continue
127 if '/*' in line:
128 block_comment = True
129 elif 0 == len(line.split()):
130 #print("Skipping empty line")
131 continue
132 elif line.split()[0].strip().startswith("//"):
Jon Ashburna0ddc902015-01-09 09:11:44 -0700133 #print("Skipping commented line %s" % line)
Tobin Ehlisee33fa52014-10-22 15:13:53 -0600134 continue
135 elif 'typedef enum' in line:
136 (ty_txt, en_txt, base_type) = line.strip().split(None, 2)
137 #print("Found ENUM type %s" % base_type)
138 parse_enum = True
Jon Ashburna0ddc902015-01-09 09:11:44 -0700139 default_enum_val = 0
Tobin Ehlisee33fa52014-10-22 15:13:53 -0600140 self.types_dict[base_type] = 'enum'
141 elif 'typedef struct' in line:
142 (ty_txt, st_txt, base_type) = line.strip().split(None, 2)
143 #print("Found STRUCT type: %s" % base_type)
144 parse_struct = True
145 self.types_dict[base_type] = 'struct'
Jon Ashburna0ddc902015-01-09 09:11:44 -0700146 elif 'typedef union' in line:
147 (ty_txt, st_txt, base_type) = line.strip().split(None, 2)
148 #print("Found UNION type: %s" % base_type)
149 parse_struct = True
150 self.types_dict[base_type] = 'struct'
Tobin Ehlisee33fa52014-10-22 15:13:53 -0600151 elif '}' in line and (parse_enum or parse_struct):
152 if len(line.split()) > 1: # deals with embedded union in one struct
153 parse_enum = False
154 parse_struct = False
155 member_num = 0
156 # TODO : Can pull target of typedef here for remapping
157 (cur_char, targ_type) = line.strip().split(None, 1)
158 self.typedef_fwd_dict[base_type] = targ_type.strip(';')
159 self.typedef_rev_dict[targ_type.strip(';')] = base_type
160 elif parse_enum:
Jon Ashburna0ddc902015-01-09 09:11:44 -0700161 if 'XGL_MAX_ENUM' not in line and '{' not in line:
162 self._add_enum(line, base_type, default_enum_val)
163 default_enum_val += 1
Tobin Ehlisee33fa52014-10-22 15:13:53 -0600164 elif parse_struct:
165 if ';' in line:
166 self._add_struct(line, base_type, member_num)
167 member_num = member_num + 1
168 #elif '(' in line:
169 #print("Function: %s" % line)
170
171 # populate enum dicts based on enum lines
Jon Ashburna0ddc902015-01-09 09:11:44 -0700172 def _add_enum(self, line_txt, enum_type, def_enum_val):
Tobin Ehlisee33fa52014-10-22 15:13:53 -0600173 #print("Parsing enum line %s" % line_txt)
Jon Ashburna0ddc902015-01-09 09:11:44 -0700174 if '=' in line_txt:
175 (enum_name, eq_char, enum_val) = line_txt.split(None, 2)
176 else:
177 enum_name = line_txt.split(',')[0]
178 enum_val = str(def_enum_val)
Tobin Ehlisee33fa52014-10-22 15:13:53 -0600179 self.enum_val_dict[enum_name] = {}
180 self.enum_val_dict[enum_name]['type'] = enum_type
181 # strip comma and comment, then extra split in case of no comma w/ comments
182 enum_val = enum_val.strip().split(',', 1)[0]
183 self.enum_val_dict[enum_name]['val'] = enum_val.split()[0]
Tobin Ehlis5e848502014-12-05 12:13:07 -0700184 # account for negative values surrounded by parens
185 self.enum_val_dict[enum_name]['val'] = self.enum_val_dict[enum_name]['val'].strip(')').replace('-(', '-')
186 # Try to cast to int to determine if enum value is unique
Tobin Ehlisee33fa52014-10-22 15:13:53 -0600187 try:
188 #print("ENUM val:", self.enum_val_dict[enum_name]['val'])
189 int(self.enum_val_dict[enum_name]['val'], 0)
190 self.enum_val_dict[enum_name]['unique'] = True
191 #print("ENUM has num value")
192 except ValueError:
193 self.enum_val_dict[enum_name]['unique'] = False
194 #print("ENUM is not a number value")
195 # Update enum_type_dict as well
196 if not enum_type in self.enum_type_dict:
197 self.enum_type_dict[enum_type] = []
198 self.enum_type_dict[enum_type].append(enum_name)
199
200 # populate struct dicts based on struct lines
201 # TODO : Handle ":" bitfield, "**" ptr->ptr and "const type*const*"
202 def _add_struct(self, line_txt, struct_type, num):
203 #print("Parsing struct line %s" % line_txt)
204 if not struct_type in self.struct_dict:
205 self.struct_dict[struct_type] = {}
206 members = line_txt.strip().split(';', 1)[0] # first strip semicolon & comments
207 # TODO : Handle bitfields more correctly
208 members = members.strip().split(':', 1)[0] # strip bitfield element
209 (member_type, member_name) = members.rsplit(None, 1)
210 self.struct_dict[struct_type][num] = {}
211 self.struct_dict[struct_type][num]['full_type'] = member_type
212 if '*' in member_type:
213 self.struct_dict[struct_type][num]['ptr'] = True
214 member_type = member_type.strip('*')
215 else:
216 self.struct_dict[struct_type][num]['ptr'] = False
217 if 'const' in member_type:
218 self.struct_dict[struct_type][num]['const'] = True
219 member_type = member_type.strip('const').strip()
220 else:
221 self.struct_dict[struct_type][num]['const'] = False
Tobin Ehlis6f7029b2014-11-11 12:28:12 -0700222 # TODO : There is a bug here where it seems that at the time we do this check,
223 # the data is not in the types or typedef_rev_dict, so we never pass this if check
Tobin Ehlisee33fa52014-10-22 15:13:53 -0600224 if is_type(member_type, 'struct'):
225 self.struct_dict[struct_type][num]['struct'] = True
226 else:
227 self.struct_dict[struct_type][num]['struct'] = False
228 self.struct_dict[struct_type][num]['type'] = member_type
229 if '[' in member_name:
230 (member_name, array_size) = member_name.split('[', 1)
231 self.struct_dict[struct_type][num]['array'] = True
232 self.struct_dict[struct_type][num]['array_size'] = array_size.strip(']')
233 else:
234 self.struct_dict[struct_type][num]['array'] = False
235 self.struct_dict[struct_type][num]['array_size'] = 0
236 self.struct_dict[struct_type][num]['name'] = member_name
237
238# check if given identifier if of specified type_to_check
239def is_type(identifier, type_to_check):
Tobin Ehlisee33fa52014-10-22 15:13:53 -0600240 if identifier in types_dict and type_to_check == types_dict[identifier]:
241 return True
242 if identifier in typedef_rev_dict:
243 new_id = typedef_rev_dict[identifier]
244 if new_id in types_dict and type_to_check == types_dict[new_id]:
245 return True
246 return False
247
248# This is a validation function to verify that we can reproduce the original structs
249def recreate_structs():
250 for struct_name in struct_dict:
251 sys.stdout.write("typedef struct %s\n{\n" % struct_name)
252 for mem_num in sorted(struct_dict[struct_name]):
253 sys.stdout.write(" ")
254 if struct_dict[struct_name][mem_num]['const']:
255 sys.stdout.write("const ")
256 #if struct_dict[struct_name][mem_num]['struct']:
257 # sys.stdout.write("struct ")
258 sys.stdout.write (struct_dict[struct_name][mem_num]['type'])
259 if struct_dict[struct_name][mem_num]['ptr']:
260 sys.stdout.write("*")
261 sys.stdout.write(" ")
262 sys.stdout.write(struct_dict[struct_name][mem_num]['name'])
263 if struct_dict[struct_name][mem_num]['array']:
264 sys.stdout.write("[")
265 sys.stdout.write(struct_dict[struct_name][mem_num]['array_size'])
266 sys.stdout.write("]")
267 sys.stdout.write(";\n")
268 sys.stdout.write("} ")
269 sys.stdout.write(typedef_fwd_dict[struct_name])
270 sys.stdout.write(";\n\n")
271
272# class for writing common file elements
273# Here's how this class lays out a file:
274# COPYRIGHT
275# HEADER
276# BODY
277# FOOTER
278#
279# For each of these sections, there's a "set*" function
280# The class as a whole has a generate function which will write each section in order
281class CommonFileGen:
282 def __init__(self, filename=None, copyright_txt="", header_txt="", body_txt="", footer_txt=""):
283 self.filename = filename
284 self.contents = {'copyright': copyright_txt, 'header': header_txt, 'body': body_txt, 'footer': footer_txt}
285 # TODO : Set a default copyright & footer at least
286
287 def setFilename(self, filename):
288 self.filename = filename
289
290 def setCopyright(self, c):
291 self.contents['copyright'] = c
292
293 def setHeader(self, h):
294 self.contents['header'] = h
295
296 def setBody(self, b):
297 self.contents['body'] = b
298
299 def setFooter(self, f):
300 self.contents['footer'] = f
301
302 def generate(self):
303 #print("Generate to file %s" % self.filename)
304 with open(self.filename, "w") as f:
305 f.write(self.contents['copyright'])
306 f.write(self.contents['header'])
307 f.write(self.contents['body'])
308 f.write(self.contents['footer'])
309
310# class for writing a wrapper class for structures
311# The wrapper class wraps the structs and includes utility functions for
312# setting/getting member values and displaying the struct data in various formats
313class StructWrapperGen:
314 def __init__(self, in_struct_dict, prefix, out_dir):
315 self.struct_dict = in_struct_dict
316 self.include_headers = []
317 self.api = prefix
318 self.header_filename = os.path.join(out_dir, self.api+"_struct_wrappers.h")
319 self.class_filename = os.path.join(out_dir, self.api+"_struct_wrappers.cpp")
320 self.string_helper_filename = os.path.join(out_dir, self.api+"_struct_string_helper.h")
Tobin Ehlis07fe9ab2014-11-25 17:43:26 -0700321 self.string_helper_no_addr_filename = os.path.join(out_dir, self.api+"_struct_string_helper_no_addr.h")
Tobin Ehlis434db7c2015-01-10 12:42:41 -0700322 self.string_helper_cpp_filename = os.path.join(out_dir, self.api+"_struct_string_helper_cpp.h")
323 self.string_helper_no_addr_cpp_filename = os.path.join(out_dir, self.api+"_struct_string_helper_no_addr_cpp.h")
Tobin Ehlis6cd06372014-12-17 17:44:50 -0700324 self.validate_helper_filename = os.path.join(out_dir, self.api+"_struct_validate_helper.h")
Tobin Ehlis07fe9ab2014-11-25 17:43:26 -0700325 self.no_addr = False
Tobin Ehlisee33fa52014-10-22 15:13:53 -0600326 self.hfg = CommonFileGen(self.header_filename)
327 self.cfg = CommonFileGen(self.class_filename)
328 self.shg = CommonFileGen(self.string_helper_filename)
Tobin Ehlis434db7c2015-01-10 12:42:41 -0700329 self.shcppg = CommonFileGen(self.string_helper_cpp_filename)
Tobin Ehlis6cd06372014-12-17 17:44:50 -0700330 self.vhg = CommonFileGen(self.validate_helper_filename)
Tobin Ehlisee33fa52014-10-22 15:13:53 -0600331 #print(self.header_filename)
332 self.header_txt = ""
333 self.definition_txt = ""
334
335 def set_include_headers(self, include_headers):
336 self.include_headers = include_headers
337
Tobin Ehlis07fe9ab2014-11-25 17:43:26 -0700338 def set_no_addr(self, no_addr):
339 self.no_addr = no_addr
340 if self.no_addr:
341 self.shg = CommonFileGen(self.string_helper_no_addr_filename)
Tobin Ehlis434db7c2015-01-10 12:42:41 -0700342 self.shcppg = CommonFileGen(self.string_helper_no_addr_cpp_filename)
Tobin Ehlis07fe9ab2014-11-25 17:43:26 -0700343 else:
344 self.shg = CommonFileGen(self.string_helper_filename)
Tobin Ehlis434db7c2015-01-10 12:42:41 -0700345 self.shcppg = CommonFileGen(self.string_helper_cpp_filename)
Tobin Ehlis07fe9ab2014-11-25 17:43:26 -0700346
Tobin Ehlisee33fa52014-10-22 15:13:53 -0600347 # Return class name for given struct name
348 def get_class_name(self, struct_name):
349 class_name = struct_name.strip('_').lower() + "_struct_wrapper"
350 return class_name
351
352 def get_file_list(self):
353 return [os.path.basename(self.header_filename), os.path.basename(self.class_filename), os.path.basename(self.string_helper_filename)]
354
355 # Generate class header file
356 def generateHeader(self):
357 self.hfg.setCopyright(self._generateCopyright())
358 self.hfg.setHeader(self._generateHeader())
359 self.hfg.setBody(self._generateClassDeclaration())
360 self.hfg.setFooter(self._generateFooter())
361 self.hfg.generate()
362
363 # Generate class definition
364 def generateBody(self):
365 self.cfg.setCopyright(self._generateCopyright())
366 self.cfg.setHeader(self._generateCppHeader())
367 self.cfg.setBody(self._generateClassDefinition())
368 self.cfg.setFooter(self._generateFooter())
369 self.cfg.generate()
370
371 # Generate c-style .h file that contains functions for printing structs
372 def generateStringHelper(self):
373 print("Generating struct string helper")
374 self.shg.setCopyright(self._generateCopyright())
375 self.shg.setHeader(self._generateStringHelperHeader())
376 self.shg.setBody(self._generateStringHelperFunctions())
377 self.shg.generate()
378
Tobin Ehlis434db7c2015-01-10 12:42:41 -0700379 # Generate cpp-style .h file that contains functions for printing structs
380 def generateStringHelperCpp(self):
381 print("Generating struct string helper cpp")
382 self.shcppg.setCopyright(self._generateCopyright())
383 self.shcppg.setHeader(self._generateStringHelperHeaderCpp())
384 self.shcppg.setBody(self._generateStringHelperFunctionsCpp())
385 self.shcppg.generate()
386
Tobin Ehlis6cd06372014-12-17 17:44:50 -0700387 # Generate c-style .h file that contains functions for printing structs
388 def generateValidateHelper(self):
389 print("Generating struct validate helper")
390 self.vhg.setCopyright(self._generateCopyright())
391 self.vhg.setHeader(self._generateValidateHelperHeader())
392 self.vhg.setBody(self._generateValidateHelperFunctions())
393 self.vhg.generate()
394
Tobin Ehlisee33fa52014-10-22 15:13:53 -0600395 def _generateCopyright(self):
396 return "//This is the copyright\n"
397
398 def _generateCppHeader(self):
399 header = []
400 header.append("//#includes, #defines, globals and such...\n")
Tobin Ehlis3ed06942014-11-10 16:03:19 -0700401 header.append("#include <stdio.h>\n#include <%s>\n#include <%s_enum_string_helper.h>\n" % (os.path.basename(self.header_filename), self.api))
Tobin Ehlisee33fa52014-10-22 15:13:53 -0600402 return "".join(header)
403
404 def _generateClassDefinition(self):
405 class_def = []
406 if 'xgl' == self.api: # Mantle doesn't have pNext to worry about
407 class_def.append(self._generateDynamicPrintFunctions())
408 for s in self.struct_dict:
409 class_def.append("\n// %s class definition" % self.get_class_name(s))
410 class_def.append(self._generateConstructorDefinitions(s))
411 class_def.append(self._generateDestructorDefinitions(s))
412 class_def.append(self._generateDisplayDefinitions(s))
413 return "\n".join(class_def)
414
415 def _generateConstructorDefinitions(self, s):
416 con_defs = []
417 con_defs.append("%s::%s() : m_struct(), m_indent(0), m_dummy_prefix('\\0'), m_origStructAddr(NULL) {}" % (self.get_class_name(s), self.get_class_name(s)))
418 # TODO : This is a shallow copy of ptrs
419 con_defs.append("%s::%s(%s* pInStruct) : m_indent(0), m_dummy_prefix('\\0')\n{\n m_struct = *pInStruct;\n m_origStructAddr = pInStruct;\n}" % (self.get_class_name(s), self.get_class_name(s), typedef_fwd_dict[s]))
420 con_defs.append("%s::%s(const %s* pInStruct) : m_indent(0), m_dummy_prefix('\\0')\n{\n m_struct = *pInStruct;\n m_origStructAddr = pInStruct;\n}" % (self.get_class_name(s), self.get_class_name(s), typedef_fwd_dict[s]))
421 return "\n".join(con_defs)
422
423 def _generateDestructorDefinitions(self, s):
424 return "%s::~%s() {}" % (self.get_class_name(s), self.get_class_name(s))
425
426 def _generateDynamicPrintFunctions(self):
427 dp_funcs = []
428 dp_funcs.append("\nvoid dynamic_display_full_txt(const XGL_VOID* pStruct, uint32_t indent)\n{\n // Cast to APP_INFO ptr initially just to pull sType off struct")
429 dp_funcs.append(" XGL_STRUCTURE_TYPE sType = ((XGL_APPLICATION_INFO*)pStruct)->sType;\n")
430 dp_funcs.append(" switch (sType)\n {")
431 for e in enum_type_dict:
432 class_num = 0
433 if "_STRUCTURE_TYPE" in e:
434 for v in sorted(enum_type_dict[e]):
435 struct_name = v.replace("_STRUCTURE_TYPE", "")
436 class_name = self.get_class_name(struct_name)
437 # TODO : Hand-coded fixes for some exceptions
438 if 'XGL_PIPELINE_CB_STATE_CREATE_INFO' in struct_name:
439 struct_name = 'XGL_PIPELINE_CB_STATE'
440 elif 'XGL_SEMAPHORE_CREATE_INFO' in struct_name:
441 struct_name = 'XGL_QUEUE_SEMAPHORE_CREATE_INFO'
442 class_name = self.get_class_name(struct_name)
443 elif 'XGL_SEMAPHORE_OPEN_INFO' in struct_name:
444 struct_name = 'XGL_QUEUE_SEMAPHORE_OPEN_INFO'
445 class_name = self.get_class_name(struct_name)
446 instance_name = "swc%i" % class_num
447 dp_funcs.append(" case %s:\n {" % (v))
448 dp_funcs.append(" %s %s((%s*)pStruct);" % (class_name, instance_name, struct_name))
449 dp_funcs.append(" %s.set_indent(indent);" % (instance_name))
450 dp_funcs.append(" %s.display_full_txt();" % (instance_name))
451 dp_funcs.append(" }")
452 dp_funcs.append(" break;")
453 class_num += 1
454 dp_funcs.append(" }")
455 dp_funcs.append("}\n")
456 return "\n".join(dp_funcs)
457
Tobin Ehlis6cd06372014-12-17 17:44:50 -0700458 def _get_func_name(self, struct, mid_str):
459 return "%s_%s_%s" % (self.api, mid_str, struct.lower().strip("_"))
460
Tobin Ehlisee33fa52014-10-22 15:13:53 -0600461 def _get_sh_func_name(self, struct):
Tobin Ehlis6cd06372014-12-17 17:44:50 -0700462 return self._get_func_name(struct, 'print')
463
464 def _get_vh_func_name(self, struct):
465 return self._get_func_name(struct, 'validate')
Tobin Ehlisee33fa52014-10-22 15:13:53 -0600466
467 # Return elements to create formatted string for given struct member
468 def _get_struct_print_formatted(self, struct_member, pre_var_name="prefix", postfix = "\\n", struct_var_name="pStruct", struct_ptr=True, print_array=False):
469 struct_op = "->"
470 if not struct_ptr:
471 struct_op = "."
472 member_name = struct_member['name']
473 print_type = "p"
474 cast_type = ""
475 member_post = ""
476 array_index = ""
477 member_print_post = ""
478 if struct_member['array'] and 'CHAR' in struct_member['type']: # just print char array as string
479 print_type = "s"
480 print_array = False
481 elif struct_member['array'] and not print_array:
482 # Just print base address of array when not full print_array
483 cast_type = "(void*)"
484 elif is_type(struct_member['type'], 'enum'):
485 cast_type = "string_%s" % struct_member['type']
Jon Ashburna0ddc902015-01-09 09:11:44 -0700486 if struct_member['ptr']:
487 struct_var_name = "*" + struct_var_name
Tobin Ehlisee33fa52014-10-22 15:13:53 -0600488 print_type = "s"
489 elif is_type(struct_member['type'], 'struct'): # print struct address for now
490 cast_type = "(void*)"
491 if not struct_member['ptr']:
492 cast_type = "(void*)&"
493 elif 'BOOL' in struct_member['type']:
494 print_type = "s"
495 member_post = ' ? "TRUE" : "FALSE"'
496 elif 'FLOAT' in struct_member['type']:
497 print_type = "f"
498 elif 'UINT64' in struct_member['type']:
499 print_type = "lu"
500 elif 'UINT8' in struct_member['type']:
501 print_type = "hu"
Chia-I Wu54ed0792014-12-27 14:14:50 +0800502 elif '_SIZE' in struct_member['type']:
503 print_type = "zu"
504 elif True in [ui_str in struct_member['type'] for ui_str in ['UINT', '_FLAGS', '_SAMPLE_MASK']]:
Tobin Ehlisee33fa52014-10-22 15:13:53 -0600505 print_type = "u"
506 elif 'INT' in struct_member['type']:
507 print_type = "i"
508 elif struct_member['ptr']:
Tobin Ehlisee33fa52014-10-22 15:13:53 -0600509 pass
510 else:
511 #print("Unhandled struct type: %s" % struct_member['type'])
512 cast_type = "(void*)"
513 if print_array and struct_member['array']:
514 member_print_post = "[%u]"
515 array_index = " i,"
516 member_post = "[i]"
517 print_out = "%%s%s%s = %%%s%s" % (member_name, member_print_post, print_type, postfix) # section of print that goes inside of quotes
518 print_arg = ", %s,%s %s(%s%s%s)%s" % (pre_var_name, array_index, cast_type, struct_var_name, struct_op, member_name, member_post) # section of print passed to portion in quotes
Tobin Ehlis07fe9ab2014-11-25 17:43:26 -0700519 if self.no_addr and "p" == print_type:
520 print_out = "%%s%s%s = addr\\n" % (member_name, member_print_post) # section of print that goes inside of quotes
521 print_arg = ", %s" % (pre_var_name)
Tobin Ehlisee33fa52014-10-22 15:13:53 -0600522 return (print_out, print_arg)
523
524 def _generateStringHelperFunctions(self):
525 sh_funcs = []
Tobin Ehlis6f7029b2014-11-11 12:28:12 -0700526 # We do two passes, first pass just generates prototypes for all the functsions
527 for s in self.struct_dict:
528 sh_funcs.append('char* %s(const %s* pStruct, const char* prefix);\n' % (self._get_sh_func_name(s), typedef_fwd_dict[s]))
Tobin Ehlisa701ef02014-11-27 15:43:39 -0700529 sh_funcs.append('\n')
Tobin Ehlisee33fa52014-10-22 15:13:53 -0600530 for s in self.struct_dict:
531 p_out = ""
532 p_args = ""
Tobin Ehlis6f7029b2014-11-11 12:28:12 -0700533 stp_list = [] # stp == "struct to print" a list of structs for this API call that should be printed as structs
Tobin Ehlisee33fa52014-10-22 15:13:53 -0600534 # This isn't great but this pre-pass counts chars in struct members and flags structs w/ pNext
Tobin Ehlisee33fa52014-10-22 15:13:53 -0600535 for m in self.struct_dict[s]:
Tobin Ehlis6f7029b2014-11-11 12:28:12 -0700536 if 'pNext' == self.struct_dict[s][m]['name'] or is_type(self.struct_dict[s][m]['type'], 'struct'):
537 stp_list.append(self.struct_dict[s][m])
Tobin Ehlisee33fa52014-10-22 15:13:53 -0600538 sh_funcs.append('char* %s(const %s* pStruct, const char* prefix)\n{\n char* str;\n' % (self._get_sh_func_name(s), typedef_fwd_dict[s]))
Courtney Goeltzenleuchtercde421c2014-12-01 09:31:17 -0700539 sh_funcs.append(" size_t len;\n")
Tobin Ehlis6f7029b2014-11-11 12:28:12 -0700540 num_stps = len(stp_list);
541 total_strlen_str = ''
542 if 0 != num_stps:
543 sh_funcs.append(" char* tmpStr;\n")
Courtney Goeltzenleuchter64efe722014-11-18 10:39:30 -0700544 sh_funcs.append(' char* extra_indent = (char*)malloc(strlen(prefix) + 3);\n')
Tobin Ehlis6f7029b2014-11-11 12:28:12 -0700545 sh_funcs.append(' strcpy(extra_indent, " ");\n')
546 sh_funcs.append(' strncat(extra_indent, prefix, strlen(prefix));\n')
Tobin Ehlis6f7029b2014-11-11 12:28:12 -0700547 sh_funcs.append(' char* stp_strs[%i];\n' % num_stps)
548 for index in range(num_stps):
549 if (stp_list[index]['ptr']):
550 sh_funcs.append(' if (pStruct->%s) {\n' % stp_list[index]['name'])
551 if 'pNext' == stp_list[index]['name']:
Tobin Ehlis08f24042014-11-20 06:38:50 -0700552 sh_funcs.append(' tmpStr = dynamic_display((XGL_VOID*)pStruct->pNext, prefix);\n')
Courtney Goeltzenleuchtercde421c2014-12-01 09:31:17 -0700553 sh_funcs.append(' len = 256+strlen(tmpStr);\n')
554 sh_funcs.append(' stp_strs[%i] = (char*)malloc(len);\n' % index)
Tobin Ehlis07fe9ab2014-11-25 17:43:26 -0700555 if self.no_addr:
Tobin Ehlis434db7c2015-01-10 12:42:41 -0700556 sh_funcs.append(' snprintf(stp_strs[%i], len, " %%spNext (addr)\\n%%s", prefix, tmpStr);\n' % index)
Tobin Ehlis07fe9ab2014-11-25 17:43:26 -0700557 else:
Tobin Ehlis434db7c2015-01-10 12:42:41 -0700558 sh_funcs.append(' snprintf(stp_strs[%i], len, " %%spNext (%%p)\\n%%s", prefix, (void*)pStruct->pNext, tmpStr);\n' % index)
Tobin Ehlis08f24042014-11-20 06:38:50 -0700559 sh_funcs.append(' free(tmpStr);\n')
Tobin Ehlis6f7029b2014-11-11 12:28:12 -0700560 else:
561 sh_funcs.append(' tmpStr = %s(pStruct->%s, extra_indent);\n' % (self._get_sh_func_name(stp_list[index]['type']), stp_list[index]['name']))
Courtney Goeltzenleuchtercde421c2014-12-01 09:31:17 -0700562 sh_funcs.append(' len = 256+strlen(tmpStr)+strlen(prefix);\n')
563 sh_funcs.append(' stp_strs[%i] = (char*)malloc(len);\n' % (index))
Tobin Ehlis07fe9ab2014-11-25 17:43:26 -0700564 if self.no_addr:
Courtney Goeltzenleuchtercde421c2014-12-01 09:31:17 -0700565 sh_funcs.append(' snprintf(stp_strs[%i], len, " %%s%s (addr)\\n%%s", prefix, tmpStr);\n' % (index, stp_list[index]['name']))
Tobin Ehlis07fe9ab2014-11-25 17:43:26 -0700566 else:
Courtney Goeltzenleuchtercde421c2014-12-01 09:31:17 -0700567 sh_funcs.append(' snprintf(stp_strs[%i], len, " %%s%s (%%p)\\n%%s", prefix, (void*)pStruct->%s, tmpStr);\n' % (index, stp_list[index]['name'], stp_list[index]['name']))
Tobin Ehlis6f7029b2014-11-11 12:28:12 -0700568 sh_funcs.append(' }\n')
Chia-I Wu81f46672014-12-16 00:36:58 +0800569 sh_funcs.append(" else\n stp_strs[%i] = \"\";\n" % (index))
Tobin Ehlis6f7029b2014-11-11 12:28:12 -0700570 elif stp_list[index]['array']: # TODO : For now just printing first element of array
571 sh_funcs.append(' tmpStr = %s(&pStruct->%s[0], extra_indent);\n' % (self._get_sh_func_name(stp_list[index]['type']), stp_list[index]['name']))
Courtney Goeltzenleuchtercde421c2014-12-01 09:31:17 -0700572 sh_funcs.append(' len = 256+strlen(tmpStr);\n')
573 sh_funcs.append(' stp_strs[%i] = (char*)malloc(len);\n' % (index))
Tobin Ehlis07fe9ab2014-11-25 17:43:26 -0700574 if self.no_addr:
Courtney Goeltzenleuchtercde421c2014-12-01 09:31:17 -0700575 sh_funcs.append(' snprintf(stp_strs[%i], len, " %%s%s[0] (addr)\\n%%s", prefix, tmpStr);\n' % (index, stp_list[index]['name']))
Tobin Ehlis07fe9ab2014-11-25 17:43:26 -0700576 else:
Courtney Goeltzenleuchtercde421c2014-12-01 09:31:17 -0700577 sh_funcs.append(' snprintf(stp_strs[%i], len, " %%s%s[0] (%%p)\\n%%s", prefix, (void*)&pStruct->%s[0], tmpStr);\n' % (index, stp_list[index]['name'], stp_list[index]['name']))
Tobin Ehlis6f7029b2014-11-11 12:28:12 -0700578 else:
579 sh_funcs.append(' tmpStr = %s(&pStruct->%s, extra_indent);\n' % (self._get_sh_func_name(stp_list[index]['type']), stp_list[index]['name']))
Courtney Goeltzenleuchtercde421c2014-12-01 09:31:17 -0700580 sh_funcs.append(' len = 256+strlen(tmpStr);\n')
581 sh_funcs.append(' stp_strs[%i] = (char*)malloc(len);\n' % (index))
Tobin Ehlis07fe9ab2014-11-25 17:43:26 -0700582 if self.no_addr:
Courtney Goeltzenleuchtercde421c2014-12-01 09:31:17 -0700583 sh_funcs.append(' snprintf(stp_strs[%i], len, " %%s%s (addr)\\n%%s", prefix, tmpStr);\n' % (index, stp_list[index]['name']))
Tobin Ehlis07fe9ab2014-11-25 17:43:26 -0700584 else:
Courtney Goeltzenleuchtercde421c2014-12-01 09:31:17 -0700585 sh_funcs.append(' snprintf(stp_strs[%i], len, " %%s%s (%%p)\\n%%s", prefix, (void*)&pStruct->%s, tmpStr);\n' % (index, stp_list[index]['name'], stp_list[index]['name']))
Tobin Ehlis6f7029b2014-11-11 12:28:12 -0700586 total_strlen_str += 'strlen(stp_strs[%i]) + ' % index
Courtney Goeltzenleuchtercde421c2014-12-01 09:31:17 -0700587 sh_funcs.append(' len = %ssizeof(char)*1024;\n' % (total_strlen_str))
588 sh_funcs.append(' str = (char*)malloc(len);\n')
589 sh_funcs.append(' snprintf(str, len, "')
Tobin Ehlisee33fa52014-10-22 15:13:53 -0600590 for m in sorted(self.struct_dict[s]):
591 (p_out1, p_args1) = self._get_struct_print_formatted(self.struct_dict[s][m])
592 p_out += p_out1
593 p_args += p_args1
Tobin Ehlisee33fa52014-10-22 15:13:53 -0600594 p_out += '"'
595 p_args += ");\n"
596 sh_funcs.append(p_out)
597 sh_funcs.append(p_args)
Tobin Ehlis6f7029b2014-11-11 12:28:12 -0700598 if 0 != num_stps:
Tobin Ehlis08f24042014-11-20 06:38:50 -0700599 sh_funcs.append(' for (int32_t stp_index = %i; stp_index >= 0; stp_index--) {\n' % (num_stps-1))
Tobin Ehlis6f7029b2014-11-11 12:28:12 -0700600 sh_funcs.append(' if (0 < strlen(stp_strs[stp_index])) {\n')
601 sh_funcs.append(' strncat(str, stp_strs[stp_index], strlen(stp_strs[stp_index]));\n')
602 sh_funcs.append(' free(stp_strs[stp_index]);\n')
603 sh_funcs.append(' }\n')
Tobin Ehlisee33fa52014-10-22 15:13:53 -0600604 sh_funcs.append(' }\n')
605 sh_funcs.append(" return str;\n}\n")
606 # Add function to dynamically print out unknown struct
607 sh_funcs.append("char* dynamic_display(const XGL_VOID* pStruct, const char* prefix)\n{\n")
608 sh_funcs.append(" // Cast to APP_INFO ptr initially just to pull sType off struct\n")
609 sh_funcs.append(" XGL_STRUCTURE_TYPE sType = ((XGL_APPLICATION_INFO*)pStruct)->sType;\n")
610 sh_funcs.append(' char indent[100];\n strcpy(indent, " ");\n strcat(indent, prefix);\n')
611 sh_funcs.append(" switch (sType)\n {\n")
612 for e in enum_type_dict:
613 if "_STRUCTURE_TYPE" in e:
614 for v in sorted(enum_type_dict[e]):
615 struct_name = v.replace("_STRUCTURE_TYPE", "")
616 print_func_name = self._get_sh_func_name(struct_name)
617 # TODO : Hand-coded fixes for some exceptions
618 if 'XGL_PIPELINE_CB_STATE_CREATE_INFO' in struct_name:
619 struct_name = 'XGL_PIPELINE_CB_STATE'
620 elif 'XGL_SEMAPHORE_CREATE_INFO' in struct_name:
621 struct_name = 'XGL_QUEUE_SEMAPHORE_CREATE_INFO'
622 print_func_name = self._get_sh_func_name(struct_name)
623 elif 'XGL_SEMAPHORE_OPEN_INFO' in struct_name:
624 struct_name = 'XGL_QUEUE_SEMAPHORE_OPEN_INFO'
625 print_func_name = self._get_sh_func_name(struct_name)
626 sh_funcs.append(' case %s:\n {\n' % (v))
627 sh_funcs.append(' return %s((%s*)pStruct, indent);\n' % (print_func_name, struct_name))
628 sh_funcs.append(' }\n')
629 sh_funcs.append(' break;\n')
Chia-I Wu84d7f5c2014-12-16 00:43:20 +0800630 sh_funcs.append(" default:\n")
631 sh_funcs.append(" return NULL;\n")
Tobin Ehlisee33fa52014-10-22 15:13:53 -0600632 sh_funcs.append(" }\n")
633 sh_funcs.append("}")
634 return "".join(sh_funcs)
Tobin Ehlis434db7c2015-01-10 12:42:41 -0700635
636 def _generateStringHelperFunctionsCpp(self):
637 # declare str & tmp str
638 # declare array of stringstreams for every struct ptr in current struct
639 # declare array of stringstreams for every non-string element in current struct
640 # For every struct ptr, it non-Null, then set it's string, else set to NULL str
641 # For every non-string element, set it's string stream
642 # create and return final string
643 sh_funcs = []
644 # First generate prototypes for every struct
645 for s in self.struct_dict:
646 sh_funcs.append('string %s(const %s* pStruct, const string prefix);' % (self._get_sh_func_name(s), typedef_fwd_dict[s]))
647 sh_funcs.append('\n')
648 for s in self.struct_dict:
649 num_non_enum_elems = [is_type(self.struct_dict[s][elem]['type'], 'enum') for elem in self.struct_dict[s]].count(False)
650 stp_list = [] # stp == "struct to print" a list of structs for this API call that should be printed as structs
651 # This isn't great but this pre-pass counts chars in struct members and flags structs w/ pNext
652 for m in self.struct_dict[s]:
653 if 'pNext' == self.struct_dict[s][m]['name'] or is_type(self.struct_dict[s][m]['type'], 'struct'):
654 stp_list.append(self.struct_dict[s][m])
655 sh_funcs.append('string %s(const %s* pStruct, const string prefix)\n{' % (self._get_sh_func_name(s), typedef_fwd_dict[s]))
656 sh_funcs.append(' string final_str;')
657 sh_funcs.append(' string tmp_str;')
658 sh_funcs.append(' string extra_indent = " " + prefix;')
659 sh_funcs.append(' stringstream ss[%u];' % num_non_enum_elems)
660 num_stps = len(stp_list)
661 # First generate code for any embedded structs
662 if 0 < num_stps:
663 sh_funcs.append(' string stp_strs[%u];' % num_stps)
664 idx_ss_decl = False # Make sure to only decl this once
665 for index in range(num_stps):
666 addr_char = '&'
667 if stp_list[index]['ptr']:
668 addr_char = ''
669 if (stp_list[index]['ptr']):
670 sh_funcs.append(' if (pStruct->%s) {' % stp_list[index]['name'])
671 if 'pNext' == stp_list[index]['name']:
672 sh_funcs.append(' tmp_str = dynamic_display((XGL_VOID*)pStruct->pNext, prefix);')
673 else:
674 sh_funcs.append(' tmp_str = %s(pStruct->%s, extra_indent);' % (self._get_sh_func_name(stp_list[index]['type']), stp_list[index]['name']))
675 sh_funcs.append(' ss[%u] << %spStruct->%s;' % (index, addr_char, stp_list[index]['name']))
676 if self.no_addr:
677 sh_funcs.append(' stp_strs[%u] = " " + prefix + "%s (addr)\\n" + tmp_str;' % (index, stp_list[index]['name']))
678 else:
679 sh_funcs.append(' stp_strs[%u] = " " + prefix + "%s (" + ss[%u].str() + ")\\n" + tmp_str;' % (index, stp_list[index]['name'], index))
680 sh_funcs.append(' ss[%u].str("");' % (index))
681 sh_funcs.append(' }')
682 sh_funcs.append(' else')
683 sh_funcs.append(' stp_strs[%u] = "";' % index)
684 elif (stp_list[index]['array']):
685 sh_funcs.append(' stp_strs[%u] = "";' % index)
686 if not idx_ss_decl:
687 sh_funcs.append(' stringstream index_ss;')
688 idx_ss_decl = True
689 sh_funcs.append(' for (uint32_t i = 0; i < %s; i++) {' % stp_list[index]['array_size'])
690 sh_funcs.append(' index_ss.str("");')
691 sh_funcs.append(' index_ss << i;')
692 sh_funcs.append(' ss[%u] << %spStruct->%s[i];' % (index, addr_char, stp_list[index]['name']))
693 sh_funcs.append(' tmp_str = %s(&pStruct->%s[i], extra_indent);' % (self._get_sh_func_name(stp_list[index]['type']), stp_list[index]['name']))
694 if self.no_addr:
695 sh_funcs.append(' stp_strs[%u] += " " + prefix + "%s[" + index_ss.str() + "] (addr)\\n" + tmp_str;' % (index, stp_list[index]['name']))
696 else:
697 sh_funcs.append(' stp_strs[%u] += " " + prefix + "%s[" + index_ss.str() + "] (" + ss[%u].str() + ")\\n" + tmp_str;' % (index, stp_list[index]['name'], index))
698 sh_funcs.append(' ss[%u].str("");' % index)
699 sh_funcs.append(' }')
700 else:
701 sh_funcs.append(' tmp_str = %s(&pStruct->%s, extra_indent);' % (self._get_sh_func_name(stp_list[index]['type']), stp_list[index]['name']))
702 sh_funcs.append(' ss[%u] << %spStruct->%s;' % (index, addr_char, stp_list[index]['name']))
703 if self.no_addr:
704 sh_funcs.append(' stp_strs[%u] = " " + prefix + "%s (addr)\\n" + tmp_str;' % (index, stp_list[index]['name']))
705 else:
706 sh_funcs.append(' stp_strs[%u] = " " + prefix + "%s (" + ss[%u].str() + ")\\n" + tmp_str;' % (index, stp_list[index]['name'], index))
707 sh_funcs.append(' ss[%u].str("");' % index)
708 # Now print non-enum data members
709 index = 0
710 final_str = ''
711 for m in sorted(self.struct_dict[s]):
712 if not is_type(self.struct_dict[s][m]['type'], 'enum'):
713 if is_type(self.struct_dict[s][m]['type'], 'struct') and not self.struct_dict[s][m]['ptr']:
714 if self.no_addr:
715 sh_funcs.append(' ss[%u].str("addr");' % (index))
716 else:
717 sh_funcs.append(' ss[%u] << &pStruct->%s;' % (index, self.struct_dict[s][m]['name']))
718 elif 'BOOL' in self.struct_dict[s][m]['type']:
719 sh_funcs.append(' ss[%u].str(pStruct->%s ? "TRUE" : "FALSE");' % (index, self.struct_dict[s][m]['name']))
720 elif 'UINT8' in self.struct_dict[s][m]['type']:
721 sh_funcs.append(' ss[%u] << (uint32_t)pStruct->%s;' % (index, self.struct_dict[s][m]['name']))
722 else:
723 (po, pa) = self._get_struct_print_formatted(self.struct_dict[s][m])
724 if "addr" in po or self.struct_dict[s][m]['ptr']:
725 sh_funcs.append(' ss[%u].str("addr");' % (index))
726 else:
727 sh_funcs.append(' ss[%u] << pStruct->%s;' % (index, self.struct_dict[s][m]['name']))
728 value_print = 'ss[%u].str()' % index
729 index += 1
730 else:
731 value_print = 'string_%s(pStruct->%s)' % (self.struct_dict[s][m]['type'], self.struct_dict[s][m]['name'])
732 final_str += ' + prefix + "%s = " + %s + "\\n"' % (self.struct_dict[s][m]['name'], value_print)
733 final_str = final_str[3:] # strip off the initial ' + '
734 if 0 != num_stps:
735 final_str += " + %s" % " + ".join(['stp_strs[%u]' % n for n in reversed(range(num_stps))])
736 sh_funcs.append(' final_str = %s;' % final_str)
737 sh_funcs.append(' return final_str;\n}')
738 # Add function to dynamically print out unknown struct
739 sh_funcs.append("string dynamic_display(const XGL_VOID* pStruct, const string prefix)\n{")
740 sh_funcs.append(" // Cast to APP_INFO ptr initially just to pull sType off struct")
741 sh_funcs.append(" XGL_STRUCTURE_TYPE sType = ((XGL_APPLICATION_INFO*)pStruct)->sType;")
742 sh_funcs.append(' string indent = " ";')
743 sh_funcs.append(' indent += prefix;')
744 sh_funcs.append(" switch (sType)\n {")
745 for e in enum_type_dict:
746 if "_STRUCTURE_TYPE" in e:
747 for v in sorted(enum_type_dict[e]):
748 struct_name = v.replace("_STRUCTURE_TYPE", "")
749 print_func_name = self._get_sh_func_name(struct_name)
750 # TODO : Hand-coded fixes for some exceptions
751 if 'XGL_PIPELINE_CB_STATE_CREATE_INFO' in struct_name:
752 struct_name = 'XGL_PIPELINE_CB_STATE'
753 elif 'XGL_SEMAPHORE_CREATE_INFO' in struct_name:
754 struct_name = 'XGL_QUEUE_SEMAPHORE_CREATE_INFO'
755 print_func_name = self._get_sh_func_name(struct_name)
756 elif 'XGL_SEMAPHORE_OPEN_INFO' in struct_name:
757 struct_name = 'XGL_QUEUE_SEMAPHORE_OPEN_INFO'
758 print_func_name = self._get_sh_func_name(struct_name)
759 sh_funcs.append(' case %s:\n {' % (v))
760 sh_funcs.append(' return %s((%s*)pStruct, indent);' % (print_func_name, struct_name))
761 sh_funcs.append(' }')
762 sh_funcs.append(' break;')
763 sh_funcs.append(" default:")
764 sh_funcs.append(" return NULL;")
765 sh_funcs.append(" }")
766 sh_funcs.append("}")
767 return "\n".join(sh_funcs)
Tobin Ehlisee33fa52014-10-22 15:13:53 -0600768
769 def _genStructMemberPrint(self, member, s, array, struct_array):
770 (p_out, p_arg) = self._get_struct_print_formatted(self.struct_dict[s][member], pre_var_name="&m_dummy_prefix", struct_var_name="m_struct", struct_ptr=False, print_array=True)
771 extra_indent = ""
772 if array:
773 extra_indent = " "
774 if is_type(self.struct_dict[s][member]['type'], 'struct'): # print struct address for now
775 struct_array.insert(0, self.struct_dict[s][member])
776 elif self.struct_dict[s][member]['ptr']:
777 # Special case for VOID* named "pNext"
778 if "VOID" in self.struct_dict[s][member]['type'] and "pNext" == self.struct_dict[s][member]['name']:
779 struct_array.insert(0, self.struct_dict[s][member])
780 return (' %sprintf("%%*s %s", m_indent, ""%s);' % (extra_indent, p_out, p_arg), struct_array)
781
782 def _generateDisplayDefinitions(self, s):
783 disp_def = []
784 struct_array = []
785 # Single-line struct print function
786 disp_def.append("// Output 'structname = struct_address' on a single line")
787 disp_def.append("void %s::display_single_txt()\n{" % self.get_class_name(s))
788 disp_def.append(' printf(" %%*s%s = %%p", m_indent, "", (void*)m_origStructAddr);' % typedef_fwd_dict[s])
789 disp_def.append("}\n")
790 # Private helper function to print struct members
791 disp_def.append("// Private helper function that displays the members of the wrapped struct")
792 disp_def.append("void %s::display_struct_members()\n{" % self.get_class_name(s))
793 i_declared = False
794 for member in sorted(self.struct_dict[s]):
795 # TODO : Need to display each member based on its type
796 # TODO : Need to handle pNext which are structs, but of XGL_VOID* type
797 # Can grab struct type off of header of struct pointed to
798 # TODO : Handle Arrays
799 if self.struct_dict[s][member]['array']:
800 # Create for loop to print each element of array
801 if not i_declared:
802 disp_def.append(' uint32_t i;')
803 i_declared = True
804 disp_def.append(' for (i = 0; i<%s; i++) {' % self.struct_dict[s][member]['array_size'])
805 (return_str, struct_array) = self._genStructMemberPrint(member, s, True, struct_array)
806 disp_def.append(return_str)
807 disp_def.append(' }')
808 else:
809 (return_str, struct_array) = self._genStructMemberPrint(member, s, False, struct_array)
810 disp_def.append(return_str)
811 disp_def.append("}\n")
812 i_declared = False
813 # Basic print function to display struct members
814 disp_def.append("// Output all struct elements, each on their own line")
815 disp_def.append("void %s::display_txt()\n{" % self.get_class_name(s))
816 disp_def.append(' printf("%%*s%s struct contents at %%p:\\n", m_indent, "", (void*)m_origStructAddr);' % typedef_fwd_dict[s])
817 disp_def.append(' this->display_struct_members();')
818 disp_def.append("}\n")
819 # Advanced print function to display current struct and contents of any pointed-to structs
820 disp_def.append("// Output all struct elements, and for any structs pointed to, print complete contents")
821 disp_def.append("void %s::display_full_txt()\n{" % self.get_class_name(s))
822 disp_def.append(' printf("%%*s%s struct contents at %%p:\\n", m_indent, "", (void*)m_origStructAddr);' % typedef_fwd_dict[s])
823 disp_def.append(' this->display_struct_members();')
824 class_num = 0
825 # TODO : Need to handle arrays of structs here
826 for ms in struct_array:
827 swc_name = "class%s" % str(class_num)
828 if ms['array']:
829 if not i_declared:
830 disp_def.append(' uint32_t i;')
831 i_declared = True
832 disp_def.append(' for (i = 0; i<%s; i++) {' % ms['array_size'])
833 #disp_def.append(" if (m_struct.%s[i]) {" % (ms['name']))
834 disp_def.append(" %s %s(&(m_struct.%s[i]));" % (self.get_class_name(ms['type']), swc_name, ms['name']))
835 disp_def.append(" %s.set_indent(m_indent + 4);" % (swc_name))
836 disp_def.append(" %s.display_full_txt();" % (swc_name))
837 #disp_def.append(' }')
838 disp_def.append(' }')
839 elif 'pNext' == ms['name']:
840 # Need some code trickery here
841 # I'm thinking have a generated function that takes pNext ptr value
842 # then it checks sType and in large switch statement creates appropriate
843 # wrapper class type and then prints contents
844 disp_def.append(" if (m_struct.%s) {" % (ms['name']))
845 #disp_def.append(' printf("%*s This is where we would call dynamic print function\\n", m_indent, "");')
846 disp_def.append(' dynamic_display_full_txt(m_struct.%s, m_indent);' % (ms['name']))
847 disp_def.append(" }")
848 else:
849 if ms['ptr']:
850 disp_def.append(" if (m_struct.%s) {" % (ms['name']))
851 disp_def.append(" %s %s(m_struct.%s);" % (self.get_class_name(ms['type']), swc_name, ms['name']))
852 else:
853 disp_def.append(" if (&m_struct.%s) {" % (ms['name']))
854 disp_def.append(" %s %s(&m_struct.%s);" % (self.get_class_name(ms['type']), swc_name, ms['name']))
855 disp_def.append(" %s.set_indent(m_indent + 4);" % (swc_name))
856 disp_def.append(" %s.display_full_txt();\n }" % (swc_name))
857 class_num += 1
858 disp_def.append("}\n")
859 return "\n".join(disp_def)
860
861 def _generateStringHelperHeader(self):
862 header = []
863 header.append("//#includes, #defines, globals and such...\n")
864 for f in self.include_headers:
Tobin Ehlis3ed06942014-11-10 16:03:19 -0700865 if 'xgl_enum_string_helper' not in f:
Tobin Ehlisee33fa52014-10-22 15:13:53 -0600866 header.append("#include <%s>\n" % f)
Tobin Ehlis6f7029b2014-11-11 12:28:12 -0700867 header.append('#include "xgl_enum_string_helper.h"\n\n// Function Prototypes\n')
Tobin Ehlisee33fa52014-10-22 15:13:53 -0600868 header.append("char* dynamic_display(const XGL_VOID* pStruct, const char* prefix);\n")
869 return "".join(header)
Tobin Ehlis434db7c2015-01-10 12:42:41 -0700870
871 def _generateStringHelperHeaderCpp(self):
872 header = []
873 header.append("//#includes, #defines, globals and such...\n")
874 for f in self.include_headers:
875 if 'xgl_enum_string_helper' not in f:
876 header.append("#include <%s>\n" % f)
877 header.append('#include "xgl_enum_string_helper.h"\n')
878 header.append('using namespace std;\n\n// Function Prototypes\n')
879 header.append("string dynamic_display(const XGL_VOID* pStruct, const string prefix);\n")
880 return "".join(header)
881
Tobin Ehlis6cd06372014-12-17 17:44:50 -0700882 def _generateValidateHelperFunctions(self):
883 sh_funcs = []
884 # We do two passes, first pass just generates prototypes for all the functsions
885 for s in self.struct_dict:
886 sh_funcs.append('uint32_t %s(const %s* pStruct);' % (self._get_vh_func_name(s), typedef_fwd_dict[s]))
887 sh_funcs.append('\n')
888 for s in self.struct_dict:
889 sh_funcs.append('uint32_t %s(const %s* pStruct)\n{' % (self._get_vh_func_name(s), typedef_fwd_dict[s]))
890 for m in sorted(self.struct_dict[s]):
891 if is_type(self.struct_dict[s][m]['type'], 'enum'):
892 sh_funcs.append(' if (!validate_%s(pStruct->%s))\n return 0;' % (self.struct_dict[s][m]['type'], self.struct_dict[s][m]['name']))
Jon Ashburnaad29362015-01-12 15:46:51 -0700893 # TODO : Need a little refinement to this code to make sure type of struct matches expected input (ptr, const...)
Tobin Ehlise719e022014-12-18 09:29:58 -0700894 if is_type(self.struct_dict[s][m]['type'], 'struct'):
895 if (self.struct_dict[s][m]['ptr']):
896 sh_funcs.append(' if (!%s((const %s*)pStruct->%s))\n return 0;' % (self._get_vh_func_name(self.struct_dict[s][m]['type']), self.struct_dict[s][m]['type'], self.struct_dict[s][m]['name']))
897 else:
898 sh_funcs.append(' if (!%s((const %s*)&pStruct->%s))\n return 0;' % (self._get_vh_func_name(self.struct_dict[s][m]['type']), self.struct_dict[s][m]['type'], self.struct_dict[s][m]['name']))
Tobin Ehlis6cd06372014-12-17 17:44:50 -0700899 sh_funcs.append(" return 1;\n}")
900
901 return "\n".join(sh_funcs)
902
903 def _generateValidateHelperHeader(self):
904 header = []
905 header.append("//#includes, #defines, globals and such...\n")
906 for f in self.include_headers:
907 if 'xgl_enum_validate_helper' not in f:
908 header.append("#include <%s>\n" % f)
909 header.append('#include "xgl_enum_validate_helper.h"\n\n// Function Prototypes\n')
910 #header.append("char* dynamic_display(const XGL_VOID* pStruct, const char* prefix);\n")
911 return "".join(header)
912
Tobin Ehlisee33fa52014-10-22 15:13:53 -0600913 def _generateHeader(self):
914 header = []
915 header.append("//#includes, #defines, globals and such...\n")
916 for f in self.include_headers:
917 header.append("#include <%s>\n" % f)
918 return "".join(header)
919
920 # Declarations
921 def _generateConstructorDeclarations(self, s):
922 constructors = []
923 constructors.append(" %s();\n" % self.get_class_name(s))
924 constructors.append(" %s(%s* pInStruct);\n" % (self.get_class_name(s), typedef_fwd_dict[s]))
925 constructors.append(" %s(const %s* pInStruct);\n" % (self.get_class_name(s), typedef_fwd_dict[s]))
926 return "".join(constructors)
927
928 def _generateDestructorDeclarations(self, s):
929 return " virtual ~%s();\n" % self.get_class_name(s)
930
931 def _generateDisplayDeclarations(self, s):
932 return " void display_txt();\n void display_single_txt();\n void display_full_txt();\n"
933
934 def _generateGetSetDeclarations(self, s):
935 get_set = []
936 get_set.append(" void set_indent(uint32_t indent) { m_indent = indent; }\n")
937 for member in sorted(self.struct_dict[s]):
938 # TODO : Skipping array set/get funcs for now
939 if self.struct_dict[s][member]['array']:
940 continue
941 get_set.append(" %s get_%s() { return m_struct.%s; }\n" % (self.struct_dict[s][member]['full_type'], self.struct_dict[s][member]['name'], self.struct_dict[s][member]['name']))
942 if not self.struct_dict[s][member]['const']:
943 get_set.append(" void set_%s(%s inValue) { m_struct.%s = inValue; }\n" % (self.struct_dict[s][member]['name'], self.struct_dict[s][member]['full_type'], self.struct_dict[s][member]['name']))
944 return "".join(get_set)
945
946 def _generatePrivateMembers(self, s):
947 priv = []
948 priv.append("\nprivate:\n")
949 priv.append(" %s m_struct;\n" % typedef_fwd_dict[s])
950 priv.append(" const %s* m_origStructAddr;\n" % typedef_fwd_dict[s])
951 priv.append(" uint32_t m_indent;\n")
952 priv.append(" const char m_dummy_prefix;\n")
953 priv.append(" void display_struct_members();\n")
954 return "".join(priv)
955
956 def _generateClassDeclaration(self):
957 class_decl = []
958 for s in self.struct_dict:
959 class_decl.append("\n//class declaration")
960 class_decl.append("class %s\n{\npublic:" % self.get_class_name(s))
961 class_decl.append(self._generateConstructorDeclarations(s))
962 class_decl.append(self._generateDestructorDeclarations(s))
963 class_decl.append(self._generateDisplayDeclarations(s))
964 class_decl.append(self._generateGetSetDeclarations(s))
965 class_decl.append(self._generatePrivateMembers(s))
966 class_decl.append("};\n")
967 return "\n".join(class_decl)
968
969 def _generateFooter(self):
970 return "\n//any footer info for class\n"
971
972class EnumCodeGen:
Tobin Ehlisbe8dded2014-12-17 07:20:23 -0700973 def __init__(self, enum_type_dict=None, enum_val_dict=None, typedef_fwd_dict=None, in_file=None, out_sh_file=None, out_vh_file=None):
Tobin Ehlisee33fa52014-10-22 15:13:53 -0600974 self.et_dict = enum_type_dict
975 self.ev_dict = enum_val_dict
976 self.tf_dict = typedef_fwd_dict
977 self.in_file = in_file
Tobin Ehlisbe8dded2014-12-17 07:20:23 -0700978 self.out_sh_file = out_sh_file
979 self.eshfg = CommonFileGen(self.out_sh_file)
980 self.out_vh_file = out_vh_file
981 self.evhfg = CommonFileGen(self.out_vh_file)
Tobin Ehlisee33fa52014-10-22 15:13:53 -0600982
983 def generateStringHelper(self):
Tobin Ehlisbe8dded2014-12-17 07:20:23 -0700984 self.eshfg.setHeader(self._generateSHHeader())
985 self.eshfg.setBody(self._generateSHBody())
986 self.eshfg.generate()
987
988 def generateEnumValidate(self):
989 self.evhfg.setHeader(self._generateSHHeader())
Tobin Ehlis6cd06372014-12-17 17:44:50 -0700990 self.evhfg.setBody(self._generateVHBody())
Tobin Ehlisbe8dded2014-12-17 07:20:23 -0700991 self.evhfg.generate()
992
993 def _generateVHBody(self):
994 body = []
995 for bet in self.et_dict:
996 fet = self.tf_dict[bet]
997 body.append("static uint32_t validate_%s(%s input_value)\n{\n switch ((%s)input_value)\n {" % (fet, fet, fet))
998 for e in sorted(self.et_dict[bet]):
999 if (self.ev_dict[e]['unique']):
1000 body.append(' case %s:' % (e))
1001 body.append(' return 1;\n default:\n return 0;\n }\n}\n\n')
1002 return "\n".join(body)
1003
Tobin Ehlisee33fa52014-10-22 15:13:53 -06001004 def _generateSHBody(self):
1005 body = []
1006# with open(self.out_file, "a") as hf:
1007 # bet == base_enum_type, fet == final_enum_type
1008 for bet in self.et_dict:
1009 fet = self.tf_dict[bet]
Chia-I Wudf142a32014-12-16 11:02:06 +08001010 body.append("static inline const char* string_%s(%s input_value)\n{\n switch ((%s)input_value)\n {\n" % (fet, fet, fet))
Tobin Ehlisee33fa52014-10-22 15:13:53 -06001011 for e in sorted(self.et_dict[bet]):
1012 if (self.ev_dict[e]['unique']):
Tobin Ehlisbe8dded2014-12-17 07:20:23 -07001013 body.append(' case %s:\n return "%s";' % (e, e))
1014 body.append(' default:\n return "Unhandled %s";\n }\n}\n\n' % (fet))
Tobin Ehlisee33fa52014-10-22 15:13:53 -06001015 return "\n".join(body)
1016
1017 def _generateSHHeader(self):
1018 return "#pragma once\n\n#include <%s>\n\n" % self.in_file
1019
1020
1021class CMakeGen:
1022 def __init__(self, struct_wrapper=None, out_dir=None):
1023 self.sw = struct_wrapper
Tobin Ehlisa701ef02014-11-27 15:43:39 -07001024 self.include_headers = []
Tobin Ehlisee33fa52014-10-22 15:13:53 -06001025 self.add_lib_file_list = self.sw.get_file_list()
1026 self.out_dir = out_dir
1027 self.out_file = os.path.join(self.out_dir, "CMakeLists.txt")
1028 self.cmg = CommonFileGen(self.out_file)
1029
1030 def generate(self):
1031 self.cmg.setBody(self._generateBody())
1032 self.cmg.generate()
1033
1034 def _generateBody(self):
1035 body = []
1036 body.append("project(%s)" % os.path.basename(self.out_dir))
1037 body.append("cmake_minimum_required(VERSION 2.8)\n")
1038 body.append("add_library(${PROJECT_NAME} %s)\n" % " ".join(self.add_lib_file_list))
1039 body.append('set(COMPILE_FLAGS "-fpermissive")')
1040 body.append('set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${COMPILE_FLAGS}")\n')
1041 body.append("include_directories(${SRC_DIR}/thirdparty/${GEN_API}/inc/)\n")
1042 body.append("target_include_directories (%s PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})\n" % os.path.basename(self.out_dir))
1043 return "\n".join(body)
1044
1045class GraphVizGen:
Tobin Ehlisa701ef02014-11-27 15:43:39 -07001046 def __init__(self, struct_dict, prefix, out_dir):
1047 self.struct_dict = struct_dict
1048 self.api = prefix
1049 self.out_file = os.path.join(out_dir, self.api+"_struct_graphviz_helper.h")
Tobin Ehlisee33fa52014-10-22 15:13:53 -06001050 self.gvg = CommonFileGen(self.out_file)
Tobin Ehlisa701ef02014-11-27 15:43:39 -07001051
Tobin Ehlisee33fa52014-10-22 15:13:53 -06001052 def generate(self):
Tobin Ehlisa701ef02014-11-27 15:43:39 -07001053 self.gvg.setCopyright("//This is the copyright\n")
Tobin Ehlisee33fa52014-10-22 15:13:53 -06001054 self.gvg.setHeader(self._generateHeader())
1055 self.gvg.setBody(self._generateBody())
Tobin Ehlisa701ef02014-11-27 15:43:39 -07001056 #self.gvg.setFooter('}')
Tobin Ehlisee33fa52014-10-22 15:13:53 -06001057 self.gvg.generate()
Tobin Ehlisa701ef02014-11-27 15:43:39 -07001058
1059 def set_include_headers(self, include_headers):
1060 self.include_headers = include_headers
1061
Tobin Ehlisee33fa52014-10-22 15:13:53 -06001062 def _generateHeader(self):
Tobin Ehlisa701ef02014-11-27 15:43:39 -07001063 header = []
1064 header.append("//#includes, #defines, globals and such...\n")
1065 for f in self.include_headers:
1066 if 'xgl_enum_string_helper' not in f:
1067 header.append("#include <%s>\n" % f)
1068 #header.append('#include "xgl_enum_string_helper.h"\n\n// Function Prototypes\n')
1069 header.append("\nchar* dynamic_gv_display(const XGL_VOID* pStruct, const char* prefix);\n")
1070 return "".join(header)
1071
1072 def _get_gv_func_name(self, struct):
1073 return "%s_gv_print_%s" % (self.api, struct.lower().strip("_"))
1074
1075 # Return elements to create formatted string for given struct member
1076 def _get_struct_gv_print_formatted(self, struct_member, pre_var_name="", postfix = "\\n", struct_var_name="pStruct", struct_ptr=True, print_array=False, port_label=""):
1077 struct_op = "->"
1078 pre_var_name = '"%s "' % struct_member['full_type']
1079 if not struct_ptr:
1080 struct_op = "."
1081 member_name = struct_member['name']
1082 print_type = "p"
1083 cast_type = ""
1084 member_post = ""
1085 array_index = ""
1086 member_print_post = ""
1087 if struct_member['array'] and 'CHAR' in struct_member['type']: # just print char array as string
1088 print_type = "s"
1089 print_array = False
1090 elif struct_member['array'] and not print_array:
1091 # Just print base address of array when not full print_array
1092 cast_type = "(void*)"
1093 elif is_type(struct_member['type'], 'enum'):
Jon Ashburna0ddc902015-01-09 09:11:44 -07001094 if struct_member['ptr']:
1095 struct_var_name = "*" + struct_var_name
Tobin Ehlisa701ef02014-11-27 15:43:39 -07001096 cast_type = "string_%s" % struct_member['type']
1097 print_type = "s"
1098 elif is_type(struct_member['type'], 'struct'): # print struct address for now
1099 cast_type = "(void*)"
1100 if not struct_member['ptr']:
1101 cast_type = "(void*)&"
1102 elif 'BOOL' in struct_member['type']:
1103 print_type = "s"
1104 member_post = ' ? "TRUE" : "FALSE"'
1105 elif 'FLOAT' in struct_member['type']:
1106 print_type = "f"
1107 elif 'UINT64' in struct_member['type']:
1108 print_type = "lu"
1109 elif 'UINT8' in struct_member['type']:
1110 print_type = "hu"
Chia-I Wu54ed0792014-12-27 14:14:50 +08001111 elif '_SIZE' in struct_member['type']:
1112 print_type = "zu"
1113 elif True in [ui_str in struct_member['type'] for ui_str in ['UINT', '_FLAGS', '_SAMPLE_MASK']]:
Tobin Ehlisa701ef02014-11-27 15:43:39 -07001114 print_type = "u"
1115 elif 'INT' in struct_member['type']:
1116 print_type = "i"
1117 elif struct_member['ptr']:
1118 pass
1119 else:
1120 #print("Unhandled struct type: %s" % struct_member['type'])
1121 cast_type = "(void*)"
1122 if print_array and struct_member['array']:
1123 member_print_post = "[%u]"
1124 array_index = " i,"
1125 member_post = "[i]"
1126 print_out = "<TR><TD>%%s%s%s</TD><TD%s>%%%s%s</TD></TR>" % (member_name, member_print_post, port_label, print_type, postfix) # section of print that goes inside of quotes
1127 print_arg = ", %s,%s %s(%s%s%s)%s" % (pre_var_name, array_index, cast_type, struct_var_name, struct_op, member_name, member_post) # section of print passed to portion in quotes
1128 return (print_out, print_arg)
1129
Tobin Ehlisee33fa52014-10-22 15:13:53 -06001130 def _generateBody(self):
Tobin Ehlisa701ef02014-11-27 15:43:39 -07001131 gv_funcs = []
1132 array_func_list = [] # structs for which we'll generate an array version of their print function
1133 array_func_list.append('xgl_descriptor_slot_info')
1134 # For first pass, generate prototype
1135 for s in self.struct_dict:
1136 gv_funcs.append('char* %s(const %s* pStruct, const char* myNodeName);\n' % (self._get_gv_func_name(s), typedef_fwd_dict[s]))
1137 if s.lower().strip("_") in array_func_list:
1138 gv_funcs.append('char* %s_array(XGL_UINT count, const %s* pStruct, const char* myNodeName);\n' % (self._get_gv_func_name(s), typedef_fwd_dict[s]))
1139 gv_funcs.append('\n')
1140 for s in self.struct_dict:
1141 p_out = ""
1142 p_args = ""
1143 stp_list = [] # stp == "struct to print" a list of structs for this API call that should be printed as structs
1144 # the fields below are a super-hacky way for now to get port labels into GV output, TODO : Clean this up!
1145 pl_dict = {}
1146 struct_num = 0
1147 # This isn't great but this pre-pass counts chars in struct members and flags structs w/ pNext
1148 for m in sorted(self.struct_dict[s]):
1149 if 'pNext' == self.struct_dict[s][m]['name'] or is_type(self.struct_dict[s][m]['type'], 'struct'):
1150 stp_list.append(self.struct_dict[s][m])
1151 if 'pNext' == self.struct_dict[s][m]['name']:
1152 pl_dict[m] = ' PORT=\\"pNext\\"'
1153 else:
1154 pl_dict[m] = ' PORT=\\"struct%i\\"' % struct_num
1155 struct_num += 1
1156 gv_funcs.append('char* %s(const %s* pStruct, const char* myNodeName)\n{\n char* str;\n' % (self._get_gv_func_name(s), typedef_fwd_dict[s]))
1157 num_stps = len(stp_list);
1158 total_strlen_str = ''
1159 if 0 != num_stps:
1160 gv_funcs.append(" char* tmpStr;\n")
1161 gv_funcs.append(" char nodeName[100];\n")
Tobin Ehlisa701ef02014-11-27 15:43:39 -07001162 gv_funcs.append(' char* stp_strs[%i];\n' % num_stps)
1163 for index in range(num_stps):
1164 if (stp_list[index]['ptr']):
1165 if 'pDescriptorInfo' == stp_list[index]['name']:
1166 gv_funcs.append(' if (pStruct->pDescriptorInfo && (0 != pStruct->descriptorCount)) {\n')
1167 else:
1168 gv_funcs.append(' if (pStruct->%s) {\n' % stp_list[index]['name'])
1169 if 'pNext' == stp_list[index]['name']:
1170 gv_funcs.append(' sprintf(nodeName, "pNext_%p", (void*)pStruct->pNext);\n')
1171 gv_funcs.append(' tmpStr = dynamic_gv_display((XGL_VOID*)pStruct->pNext, nodeName);\n')
1172 gv_funcs.append(' stp_strs[%i] = (char*)malloc(256+strlen(tmpStr)+strlen(nodeName)+strlen(myNodeName));\n' % index)
1173 gv_funcs.append(' sprintf(stp_strs[%i], "%%s\\n\\"%%s\\":pNext -> \\"%%s\\" [];\\n", tmpStr, myNodeName, nodeName);\n' % index)
1174 gv_funcs.append(' free(tmpStr);\n')
1175 else:
1176 gv_funcs.append(' sprintf(nodeName, "%s_%%p", (void*)pStruct->%s);\n' % (stp_list[index]['name'], stp_list[index]['name']))
1177 if 'pDescriptorInfo' == stp_list[index]['name']:
1178 gv_funcs.append(' tmpStr = %s_array(pStruct->descriptorCount, pStruct->%s, nodeName);\n' % (self._get_gv_func_name(stp_list[index]['type']), stp_list[index]['name']))
1179 else:
1180 gv_funcs.append(' tmpStr = %s(pStruct->%s, nodeName);\n' % (self._get_gv_func_name(stp_list[index]['type']), stp_list[index]['name']))
1181 gv_funcs.append(' stp_strs[%i] = (char*)malloc(256+strlen(tmpStr)+strlen(nodeName)+strlen(myNodeName));\n' % (index))
1182 gv_funcs.append(' sprintf(stp_strs[%i], "%%s\\n\\"%%s\\":struct%i -> \\"%%s\\" [];\\n", tmpStr, myNodeName, nodeName);\n' % (index, index))
1183 gv_funcs.append(' }\n')
Chia-I Wu81f46672014-12-16 00:36:58 +08001184 gv_funcs.append(" else\n stp_strs[%i] = \"\";\n" % (index))
Tobin Ehlisa701ef02014-11-27 15:43:39 -07001185 elif stp_list[index]['array']: # TODO : For now just printing first element of array
1186 gv_funcs.append(' sprintf(nodeName, "%s_%%p", (void*)&pStruct->%s[0]);\n' % (stp_list[index]['name'], stp_list[index]['name']))
1187 gv_funcs.append(' tmpStr = %s(&pStruct->%s[0], nodeName);\n' % (self._get_gv_func_name(stp_list[index]['type']), stp_list[index]['name']))
1188 gv_funcs.append(' stp_strs[%i] = (char*)malloc(256+strlen(tmpStr)+strlen(nodeName)+strlen(myNodeName));\n' % (index))
1189 gv_funcs.append(' sprintf(stp_strs[%i], "%%s\\n\\"%%s\\":struct%i -> \\"%%s\\" [];\\n", tmpStr, myNodeName, nodeName);\n' % (index, index))
1190 else:
1191 gv_funcs.append(' sprintf(nodeName, "%s_%%p", (void*)&pStruct->%s);\n' % (stp_list[index]['name'], stp_list[index]['name']))
1192 gv_funcs.append(' tmpStr = %s(&pStruct->%s, nodeName);\n' % (self._get_gv_func_name(stp_list[index]['type']), stp_list[index]['name']))
1193 gv_funcs.append(' stp_strs[%i] = (char*)malloc(256+strlen(tmpStr)+strlen(nodeName)+strlen(myNodeName));\n' % (index))
1194 gv_funcs.append(' sprintf(stp_strs[%i], "%%s\\n\\"%%s\\":struct%i -> \\"%%s\\" [];\\n", tmpStr, myNodeName, nodeName);\n' % (index, index))
1195 total_strlen_str += 'strlen(stp_strs[%i]) + ' % index
1196 gv_funcs.append(' str = (char*)malloc(%ssizeof(char)*2048);\n' % (total_strlen_str))
1197 gv_funcs.append(' sprintf(str, "\\"%s\\" [\\nlabel = <<TABLE BORDER=\\"0\\" CELLBORDER=\\"1\\" CELLSPACING=\\"0\\"><TR><TD COLSPAN=\\"2\\">%s (%p)</TD></TR>')
1198 p_args = ", myNodeName, myNodeName, pStruct"
1199 for m in sorted(self.struct_dict[s]):
1200 plabel = ""
1201 if m in pl_dict:
1202 plabel = pl_dict[m]
1203 (p_out1, p_args1) = self._get_struct_gv_print_formatted(self.struct_dict[s][m], port_label=plabel)
1204 p_out += p_out1
1205 p_args += p_args1
1206 p_out += '</TABLE>>\\n];\\n\\n"'
1207 p_args += ");\n"
1208 gv_funcs.append(p_out)
1209 gv_funcs.append(p_args)
1210 if 0 != num_stps:
1211 gv_funcs.append(' for (int32_t stp_index = %i; stp_index >= 0; stp_index--) {\n' % (num_stps-1))
1212 gv_funcs.append(' if (0 < strlen(stp_strs[stp_index])) {\n')
1213 gv_funcs.append(' strncat(str, stp_strs[stp_index], strlen(stp_strs[stp_index]));\n')
1214 gv_funcs.append(' free(stp_strs[stp_index]);\n')
1215 gv_funcs.append(' }\n')
1216 gv_funcs.append(' }\n')
1217 gv_funcs.append(" return str;\n}\n")
1218 if s.lower().strip("_") in array_func_list:
1219 gv_funcs.append('char* %s_array(XGL_UINT count, const %s* pStruct, const char* myNodeName)\n{\n char* str;\n char tmpStr[1024];\n' % (self._get_gv_func_name(s), typedef_fwd_dict[s]))
1220 gv_funcs.append(' str = (char*)malloc(sizeof(char)*1024*count);\n')
1221 gv_funcs.append(' sprintf(str, "\\"%s\\" [\\nlabel = <<TABLE BORDER=\\"0\\" CELLBORDER=\\"1\\" CELLSPACING=\\"0\\"><TR><TD COLSPAN=\\"3\\">%s (%p)</TD></TR>", myNodeName, myNodeName, pStruct);\n')
1222 gv_funcs.append(' for (uint32_t i=0; i < count; i++) {\n')
1223 gv_funcs.append(' sprintf(tmpStr, "');
1224 p_args = ""
1225 p_out = ""
1226 for m in sorted(self.struct_dict[s]):
1227 if 2 == m: # TODO : Hard-coded hack to skip last element of union for xgl_descriptor_slot_info struct
1228 continue
1229 plabel = ""
1230 (p_out1, p_args1) = self._get_struct_gv_print_formatted(self.struct_dict[s][m], port_label=plabel)
1231 if 0 == m: # Add array index notation at end of first row (TODO : ROWSPAN# should be dynamic based on number of elements, but hard-coding for now)
1232 p_out1 = '%s<TD ROWSPAN=\\"2\\" PORT=\\"slot%%u\\">%%u</TD></TR>' % (p_out1[:-5])
1233 p_args1 += ', i, i'
1234 p_out += p_out1
1235 p_args += p_args1
1236 p_out += '"'
1237 p_args += ");\n"
1238 p_args = p_args.replace('->', '[i].')
1239 gv_funcs.append(p_out);
1240 gv_funcs.append(p_args);
1241 gv_funcs.append(' strncat(str, tmpStr, strlen(tmpStr));\n')
1242 gv_funcs.append(' }\n')
1243 gv_funcs.append(' strncat(str, "</TABLE>>\\n];\\n\\n", 20);\n')
1244 # TODO : Another hard-coded hack. Tie these slots to "magical" DS0_MEMORY slots that should appear separately
1245 gv_funcs.append(' for (uint32_t i=0; i < count; i++) {\n')
Tobin Ehlisf1c468a2014-12-09 17:00:33 -07001246 gv_funcs.append(' if (XGL_SLOT_UNUSED != pStruct[i].slotObjectType) {\n')
1247 gv_funcs.append(' sprintf(tmpStr, "\\"%s\\":slot%u -> \\"DS0_MEMORY\\":slot%u [];\\n", myNodeName, i, i);\n')
1248 gv_funcs.append(' strncat(str, tmpStr, strlen(tmpStr));\n')
1249 gv_funcs.append(' }\n')
Tobin Ehlisa701ef02014-11-27 15:43:39 -07001250 gv_funcs.append(' }\n')
1251 gv_funcs.append(' return str;\n}\n')
1252 # Add function to dynamically print out unknown struct
1253 gv_funcs.append("char* dynamic_gv_display(const XGL_VOID* pStruct, const char* nodeName)\n{\n")
1254 gv_funcs.append(" // Cast to APP_INFO ptr initially just to pull sType off struct\n")
1255 gv_funcs.append(" XGL_STRUCTURE_TYPE sType = ((XGL_APPLICATION_INFO*)pStruct)->sType;\n")
1256 gv_funcs.append(" switch (sType)\n {\n")
1257 for e in enum_type_dict:
1258 if "_STRUCTURE_TYPE" in e:
1259 for v in sorted(enum_type_dict[e]):
1260 struct_name = v.replace("_STRUCTURE_TYPE", "")
1261 print_func_name = self._get_gv_func_name(struct_name)
1262 # TODO : Hand-coded fixes for some exceptions
1263 if 'XGL_PIPELINE_CB_STATE_CREATE_INFO' in struct_name:
1264 struct_name = 'XGL_PIPELINE_CB_STATE'
1265 elif 'XGL_SEMAPHORE_CREATE_INFO' in struct_name:
1266 struct_name = 'XGL_QUEUE_SEMAPHORE_CREATE_INFO'
1267 print_func_name = self._get_gv_func_name(struct_name)
1268 elif 'XGL_SEMAPHORE_OPEN_INFO' in struct_name:
1269 struct_name = 'XGL_QUEUE_SEMAPHORE_OPEN_INFO'
1270 print_func_name = self._get_gv_func_name(struct_name)
1271 gv_funcs.append(' case %s:\n' % (v))
1272 gv_funcs.append(' return %s((%s*)pStruct, nodeName);\n' % (print_func_name, struct_name))
1273 #gv_funcs.append(' }\n')
1274 #gv_funcs.append(' break;\n')
Chia-I Wu84d7f5c2014-12-16 00:43:20 +08001275 gv_funcs.append(" default:\n")
1276 gv_funcs.append(" return NULL;\n")
Tobin Ehlisa701ef02014-11-27 15:43:39 -07001277 gv_funcs.append(" }\n")
1278 gv_funcs.append("}")
1279 return "".join(gv_funcs)
1280
1281
1282
1283
1284
1285# def _generateHeader(self):
1286# hdr = []
1287# hdr.append('digraph g {\ngraph [\nrankdir = "LR"\n];')
1288# hdr.append('node [\nfontsize = "16"\nshape = "plaintext"\n];')
1289# hdr.append('edge [\n];\n')
1290# return "\n".join(hdr)
1291#
1292# def _generateBody(self):
1293# body = []
1294# for s in self.struc_dict:
1295# field_num = 1
1296# body.append('"%s" [\nlabel = <<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0"> <TR><TD COLSPAN="2" PORT="f0">%s</TD></TR>' % (s, typedef_fwd_dict[s]))
1297# for m in sorted(self.struc_dict[s]):
1298# body.append('<TR><TD PORT="f%i">%s</TD><TD PORT="f%i">%s</TD></TR>' % (field_num, self.struc_dict[s][m]['full_type'], field_num+1, self.struc_dict[s][m]['name']))
1299# field_num += 2
1300# body.append('</TABLE>>\n];\n')
1301# return "".join(body)
Tobin Ehlisee33fa52014-10-22 15:13:53 -06001302
1303def main(argv=None):
1304 opts = handle_args()
1305 # Parse input file and fill out global dicts
1306 hfp = HeaderFileParser(opts.input_file)
1307 hfp.parse()
1308 # TODO : Don't want these to be global, see note at top about wrapper classes
1309 global enum_val_dict
1310 global enum_type_dict
1311 global struct_dict
1312 global typedef_fwd_dict
1313 global typedef_rev_dict
1314 global types_dict
1315 enum_val_dict = hfp.get_enum_val_dict()
1316 enum_type_dict = hfp.get_enum_type_dict()
1317 struct_dict = hfp.get_struct_dict()
Tobin Ehlis6f7029b2014-11-11 12:28:12 -07001318 # TODO : Would like to validate struct data here to verify that all of the bools for struct members are correct at this point
Tobin Ehlisee33fa52014-10-22 15:13:53 -06001319 typedef_fwd_dict = hfp.get_typedef_fwd_dict()
1320 typedef_rev_dict = hfp.get_typedef_rev_dict()
1321 types_dict = hfp.get_types_dict()
1322 #print(enum_val_dict)
1323 #print(typedef_dict)
1324 #print(struct_dict)
1325 if (opts.abs_out_dir is not None):
Tobin Ehlisbe8dded2014-12-17 07:20:23 -07001326 enum_sh_filename = os.path.join(opts.abs_out_dir, os.path.basename(opts.input_file).strip(".h")+"_enum_string_helper.h")
Tobin Ehlisee33fa52014-10-22 15:13:53 -06001327 else:
Tobin Ehlisbe8dded2014-12-17 07:20:23 -07001328 enum_sh_filename = os.path.join(os.getcwd(), opts.rel_out_dir, os.path.basename(opts.input_file).strip(".h")+"_enum_string_helper.h")
1329 enum_sh_filename = os.path.abspath(enum_sh_filename)
1330 if not os.path.exists(os.path.dirname(enum_sh_filename)):
1331 print("Creating output dir %s" % os.path.dirname(enum_sh_filename))
1332 os.mkdir(os.path.dirname(enum_sh_filename))
Tobin Ehlisee33fa52014-10-22 15:13:53 -06001333 if opts.gen_enum_string_helper:
Tobin Ehlisbe8dded2014-12-17 07:20:23 -07001334 print("Generating enum string helper to %s" % enum_sh_filename)
1335 enum_vh_filename = os.path.join(os.path.dirname(enum_sh_filename), os.path.basename(opts.input_file).strip(".h")+"_enum_validate_helper.h")
1336 print("Generating enum validate helper to %s" % enum_vh_filename)
1337 eg = EnumCodeGen(enum_type_dict, enum_val_dict, typedef_fwd_dict, os.path.basename(opts.input_file), enum_sh_filename, enum_vh_filename)
Tobin Ehlisee33fa52014-10-22 15:13:53 -06001338 eg.generateStringHelper()
Tobin Ehlisbe8dded2014-12-17 07:20:23 -07001339 eg.generateEnumValidate()
Tobin Ehlisee33fa52014-10-22 15:13:53 -06001340 #for struct in struct_dict:
1341 #print(struct)
1342 if opts.gen_struct_wrappers:
Tobin Ehlisbe8dded2014-12-17 07:20:23 -07001343 sw = StructWrapperGen(struct_dict, os.path.basename(opts.input_file).strip(".h"), os.path.dirname(enum_sh_filename))
Tobin Ehlisee33fa52014-10-22 15:13:53 -06001344 #print(sw.get_class_name(struct))
Tobin Ehlisbe8dded2014-12-17 07:20:23 -07001345 sw.set_include_headers([os.path.basename(opts.input_file),os.path.basename(enum_sh_filename),"stdint.h","stdio.h","stdlib.h"])
Tobin Ehlisee33fa52014-10-22 15:13:53 -06001346 print("Generating struct wrapper header to %s" % sw.header_filename)
1347 sw.generateHeader()
1348 print("Generating struct wrapper class to %s" % sw.class_filename)
1349 sw.generateBody()
1350 sw.generateStringHelper()
Tobin Ehlis6cd06372014-12-17 17:44:50 -07001351 sw.generateValidateHelper()
Tobin Ehlis07fe9ab2014-11-25 17:43:26 -07001352 # Generate a 2nd helper file that excludes addrs
1353 sw.set_no_addr(True)
1354 sw.generateStringHelper()
Tobin Ehlis434db7c2015-01-10 12:42:41 -07001355 sw.set_no_addr(False)
1356 sw.set_include_headers([os.path.basename(opts.input_file),os.path.basename(enum_sh_filename),"stdint.h","stdio.h","stdlib.h","iostream","sstream","string"])
1357 sw.generateStringHelperCpp()
1358 sw.set_no_addr(True)
1359 sw.generateStringHelperCpp()
Tobin Ehlisee33fa52014-10-22 15:13:53 -06001360 if opts.gen_cmake:
Tobin Ehlisbe8dded2014-12-17 07:20:23 -07001361 cmg = CMakeGen(sw, os.path.dirname(enum_sh_filename))
Tobin Ehlisee33fa52014-10-22 15:13:53 -06001362 cmg.generate()
1363 if opts.gen_graphviz:
Tobin Ehlisbe8dded2014-12-17 07:20:23 -07001364 gv = GraphVizGen(struct_dict, os.path.basename(opts.input_file).strip(".h"), os.path.dirname(enum_sh_filename))
1365 gv.set_include_headers([os.path.basename(opts.input_file),os.path.basename(enum_sh_filename),"stdint.h","stdio.h","stdlib.h"])
Tobin Ehlisee33fa52014-10-22 15:13:53 -06001366 gv.generate()
1367 print("DONE!")
1368 #print(typedef_rev_dict)
1369 #print(types_dict)
1370 #recreate_structs()
1371
1372if __name__ == "__main__":
1373 sys.exit(main())