From: Tobin Ehlis Date: Thu, 18 Dec 2014 00:44:50 +0000 (-0700) Subject: layers: Initial ParamChecker layer X-Git-Tag: submit/tizen/20181227.054638~6248 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=ad0170c34eef4e8ee453cc0e0b3facace2e73bf5;p=platform%2Fupstream%2FVulkan-Tools.git layers: Initial ParamChecker layer ParamChecker layer is generated and currently only checks that ENUM input to functions or ENUMS as part of input structs have valid values. Conflicts: layers/CMakeLists.txt --- diff --git a/layers/CMakeLists.txt b/layers/CMakeLists.txt index 86fc0311..618e4917 100644 --- a/layers/CMakeLists.txt +++ b/layers/CMakeLists.txt @@ -2,15 +2,15 @@ cmake_minimum_required (VERSION 2.8.11) macro(run_xgl_helper subcmd) add_custom_command(OUTPUT ${ARGN} - COMMAND ${PROJECT_SOURCE_DIR}/xgl-helper.py --${subcmd} ${PROJECT_SOURCE_DIR}/include/xgl.h --abs_out_dir ${CMAKE_CURRENT_BINARY_DIR} - DEPENDS ${PROJECT_SOURCE_DIR}/xgl-helper.py ${PROJECT_SOURCE_DIR}/include/xgl.h + COMMAND ${PROJECT_SOURCE_DIR}/xgl_helper.py --${subcmd} ${PROJECT_SOURCE_DIR}/include/xgl.h --abs_out_dir ${CMAKE_CURRENT_BINARY_DIR} + DEPENDS ${PROJECT_SOURCE_DIR}/xgl_helper.py ${PROJECT_SOURCE_DIR}/include/xgl.h ) endmacro() macro(run_xgl_layer_generate subcmd output) add_custom_command(OUTPUT ${output} - COMMAND ${PROJECT_SOURCE_DIR}/xgl-layer-generate.py ${subcmd} > ${output} - DEPENDS ${PROJECT_SOURCE_DIR}/xgl-layer-generate.py ${PROJECT_SOURCE_DIR}/xgl.py + COMMAND ${PROJECT_SOURCE_DIR}/xgl-layer-generate.py ${subcmd} ${PROJECT_SOURCE_DIR}/include/xgl.h > ${output} + DEPENDS ${PROJECT_SOURCE_DIR}/xgl-layer-generate.py ${PROJECT_SOURCE_DIR}/include/xgl.h ${PROJECT_SOURCE_DIR}/xgl.py ) endmacro() @@ -67,6 +67,7 @@ run_xgl_layer_generate(ApiDumpNoAddr api_dump_no_addr.c) run_xgl_layer_generate(ApiDumpCpp api_dump.cpp) run_xgl_layer_generate(ApiDumpNoAddrCpp api_dump_no_addr.cpp) run_xgl_layer_generate(ObjectTracker object_track.c) +run_xgl_layer_generate(ParamChecker param_checker.c) add_xgl_layer(Basic basic.cpp) add_xgl_layer(Multi multi.cpp) @@ -80,3 +81,4 @@ add_xgl_layer(APIDumpNoAddr api_dump_no_addr.c) add_xgl_layer(APIDumpCpp api_dump.cpp) add_xgl_layer(APIDumpNoAddrCpp api_dump_no_addr.cpp) add_xgl_layer(ObjectTracker object_track.c) +add_xgl_layer(ParamChecker param_checker.c) diff --git a/xgl-helper.py b/xgl-helper.py deleted file mode 100755 index 67cada7e..00000000 --- a/xgl-helper.py +++ /dev/null @@ -1,1325 +0,0 @@ -#!/usr/bin/env python3 -# -# XGL -# -# Copyright (C) 2014 LunarG, Inc. -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the "Software"), -# to deal in the Software without restriction, including without limitation -# the rights to use, copy, modify, merge, publish, distribute, sublicense, -# and/or sell copies of the Software, and to permit persons to whom the -# Software is furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -# DEALINGS IN THE SOFTWARE. -import argparse -import os -import sys - -# code_gen.py overview -# This script generates code based on input headers -# Initially it's intended to support Mantle and XGL headers and -# generate wrappers functions that can be used to display -# structs in a human-readable txt format, as well as utility functions -# to print enum values as strings - - -def handle_args(): - parser = argparse.ArgumentParser(description='Perform analysis of vogl trace.') - parser.add_argument('input_file', help='The input header file from which code will be generated.') - 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.') - parser.add_argument('--abs_out_dir', required=False, default=None, help='Absolute path to write output files. Will be created if needed.') - 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.') - parser.add_argument('--gen_struct_wrappers', required=False, action='store_true', default=False, help='Enable generation of struct wrapper classes.') - parser.add_argument('--gen_cmake', required=False, action='store_true', default=False, help='Enable generation of cmake file for generated code.') - parser.add_argument('--gen_graphviz', required=False, action='store_true', default=False, help='Enable generation of graphviz dot file.') - #parser.add_argument('--test', action='store_true', default=False, help='Run simple test.') - return parser.parse_args() - -# TODO : Ideally these data structs would be opaque to user and could be wrapped -# in their own class(es) to make them friendly for data look-up -# Dicts for Data storage -# enum_val_dict[value_name] = dict keys are the string enum value names for all enums -# |-------->['type'] = the type of enum class into which the value falls -# |-------->['val'] = the value assigned to this particular value_name -# '-------->['unique'] = bool designating if this enum 'val' is unique within this enum 'type' -enum_val_dict = {} -# enum_type_dict['type'] = the type or class of of enum -# '----->['val_name1', 'val_name2'...] = each type references a list of val_names within this type -enum_type_dict = {} -# struct_dict['struct_basename'] = the base (non-typedef'd) name of the struct -# |->[] = members are stored via their integer placement in the struct -# | |->['name'] = string name of this struct member -# ... |->['full_type'] = complete type qualifier for this member -# |->['type'] = base type for this member -# |->['ptr'] = bool indicating if this member is ptr -# |->['const'] = bool indicating if this member is const -# |->['struct'] = bool indicating if this member is a struct type -# |->['array'] = bool indicating if this member is an array -# '->['array_size'] = int indicating size of array members (0 by default) -struct_dict = {} -# typedef_fwd_dict stores mapping from orig_type_name -> new_type_name -typedef_fwd_dict = {} -# typedef_rev_dict stores mapping from new_type_name -> orig_type_name -typedef_rev_dict = {} # store new_name -> orig_name mapping -# types_dict['id_name'] = identifier name will map to it's type -# '---->'type' = currently either 'struct' or 'enum' -types_dict = {} # store orig_name -> type mapping - - -# Class that parses header file and generates data structures that can -# Then be used for other tasks -class HeaderFileParser: - def __init__(self, header_file=None): - self.header_file = header_file - # store header data in various formats, see above for more info - self.enum_val_dict = {} - self.enum_type_dict = {} - self.struct_dict = {} - self.typedef_fwd_dict = {} - self.typedef_rev_dict = {} - self.types_dict = {} - - def setHeaderFile(self, header_file): - self.header_file = header_file - - def get_enum_val_dict(self): - return self.enum_val_dict - - def get_enum_type_dict(self): - return self.enum_type_dict - - def get_struct_dict(self): - return self.struct_dict - - def get_typedef_fwd_dict(self): - return self.typedef_fwd_dict - - def get_typedef_rev_dict(self): - return self.typedef_rev_dict - - def get_types_dict(self): - return self.types_dict - - # Parse header file into data structures - def parse(self): - # parse through the file, identifying different sections - parse_enum = False - parse_struct = False - member_num = 0 - # TODO : Comment parsing is very fragile but handles 2 known files - block_comment = False - with open(self.header_file) as f: - for line in f: - if block_comment: - if '*/' in line: - block_comment = False - continue - if '/*' in line: - block_comment = True - elif 0 == len(line.split()): - #print("Skipping empty line") - continue - elif line.split()[0].strip().startswith("//"): - #print("Skipping commented line %s" % line) - continue - elif 'typedef enum' in line: - (ty_txt, en_txt, base_type) = line.strip().split(None, 2) - #print("Found ENUM type %s" % base_type) - parse_enum = True - default_enum_val = 0 - self.types_dict[base_type] = 'enum' - elif 'typedef struct' in line: - (ty_txt, st_txt, base_type) = line.strip().split(None, 2) - #print("Found STRUCT type: %s" % base_type) - parse_struct = True - self.types_dict[base_type] = 'struct' - elif 'typedef union' in line: - (ty_txt, st_txt, base_type) = line.strip().split(None, 2) - #print("Found UNION type: %s" % base_type) - parse_struct = True - self.types_dict[base_type] = 'struct' - elif '}' in line and (parse_enum or parse_struct): - if len(line.split()) > 1: # deals with embedded union in one struct - parse_enum = False - parse_struct = False - member_num = 0 - # TODO : Can pull target of typedef here for remapping - (cur_char, targ_type) = line.strip().split(None, 1) - self.typedef_fwd_dict[base_type] = targ_type.strip(';') - self.typedef_rev_dict[targ_type.strip(';')] = base_type - elif parse_enum: - if 'XGL_MAX_ENUM' not in line and '{' not in line: - self._add_enum(line, base_type, default_enum_val) - default_enum_val += 1 - elif parse_struct: - if ';' in line: - self._add_struct(line, base_type, member_num) - member_num = member_num + 1 - #elif '(' in line: - #print("Function: %s" % line) - - # populate enum dicts based on enum lines - def _add_enum(self, line_txt, enum_type, def_enum_val): - #print("Parsing enum line %s" % line_txt) - if '=' in line_txt: - (enum_name, eq_char, enum_val) = line_txt.split(None, 2) - else: - enum_name = line_txt.split(',')[0] - enum_val = str(def_enum_val) - self.enum_val_dict[enum_name] = {} - self.enum_val_dict[enum_name]['type'] = enum_type - # strip comma and comment, then extra split in case of no comma w/ comments - enum_val = enum_val.strip().split(',', 1)[0] - self.enum_val_dict[enum_name]['val'] = enum_val.split()[0] - # account for negative values surrounded by parens - self.enum_val_dict[enum_name]['val'] = self.enum_val_dict[enum_name]['val'].strip(')').replace('-(', '-') - # Try to cast to int to determine if enum value is unique - try: - #print("ENUM val:", self.enum_val_dict[enum_name]['val']) - int(self.enum_val_dict[enum_name]['val'], 0) - self.enum_val_dict[enum_name]['unique'] = True - #print("ENUM has num value") - except ValueError: - self.enum_val_dict[enum_name]['unique'] = False - #print("ENUM is not a number value") - # Update enum_type_dict as well - if not enum_type in self.enum_type_dict: - self.enum_type_dict[enum_type] = [] - self.enum_type_dict[enum_type].append(enum_name) - - # populate struct dicts based on struct lines - # TODO : Handle ":" bitfield, "**" ptr->ptr and "const type*const*" - def _add_struct(self, line_txt, struct_type, num): - #print("Parsing struct line %s" % line_txt) - if not struct_type in self.struct_dict: - self.struct_dict[struct_type] = {} - members = line_txt.strip().split(';', 1)[0] # first strip semicolon & comments - # TODO : Handle bitfields more correctly - members = members.strip().split(':', 1)[0] # strip bitfield element - (member_type, member_name) = members.rsplit(None, 1) - self.struct_dict[struct_type][num] = {} - self.struct_dict[struct_type][num]['full_type'] = member_type - if '*' in member_type: - self.struct_dict[struct_type][num]['ptr'] = True - member_type = member_type.strip('*') - else: - self.struct_dict[struct_type][num]['ptr'] = False - if 'const' in member_type: - self.struct_dict[struct_type][num]['const'] = True - member_type = member_type.strip('const').strip() - else: - self.struct_dict[struct_type][num]['const'] = False - # TODO : There is a bug here where it seems that at the time we do this check, - # the data is not in the types or typedef_rev_dict, so we never pass this if check - if is_type(member_type, 'struct'): - self.struct_dict[struct_type][num]['struct'] = True - else: - self.struct_dict[struct_type][num]['struct'] = False - self.struct_dict[struct_type][num]['type'] = member_type - if '[' in member_name: - (member_name, array_size) = member_name.split('[', 1) - self.struct_dict[struct_type][num]['array'] = True - self.struct_dict[struct_type][num]['array_size'] = array_size.strip(']') - else: - self.struct_dict[struct_type][num]['array'] = False - self.struct_dict[struct_type][num]['array_size'] = 0 - self.struct_dict[struct_type][num]['name'] = member_name - -# check if given identifier if of specified type_to_check -def is_type(identifier, type_to_check): - if identifier in types_dict and type_to_check == types_dict[identifier]: - return True - if identifier in typedef_rev_dict: - new_id = typedef_rev_dict[identifier] - if new_id in types_dict and type_to_check == types_dict[new_id]: - return True - return False - -# This is a validation function to verify that we can reproduce the original structs -def recreate_structs(): - for struct_name in struct_dict: - sys.stdout.write("typedef struct %s\n{\n" % struct_name) - for mem_num in sorted(struct_dict[struct_name]): - sys.stdout.write(" ") - if struct_dict[struct_name][mem_num]['const']: - sys.stdout.write("const ") - #if struct_dict[struct_name][mem_num]['struct']: - # sys.stdout.write("struct ") - sys.stdout.write (struct_dict[struct_name][mem_num]['type']) - if struct_dict[struct_name][mem_num]['ptr']: - sys.stdout.write("*") - sys.stdout.write(" ") - sys.stdout.write(struct_dict[struct_name][mem_num]['name']) - if struct_dict[struct_name][mem_num]['array']: - sys.stdout.write("[") - sys.stdout.write(struct_dict[struct_name][mem_num]['array_size']) - sys.stdout.write("]") - sys.stdout.write(";\n") - sys.stdout.write("} ") - sys.stdout.write(typedef_fwd_dict[struct_name]) - sys.stdout.write(";\n\n") - -# class for writing common file elements -# Here's how this class lays out a file: -# COPYRIGHT -# HEADER -# BODY -# FOOTER -# -# For each of these sections, there's a "set*" function -# The class as a whole has a generate function which will write each section in order -class CommonFileGen: - def __init__(self, filename=None, copyright_txt="", header_txt="", body_txt="", footer_txt=""): - self.filename = filename - self.contents = {'copyright': copyright_txt, 'header': header_txt, 'body': body_txt, 'footer': footer_txt} - # TODO : Set a default copyright & footer at least - - def setFilename(self, filename): - self.filename = filename - - def setCopyright(self, c): - self.contents['copyright'] = c - - def setHeader(self, h): - self.contents['header'] = h - - def setBody(self, b): - self.contents['body'] = b - - def setFooter(self, f): - self.contents['footer'] = f - - def generate(self): - #print("Generate to file %s" % self.filename) - with open(self.filename, "w") as f: - f.write(self.contents['copyright']) - f.write(self.contents['header']) - f.write(self.contents['body']) - f.write(self.contents['footer']) - -# class for writing a wrapper class for structures -# The wrapper class wraps the structs and includes utility functions for -# setting/getting member values and displaying the struct data in various formats -class StructWrapperGen: - def __init__(self, in_struct_dict, prefix, out_dir): - self.struct_dict = in_struct_dict - self.include_headers = [] - self.api = prefix - self.header_filename = os.path.join(out_dir, self.api+"_struct_wrappers.h") - self.class_filename = os.path.join(out_dir, self.api+"_struct_wrappers.cpp") - self.string_helper_filename = os.path.join(out_dir, self.api+"_struct_string_helper.h") - self.string_helper_no_addr_filename = os.path.join(out_dir, self.api+"_struct_string_helper_no_addr.h") - self.string_helper_cpp_filename = os.path.join(out_dir, self.api+"_struct_string_helper_cpp.h") - self.string_helper_no_addr_cpp_filename = os.path.join(out_dir, self.api+"_struct_string_helper_no_addr_cpp.h") - self.no_addr = False - self.hfg = CommonFileGen(self.header_filename) - self.cfg = CommonFileGen(self.class_filename) - self.shg = CommonFileGen(self.string_helper_filename) - self.shcppg = CommonFileGen(self.string_helper_cpp_filename) - #print(self.header_filename) - self.header_txt = "" - self.definition_txt = "" - - def set_include_headers(self, include_headers): - self.include_headers = include_headers - - def set_no_addr(self, no_addr): - self.no_addr = no_addr - if self.no_addr: - self.shg = CommonFileGen(self.string_helper_no_addr_filename) - self.shcppg = CommonFileGen(self.string_helper_no_addr_cpp_filename) - else: - self.shg = CommonFileGen(self.string_helper_filename) - self.shcppg = CommonFileGen(self.string_helper_cpp_filename) - - # Return class name for given struct name - def get_class_name(self, struct_name): - class_name = struct_name.strip('_').lower() + "_struct_wrapper" - return class_name - - def get_file_list(self): - return [os.path.basename(self.header_filename), os.path.basename(self.class_filename), os.path.basename(self.string_helper_filename)] - - # Generate class header file - def generateHeader(self): - self.hfg.setCopyright(self._generateCopyright()) - self.hfg.setHeader(self._generateHeader()) - self.hfg.setBody(self._generateClassDeclaration()) - self.hfg.setFooter(self._generateFooter()) - self.hfg.generate() - - # Generate class definition - def generateBody(self): - self.cfg.setCopyright(self._generateCopyright()) - self.cfg.setHeader(self._generateCppHeader()) - self.cfg.setBody(self._generateClassDefinition()) - self.cfg.setFooter(self._generateFooter()) - self.cfg.generate() - - # Generate c-style .h file that contains functions for printing structs - def generateStringHelper(self): - print("Generating struct string helper") - self.shg.setCopyright(self._generateCopyright()) - self.shg.setHeader(self._generateStringHelperHeader()) - self.shg.setBody(self._generateStringHelperFunctions()) - self.shg.generate() - - # Generate cpp-style .h file that contains functions for printing structs - def generateStringHelperCpp(self): - print("Generating struct string helper cpp") - self.shcppg.setCopyright(self._generateCopyright()) - self.shcppg.setHeader(self._generateStringHelperHeaderCpp()) - self.shcppg.setBody(self._generateStringHelperFunctionsCpp()) - self.shcppg.generate() - - def _generateCopyright(self): - return "//This is the copyright\n" - - def _generateCppHeader(self): - header = [] - header.append("//#includes, #defines, globals and such...\n") - header.append("#include \n#include <%s>\n#include <%s_enum_string_helper.h>\n" % (os.path.basename(self.header_filename), self.api)) - return "".join(header) - - def _generateClassDefinition(self): - class_def = [] - if 'xgl' == self.api: # Mantle doesn't have pNext to worry about - class_def.append(self._generateDynamicPrintFunctions()) - for s in self.struct_dict: - class_def.append("\n// %s class definition" % self.get_class_name(s)) - class_def.append(self._generateConstructorDefinitions(s)) - class_def.append(self._generateDestructorDefinitions(s)) - class_def.append(self._generateDisplayDefinitions(s)) - return "\n".join(class_def) - - def _generateConstructorDefinitions(self, s): - con_defs = [] - 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))) - # TODO : This is a shallow copy of ptrs - 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])) - 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])) - return "\n".join(con_defs) - - def _generateDestructorDefinitions(self, s): - return "%s::~%s() {}" % (self.get_class_name(s), self.get_class_name(s)) - - def _generateDynamicPrintFunctions(self): - dp_funcs = [] - 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") - dp_funcs.append(" XGL_STRUCTURE_TYPE sType = ((XGL_APPLICATION_INFO*)pStruct)->sType;\n") - dp_funcs.append(" switch (sType)\n {") - for e in enum_type_dict: - class_num = 0 - if "_STRUCTURE_TYPE" in e: - for v in sorted(enum_type_dict[e]): - struct_name = v.replace("_STRUCTURE_TYPE", "") - class_name = self.get_class_name(struct_name) - # TODO : Hand-coded fixes for some exceptions - if 'XGL_PIPELINE_CB_STATE_CREATE_INFO' in struct_name: - struct_name = 'XGL_PIPELINE_CB_STATE' - elif 'XGL_SEMAPHORE_CREATE_INFO' in struct_name: - struct_name = 'XGL_QUEUE_SEMAPHORE_CREATE_INFO' - class_name = self.get_class_name(struct_name) - elif 'XGL_SEMAPHORE_OPEN_INFO' in struct_name: - struct_name = 'XGL_QUEUE_SEMAPHORE_OPEN_INFO' - class_name = self.get_class_name(struct_name) - instance_name = "swc%i" % class_num - dp_funcs.append(" case %s:\n {" % (v)) - dp_funcs.append(" %s %s((%s*)pStruct);" % (class_name, instance_name, struct_name)) - dp_funcs.append(" %s.set_indent(indent);" % (instance_name)) - dp_funcs.append(" %s.display_full_txt();" % (instance_name)) - dp_funcs.append(" }") - dp_funcs.append(" break;") - class_num += 1 - dp_funcs.append(" }") - dp_funcs.append("}\n") - return "\n".join(dp_funcs) - - def _get_sh_func_name(self, struct): - return "%s_print_%s" % (self.api, struct.lower().strip("_")) - - # Return elements to create formatted string for given struct member - def _get_struct_print_formatted(self, struct_member, pre_var_name="prefix", postfix = "\\n", struct_var_name="pStruct", struct_ptr=True, print_array=False): - struct_op = "->" - if not struct_ptr: - struct_op = "." - member_name = struct_member['name'] - print_type = "p" - cast_type = "" - member_post = "" - array_index = "" - member_print_post = "" - if struct_member['array'] and 'CHAR' in struct_member['type']: # just print char array as string - print_type = "s" - print_array = False - elif struct_member['array'] and not print_array: - # Just print base address of array when not full print_array - cast_type = "(void*)" - elif is_type(struct_member['type'], 'enum'): - cast_type = "string_%s" % struct_member['type'] - if struct_member['ptr']: - struct_var_name = "*" + struct_var_name - print_type = "s" - elif is_type(struct_member['type'], 'struct'): # print struct address for now - cast_type = "(void*)" - if not struct_member['ptr']: - cast_type = "(void*)&" - elif 'BOOL' in struct_member['type']: - print_type = "s" - member_post = ' ? "TRUE" : "FALSE"' - elif 'FLOAT' in struct_member['type']: - print_type = "f" - elif 'UINT64' in struct_member['type']: - print_type = "lu" - elif 'UINT8' in struct_member['type']: - print_type = "hu" - elif '_SIZE' in struct_member['type']: - print_type = "zu" - elif True in [ui_str in struct_member['type'] for ui_str in ['UINT', '_FLAGS', '_SAMPLE_MASK']]: - print_type = "u" - elif 'INT' in struct_member['type']: - print_type = "i" - elif struct_member['ptr']: - pass - else: - #print("Unhandled struct type: %s" % struct_member['type']) - cast_type = "(void*)" - if print_array and struct_member['array']: - member_print_post = "[%u]" - array_index = " i," - member_post = "[i]" - print_out = "%%s%s%s = %%%s%s" % (member_name, member_print_post, print_type, postfix) # section of print that goes inside of quotes - 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 - if self.no_addr and "p" == print_type: - print_out = "%%s%s%s = addr\\n" % (member_name, member_print_post) # section of print that goes inside of quotes - print_arg = ", %s" % (pre_var_name) - return (print_out, print_arg) - - def _generateStringHelperFunctions(self): - sh_funcs = [] - # We do two passes, first pass just generates prototypes for all the functsions - for s in self.struct_dict: - sh_funcs.append('char* %s(const %s* pStruct, const char* prefix);\n' % (self._get_sh_func_name(s), typedef_fwd_dict[s])) - sh_funcs.append('\n') - for s in self.struct_dict: - p_out = "" - p_args = "" - stp_list = [] # stp == "struct to print" a list of structs for this API call that should be printed as structs - # This isn't great but this pre-pass counts chars in struct members and flags structs w/ pNext - for m in self.struct_dict[s]: - if 'pNext' == self.struct_dict[s][m]['name'] or is_type(self.struct_dict[s][m]['type'], 'struct'): - stp_list.append(self.struct_dict[s][m]) - 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])) - sh_funcs.append(" size_t len;\n") - num_stps = len(stp_list); - total_strlen_str = '' - if 0 != num_stps: - sh_funcs.append(" char* tmpStr;\n") - sh_funcs.append(' char* extra_indent = (char*)malloc(strlen(prefix) + 3);\n') - sh_funcs.append(' strcpy(extra_indent, " ");\n') - sh_funcs.append(' strncat(extra_indent, prefix, strlen(prefix));\n') - sh_funcs.append(' char* stp_strs[%i];\n' % num_stps) - for index in range(num_stps): - if (stp_list[index]['ptr']): - sh_funcs.append(' if (pStruct->%s) {\n' % stp_list[index]['name']) - if 'pNext' == stp_list[index]['name']: - sh_funcs.append(' tmpStr = dynamic_display((XGL_VOID*)pStruct->pNext, prefix);\n') - sh_funcs.append(' len = 256+strlen(tmpStr);\n') - sh_funcs.append(' stp_strs[%i] = (char*)malloc(len);\n' % index) - if self.no_addr: - sh_funcs.append(' snprintf(stp_strs[%i], len, " %%spNext (addr)\\n%%s", prefix, tmpStr);\n' % index) - else: - sh_funcs.append(' snprintf(stp_strs[%i], len, " %%spNext (%%p)\\n%%s", prefix, (void*)pStruct->pNext, tmpStr);\n' % index) - sh_funcs.append(' free(tmpStr);\n') - else: - sh_funcs.append(' tmpStr = %s(pStruct->%s, extra_indent);\n' % (self._get_sh_func_name(stp_list[index]['type']), stp_list[index]['name'])) - sh_funcs.append(' len = 256+strlen(tmpStr)+strlen(prefix);\n') - sh_funcs.append(' stp_strs[%i] = (char*)malloc(len);\n' % (index)) - if self.no_addr: - sh_funcs.append(' snprintf(stp_strs[%i], len, " %%s%s (addr)\\n%%s", prefix, tmpStr);\n' % (index, stp_list[index]['name'])) - else: - 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'])) - sh_funcs.append(' }\n') - sh_funcs.append(" else\n stp_strs[%i] = \"\";\n" % (index)) - elif stp_list[index]['array']: # TODO : For now just printing first element of array - sh_funcs.append(' tmpStr = %s(&pStruct->%s[0], extra_indent);\n' % (self._get_sh_func_name(stp_list[index]['type']), stp_list[index]['name'])) - sh_funcs.append(' len = 256+strlen(tmpStr);\n') - sh_funcs.append(' stp_strs[%i] = (char*)malloc(len);\n' % (index)) - if self.no_addr: - sh_funcs.append(' snprintf(stp_strs[%i], len, " %%s%s[0] (addr)\\n%%s", prefix, tmpStr);\n' % (index, stp_list[index]['name'])) - else: - 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'])) - else: - sh_funcs.append(' tmpStr = %s(&pStruct->%s, extra_indent);\n' % (self._get_sh_func_name(stp_list[index]['type']), stp_list[index]['name'])) - sh_funcs.append(' len = 256+strlen(tmpStr);\n') - sh_funcs.append(' stp_strs[%i] = (char*)malloc(len);\n' % (index)) - if self.no_addr: - sh_funcs.append(' snprintf(stp_strs[%i], len, " %%s%s (addr)\\n%%s", prefix, tmpStr);\n' % (index, stp_list[index]['name'])) - else: - 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'])) - total_strlen_str += 'strlen(stp_strs[%i]) + ' % index - sh_funcs.append(' len = %ssizeof(char)*1024;\n' % (total_strlen_str)) - sh_funcs.append(' str = (char*)malloc(len);\n') - sh_funcs.append(' snprintf(str, len, "') - for m in sorted(self.struct_dict[s]): - (p_out1, p_args1) = self._get_struct_print_formatted(self.struct_dict[s][m]) - p_out += p_out1 - p_args += p_args1 - p_out += '"' - p_args += ");\n" - sh_funcs.append(p_out) - sh_funcs.append(p_args) - if 0 != num_stps: - sh_funcs.append(' for (int32_t stp_index = %i; stp_index >= 0; stp_index--) {\n' % (num_stps-1)) - sh_funcs.append(' if (0 < strlen(stp_strs[stp_index])) {\n') - sh_funcs.append(' strncat(str, stp_strs[stp_index], strlen(stp_strs[stp_index]));\n') - sh_funcs.append(' free(stp_strs[stp_index]);\n') - sh_funcs.append(' }\n') - sh_funcs.append(' }\n') - sh_funcs.append(" return str;\n}\n") - # Add function to dynamically print out unknown struct - sh_funcs.append("char* dynamic_display(const XGL_VOID* pStruct, const char* prefix)\n{\n") - sh_funcs.append(" // Cast to APP_INFO ptr initially just to pull sType off struct\n") - sh_funcs.append(" XGL_STRUCTURE_TYPE sType = ((XGL_APPLICATION_INFO*)pStruct)->sType;\n") - sh_funcs.append(' char indent[100];\n strcpy(indent, " ");\n strcat(indent, prefix);\n') - sh_funcs.append(" switch (sType)\n {\n") - for e in enum_type_dict: - if "_STRUCTURE_TYPE" in e: - for v in sorted(enum_type_dict[e]): - struct_name = v.replace("_STRUCTURE_TYPE", "") - print_func_name = self._get_sh_func_name(struct_name) - # TODO : Hand-coded fixes for some exceptions - if 'XGL_PIPELINE_CB_STATE_CREATE_INFO' in struct_name: - struct_name = 'XGL_PIPELINE_CB_STATE' - elif 'XGL_SEMAPHORE_CREATE_INFO' in struct_name: - struct_name = 'XGL_QUEUE_SEMAPHORE_CREATE_INFO' - print_func_name = self._get_sh_func_name(struct_name) - elif 'XGL_SEMAPHORE_OPEN_INFO' in struct_name: - struct_name = 'XGL_QUEUE_SEMAPHORE_OPEN_INFO' - print_func_name = self._get_sh_func_name(struct_name) - sh_funcs.append(' case %s:\n {\n' % (v)) - sh_funcs.append(' return %s((%s*)pStruct, indent);\n' % (print_func_name, struct_name)) - sh_funcs.append(' }\n') - sh_funcs.append(' break;\n') - sh_funcs.append(" default:\n") - sh_funcs.append(" return NULL;\n") - sh_funcs.append(" }\n") - sh_funcs.append("}") - return "".join(sh_funcs) - - def _generateStringHelperFunctionsCpp(self): - # declare str & tmp str - # declare array of stringstreams for every struct ptr in current struct - # declare array of stringstreams for every non-string element in current struct - # For every struct ptr, it non-Null, then set it's string, else set to NULL str - # For every non-string element, set it's string stream - # create and return final string - sh_funcs = [] - # First generate prototypes for every struct - for s in self.struct_dict: - sh_funcs.append('string %s(const %s* pStruct, const string prefix);' % (self._get_sh_func_name(s), typedef_fwd_dict[s])) - sh_funcs.append('\n') - for s in self.struct_dict: - num_non_enum_elems = [is_type(self.struct_dict[s][elem]['type'], 'enum') for elem in self.struct_dict[s]].count(False) - stp_list = [] # stp == "struct to print" a list of structs for this API call that should be printed as structs - # This isn't great but this pre-pass counts chars in struct members and flags structs w/ pNext - for m in self.struct_dict[s]: - if 'pNext' == self.struct_dict[s][m]['name'] or is_type(self.struct_dict[s][m]['type'], 'struct'): - stp_list.append(self.struct_dict[s][m]) - sh_funcs.append('string %s(const %s* pStruct, const string prefix)\n{' % (self._get_sh_func_name(s), typedef_fwd_dict[s])) - sh_funcs.append(' string final_str;') - sh_funcs.append(' string tmp_str;') - sh_funcs.append(' string extra_indent = " " + prefix;') - sh_funcs.append(' stringstream ss[%u];' % num_non_enum_elems) - num_stps = len(stp_list) - # First generate code for any embedded structs - if 0 < num_stps: - sh_funcs.append(' string stp_strs[%u];' % num_stps) - idx_ss_decl = False # Make sure to only decl this once - for index in range(num_stps): - addr_char = '&' - if stp_list[index]['ptr']: - addr_char = '' - if (stp_list[index]['ptr']): - sh_funcs.append(' if (pStruct->%s) {' % stp_list[index]['name']) - if 'pNext' == stp_list[index]['name']: - sh_funcs.append(' tmp_str = dynamic_display((XGL_VOID*)pStruct->pNext, prefix);') - else: - sh_funcs.append(' tmp_str = %s(pStruct->%s, extra_indent);' % (self._get_sh_func_name(stp_list[index]['type']), stp_list[index]['name'])) - sh_funcs.append(' ss[%u] << %spStruct->%s;' % (index, addr_char, stp_list[index]['name'])) - if self.no_addr: - sh_funcs.append(' stp_strs[%u] = " " + prefix + "%s (addr)\\n" + tmp_str;' % (index, stp_list[index]['name'])) - else: - sh_funcs.append(' stp_strs[%u] = " " + prefix + "%s (" + ss[%u].str() + ")\\n" + tmp_str;' % (index, stp_list[index]['name'], index)) - sh_funcs.append(' ss[%u].str("");' % (index)) - sh_funcs.append(' }') - sh_funcs.append(' else') - sh_funcs.append(' stp_strs[%u] = "";' % index) - elif (stp_list[index]['array']): - sh_funcs.append(' stp_strs[%u] = "";' % index) - if not idx_ss_decl: - sh_funcs.append(' stringstream index_ss;') - idx_ss_decl = True - sh_funcs.append(' for (uint32_t i = 0; i < %s; i++) {' % stp_list[index]['array_size']) - sh_funcs.append(' index_ss.str("");') - sh_funcs.append(' index_ss << i;') - sh_funcs.append(' ss[%u] << %spStruct->%s[i];' % (index, addr_char, stp_list[index]['name'])) - sh_funcs.append(' tmp_str = %s(&pStruct->%s[i], extra_indent);' % (self._get_sh_func_name(stp_list[index]['type']), stp_list[index]['name'])) - if self.no_addr: - sh_funcs.append(' stp_strs[%u] += " " + prefix + "%s[" + index_ss.str() + "] (addr)\\n" + tmp_str;' % (index, stp_list[index]['name'])) - else: - sh_funcs.append(' stp_strs[%u] += " " + prefix + "%s[" + index_ss.str() + "] (" + ss[%u].str() + ")\\n" + tmp_str;' % (index, stp_list[index]['name'], index)) - sh_funcs.append(' ss[%u].str("");' % index) - sh_funcs.append(' }') - else: - sh_funcs.append(' tmp_str = %s(&pStruct->%s, extra_indent);' % (self._get_sh_func_name(stp_list[index]['type']), stp_list[index]['name'])) - sh_funcs.append(' ss[%u] << %spStruct->%s;' % (index, addr_char, stp_list[index]['name'])) - if self.no_addr: - sh_funcs.append(' stp_strs[%u] = " " + prefix + "%s (addr)\\n" + tmp_str;' % (index, stp_list[index]['name'])) - else: - sh_funcs.append(' stp_strs[%u] = " " + prefix + "%s (" + ss[%u].str() + ")\\n" + tmp_str;' % (index, stp_list[index]['name'], index)) - sh_funcs.append(' ss[%u].str("");' % index) - # Now print non-enum data members - index = 0 - final_str = '' - for m in sorted(self.struct_dict[s]): - if not is_type(self.struct_dict[s][m]['type'], 'enum'): - if is_type(self.struct_dict[s][m]['type'], 'struct') and not self.struct_dict[s][m]['ptr']: - if self.no_addr: - sh_funcs.append(' ss[%u].str("addr");' % (index)) - else: - sh_funcs.append(' ss[%u] << &pStruct->%s;' % (index, self.struct_dict[s][m]['name'])) - elif 'BOOL' in self.struct_dict[s][m]['type']: - sh_funcs.append(' ss[%u].str(pStruct->%s ? "TRUE" : "FALSE");' % (index, self.struct_dict[s][m]['name'])) - elif 'UINT8' in self.struct_dict[s][m]['type']: - sh_funcs.append(' ss[%u] << (uint32_t)pStruct->%s;' % (index, self.struct_dict[s][m]['name'])) - else: - (po, pa) = self._get_struct_print_formatted(self.struct_dict[s][m]) - if "addr" in po or self.struct_dict[s][m]['ptr']: - sh_funcs.append(' ss[%u].str("addr");' % (index)) - else: - sh_funcs.append(' ss[%u] << pStruct->%s;' % (index, self.struct_dict[s][m]['name'])) - value_print = 'ss[%u].str()' % index - index += 1 - else: - value_print = 'string_%s(pStruct->%s)' % (self.struct_dict[s][m]['type'], self.struct_dict[s][m]['name']) - final_str += ' + prefix + "%s = " + %s + "\\n"' % (self.struct_dict[s][m]['name'], value_print) - final_str = final_str[3:] # strip off the initial ' + ' - if 0 != num_stps: - final_str += " + %s" % " + ".join(['stp_strs[%u]' % n for n in reversed(range(num_stps))]) - sh_funcs.append(' final_str = %s;' % final_str) - sh_funcs.append(' return final_str;\n}') - # Add function to dynamically print out unknown struct - sh_funcs.append("string dynamic_display(const XGL_VOID* pStruct, const string prefix)\n{") - sh_funcs.append(" // Cast to APP_INFO ptr initially just to pull sType off struct") - sh_funcs.append(" XGL_STRUCTURE_TYPE sType = ((XGL_APPLICATION_INFO*)pStruct)->sType;") - sh_funcs.append(' string indent = " ";') - sh_funcs.append(' indent += prefix;') - sh_funcs.append(" switch (sType)\n {") - for e in enum_type_dict: - if "_STRUCTURE_TYPE" in e: - for v in sorted(enum_type_dict[e]): - struct_name = v.replace("_STRUCTURE_TYPE", "") - print_func_name = self._get_sh_func_name(struct_name) - # TODO : Hand-coded fixes for some exceptions - if 'XGL_PIPELINE_CB_STATE_CREATE_INFO' in struct_name: - struct_name = 'XGL_PIPELINE_CB_STATE' - elif 'XGL_SEMAPHORE_CREATE_INFO' in struct_name: - struct_name = 'XGL_QUEUE_SEMAPHORE_CREATE_INFO' - print_func_name = self._get_sh_func_name(struct_name) - elif 'XGL_SEMAPHORE_OPEN_INFO' in struct_name: - struct_name = 'XGL_QUEUE_SEMAPHORE_OPEN_INFO' - print_func_name = self._get_sh_func_name(struct_name) - sh_funcs.append(' case %s:\n {' % (v)) - sh_funcs.append(' return %s((%s*)pStruct, indent);' % (print_func_name, struct_name)) - sh_funcs.append(' }') - sh_funcs.append(' break;') - sh_funcs.append(" default:") - sh_funcs.append(" return NULL;") - sh_funcs.append(" }") - sh_funcs.append("}") - return "\n".join(sh_funcs) - - def _genStructMemberPrint(self, member, s, array, struct_array): - (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) - extra_indent = "" - if array: - extra_indent = " " - if is_type(self.struct_dict[s][member]['type'], 'struct'): # print struct address for now - struct_array.insert(0, self.struct_dict[s][member]) - elif self.struct_dict[s][member]['ptr']: - # Special case for VOID* named "pNext" - if "VOID" in self.struct_dict[s][member]['type'] and "pNext" == self.struct_dict[s][member]['name']: - struct_array.insert(0, self.struct_dict[s][member]) - return (' %sprintf("%%*s %s", m_indent, ""%s);' % (extra_indent, p_out, p_arg), struct_array) - - def _generateDisplayDefinitions(self, s): - disp_def = [] - struct_array = [] - # Single-line struct print function - disp_def.append("// Output 'structname = struct_address' on a single line") - disp_def.append("void %s::display_single_txt()\n{" % self.get_class_name(s)) - disp_def.append(' printf(" %%*s%s = %%p", m_indent, "", (void*)m_origStructAddr);' % typedef_fwd_dict[s]) - disp_def.append("}\n") - # Private helper function to print struct members - disp_def.append("// Private helper function that displays the members of the wrapped struct") - disp_def.append("void %s::display_struct_members()\n{" % self.get_class_name(s)) - i_declared = False - for member in sorted(self.struct_dict[s]): - # TODO : Need to display each member based on its type - # TODO : Need to handle pNext which are structs, but of XGL_VOID* type - # Can grab struct type off of header of struct pointed to - # TODO : Handle Arrays - if self.struct_dict[s][member]['array']: - # Create for loop to print each element of array - if not i_declared: - disp_def.append(' uint32_t i;') - i_declared = True - disp_def.append(' for (i = 0; i<%s; i++) {' % self.struct_dict[s][member]['array_size']) - (return_str, struct_array) = self._genStructMemberPrint(member, s, True, struct_array) - disp_def.append(return_str) - disp_def.append(' }') - else: - (return_str, struct_array) = self._genStructMemberPrint(member, s, False, struct_array) - disp_def.append(return_str) - disp_def.append("}\n") - i_declared = False - # Basic print function to display struct members - disp_def.append("// Output all struct elements, each on their own line") - disp_def.append("void %s::display_txt()\n{" % self.get_class_name(s)) - disp_def.append(' printf("%%*s%s struct contents at %%p:\\n", m_indent, "", (void*)m_origStructAddr);' % typedef_fwd_dict[s]) - disp_def.append(' this->display_struct_members();') - disp_def.append("}\n") - # Advanced print function to display current struct and contents of any pointed-to structs - disp_def.append("// Output all struct elements, and for any structs pointed to, print complete contents") - disp_def.append("void %s::display_full_txt()\n{" % self.get_class_name(s)) - disp_def.append(' printf("%%*s%s struct contents at %%p:\\n", m_indent, "", (void*)m_origStructAddr);' % typedef_fwd_dict[s]) - disp_def.append(' this->display_struct_members();') - class_num = 0 - # TODO : Need to handle arrays of structs here - for ms in struct_array: - swc_name = "class%s" % str(class_num) - if ms['array']: - if not i_declared: - disp_def.append(' uint32_t i;') - i_declared = True - disp_def.append(' for (i = 0; i<%s; i++) {' % ms['array_size']) - #disp_def.append(" if (m_struct.%s[i]) {" % (ms['name'])) - disp_def.append(" %s %s(&(m_struct.%s[i]));" % (self.get_class_name(ms['type']), swc_name, ms['name'])) - disp_def.append(" %s.set_indent(m_indent + 4);" % (swc_name)) - disp_def.append(" %s.display_full_txt();" % (swc_name)) - #disp_def.append(' }') - disp_def.append(' }') - elif 'pNext' == ms['name']: - # Need some code trickery here - # I'm thinking have a generated function that takes pNext ptr value - # then it checks sType and in large switch statement creates appropriate - # wrapper class type and then prints contents - disp_def.append(" if (m_struct.%s) {" % (ms['name'])) - #disp_def.append(' printf("%*s This is where we would call dynamic print function\\n", m_indent, "");') - disp_def.append(' dynamic_display_full_txt(m_struct.%s, m_indent);' % (ms['name'])) - disp_def.append(" }") - else: - if ms['ptr']: - disp_def.append(" if (m_struct.%s) {" % (ms['name'])) - disp_def.append(" %s %s(m_struct.%s);" % (self.get_class_name(ms['type']), swc_name, ms['name'])) - else: - disp_def.append(" if (&m_struct.%s) {" % (ms['name'])) - disp_def.append(" %s %s(&m_struct.%s);" % (self.get_class_name(ms['type']), swc_name, ms['name'])) - disp_def.append(" %s.set_indent(m_indent + 4);" % (swc_name)) - disp_def.append(" %s.display_full_txt();\n }" % (swc_name)) - class_num += 1 - disp_def.append("}\n") - return "\n".join(disp_def) - - def _generateStringHelperHeader(self): - header = [] - header.append("//#includes, #defines, globals and such...\n") - for f in self.include_headers: - if 'xgl_enum_string_helper' not in f: - header.append("#include <%s>\n" % f) - header.append('#include "xgl_enum_string_helper.h"\n\n// Function Prototypes\n') - header.append("char* dynamic_display(const XGL_VOID* pStruct, const char* prefix);\n") - return "".join(header) - - def _generateStringHelperHeaderCpp(self): - header = [] - header.append("//#includes, #defines, globals and such...\n") - for f in self.include_headers: - if 'xgl_enum_string_helper' not in f: - header.append("#include <%s>\n" % f) - header.append('#include "xgl_enum_string_helper.h"\n') - header.append('using namespace std;\n\n// Function Prototypes\n') - header.append("string dynamic_display(const XGL_VOID* pStruct, const string prefix);\n") - return "".join(header) - - def _generateHeader(self): - header = [] - header.append("//#includes, #defines, globals and such...\n") - for f in self.include_headers: - header.append("#include <%s>\n" % f) - return "".join(header) - - # Declarations - def _generateConstructorDeclarations(self, s): - constructors = [] - constructors.append(" %s();\n" % self.get_class_name(s)) - constructors.append(" %s(%s* pInStruct);\n" % (self.get_class_name(s), typedef_fwd_dict[s])) - constructors.append(" %s(const %s* pInStruct);\n" % (self.get_class_name(s), typedef_fwd_dict[s])) - return "".join(constructors) - - def _generateDestructorDeclarations(self, s): - return " virtual ~%s();\n" % self.get_class_name(s) - - def _generateDisplayDeclarations(self, s): - return " void display_txt();\n void display_single_txt();\n void display_full_txt();\n" - - def _generateGetSetDeclarations(self, s): - get_set = [] - get_set.append(" void set_indent(uint32_t indent) { m_indent = indent; }\n") - for member in sorted(self.struct_dict[s]): - # TODO : Skipping array set/get funcs for now - if self.struct_dict[s][member]['array']: - continue - 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'])) - if not self.struct_dict[s][member]['const']: - 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'])) - return "".join(get_set) - - def _generatePrivateMembers(self, s): - priv = [] - priv.append("\nprivate:\n") - priv.append(" %s m_struct;\n" % typedef_fwd_dict[s]) - priv.append(" const %s* m_origStructAddr;\n" % typedef_fwd_dict[s]) - priv.append(" uint32_t m_indent;\n") - priv.append(" const char m_dummy_prefix;\n") - priv.append(" void display_struct_members();\n") - return "".join(priv) - - def _generateClassDeclaration(self): - class_decl = [] - for s in self.struct_dict: - class_decl.append("\n//class declaration") - class_decl.append("class %s\n{\npublic:" % self.get_class_name(s)) - class_decl.append(self._generateConstructorDeclarations(s)) - class_decl.append(self._generateDestructorDeclarations(s)) - class_decl.append(self._generateDisplayDeclarations(s)) - class_decl.append(self._generateGetSetDeclarations(s)) - class_decl.append(self._generatePrivateMembers(s)) - class_decl.append("};\n") - return "\n".join(class_decl) - - def _generateFooter(self): - return "\n//any footer info for class\n" - -class EnumCodeGen: - 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): - self.et_dict = enum_type_dict - self.ev_dict = enum_val_dict - self.tf_dict = typedef_fwd_dict - self.in_file = in_file - self.out_sh_file = out_sh_file - self.eshfg = CommonFileGen(self.out_sh_file) - self.out_vh_file = out_vh_file - self.evhfg = CommonFileGen(self.out_vh_file) - - def generateStringHelper(self): - self.eshfg.setHeader(self._generateSHHeader()) - self.eshfg.setBody(self._generateSHBody()) - self.eshfg.generate() - - def generateEnumValidate(self): - self.evhfg.setHeader(self._generateSHHeader()) - self.evhfg.setHeader(self._generateVHBody()) - self.evhfg.generate() - - def _generateVHBody(self): - body = [] - for bet in self.et_dict: - fet = self.tf_dict[bet] - body.append("static uint32_t validate_%s(%s input_value)\n{\n switch ((%s)input_value)\n {" % (fet, fet, fet)) - for e in sorted(self.et_dict[bet]): - if (self.ev_dict[e]['unique']): - body.append(' case %s:' % (e)) - body.append(' return 1;\n default:\n return 0;\n }\n}\n\n') - return "\n".join(body) - - def _generateSHBody(self): - body = [] -# with open(self.out_file, "a") as hf: - # bet == base_enum_type, fet == final_enum_type - for bet in self.et_dict: - fet = self.tf_dict[bet] - body.append("static inline const char* string_%s(%s input_value)\n{\n switch ((%s)input_value)\n {\n" % (fet, fet, fet)) - for e in sorted(self.et_dict[bet]): - if (self.ev_dict[e]['unique']): - body.append(' case %s:\n return "%s";' % (e, e)) - body.append(' default:\n return "Unhandled %s";\n }\n}\n\n' % (fet)) - return "\n".join(body) - - def _generateSHHeader(self): - return "#pragma once\n\n#include <%s>\n\n" % self.in_file - - -class CMakeGen: - def __init__(self, struct_wrapper=None, out_dir=None): - self.sw = struct_wrapper - self.include_headers = [] - self.add_lib_file_list = self.sw.get_file_list() - self.out_dir = out_dir - self.out_file = os.path.join(self.out_dir, "CMakeLists.txt") - self.cmg = CommonFileGen(self.out_file) - - def generate(self): - self.cmg.setBody(self._generateBody()) - self.cmg.generate() - - def _generateBody(self): - body = [] - body.append("project(%s)" % os.path.basename(self.out_dir)) - body.append("cmake_minimum_required(VERSION 2.8)\n") - body.append("add_library(${PROJECT_NAME} %s)\n" % " ".join(self.add_lib_file_list)) - body.append('set(COMPILE_FLAGS "-fpermissive")') - body.append('set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${COMPILE_FLAGS}")\n') - body.append("include_directories(${SRC_DIR}/thirdparty/${GEN_API}/inc/)\n") - body.append("target_include_directories (%s PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})\n" % os.path.basename(self.out_dir)) - return "\n".join(body) - -class GraphVizGen: - def __init__(self, struct_dict, prefix, out_dir): - self.struct_dict = struct_dict - self.api = prefix - self.out_file = os.path.join(out_dir, self.api+"_struct_graphviz_helper.h") - self.gvg = CommonFileGen(self.out_file) - - def generate(self): - self.gvg.setCopyright("//This is the copyright\n") - self.gvg.setHeader(self._generateHeader()) - self.gvg.setBody(self._generateBody()) - #self.gvg.setFooter('}') - self.gvg.generate() - - def set_include_headers(self, include_headers): - self.include_headers = include_headers - - def _generateHeader(self): - header = [] - header.append("//#includes, #defines, globals and such...\n") - for f in self.include_headers: - if 'xgl_enum_string_helper' not in f: - header.append("#include <%s>\n" % f) - #header.append('#include "xgl_enum_string_helper.h"\n\n// Function Prototypes\n') - header.append("\nchar* dynamic_gv_display(const XGL_VOID* pStruct, const char* prefix);\n") - return "".join(header) - - def _get_gv_func_name(self, struct): - return "%s_gv_print_%s" % (self.api, struct.lower().strip("_")) - - # Return elements to create formatted string for given struct member - 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=""): - struct_op = "->" - pre_var_name = '"%s "' % struct_member['full_type'] - if not struct_ptr: - struct_op = "." - member_name = struct_member['name'] - print_type = "p" - cast_type = "" - member_post = "" - array_index = "" - member_print_post = "" - if struct_member['array'] and 'CHAR' in struct_member['type']: # just print char array as string - print_type = "s" - print_array = False - elif struct_member['array'] and not print_array: - # Just print base address of array when not full print_array - cast_type = "(void*)" - elif is_type(struct_member['type'], 'enum'): - if struct_member['ptr']: - struct_var_name = "*" + struct_var_name - cast_type = "string_%s" % struct_member['type'] - print_type = "s" - elif is_type(struct_member['type'], 'struct'): # print struct address for now - cast_type = "(void*)" - if not struct_member['ptr']: - cast_type = "(void*)&" - elif 'BOOL' in struct_member['type']: - print_type = "s" - member_post = ' ? "TRUE" : "FALSE"' - elif 'FLOAT' in struct_member['type']: - print_type = "f" - elif 'UINT64' in struct_member['type']: - print_type = "lu" - elif 'UINT8' in struct_member['type']: - print_type = "hu" - elif '_SIZE' in struct_member['type']: - print_type = "zu" - elif True in [ui_str in struct_member['type'] for ui_str in ['UINT', '_FLAGS', '_SAMPLE_MASK']]: - print_type = "u" - elif 'INT' in struct_member['type']: - print_type = "i" - elif struct_member['ptr']: - pass - else: - #print("Unhandled struct type: %s" % struct_member['type']) - cast_type = "(void*)" - if print_array and struct_member['array']: - member_print_post = "[%u]" - array_index = " i," - member_post = "[i]" - print_out = "%%s%s%s%%%s%s" % (member_name, member_print_post, port_label, print_type, postfix) # section of print that goes inside of quotes - 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 - return (print_out, print_arg) - - def _generateBody(self): - gv_funcs = [] - array_func_list = [] # structs for which we'll generate an array version of their print function - array_func_list.append('xgl_descriptor_slot_info') - # For first pass, generate prototype - for s in self.struct_dict: - gv_funcs.append('char* %s(const %s* pStruct, const char* myNodeName);\n' % (self._get_gv_func_name(s), typedef_fwd_dict[s])) - if s.lower().strip("_") in array_func_list: - 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])) - gv_funcs.append('\n') - for s in self.struct_dict: - p_out = "" - p_args = "" - stp_list = [] # stp == "struct to print" a list of structs for this API call that should be printed as structs - # the fields below are a super-hacky way for now to get port labels into GV output, TODO : Clean this up! - pl_dict = {} - struct_num = 0 - # This isn't great but this pre-pass counts chars in struct members and flags structs w/ pNext - for m in sorted(self.struct_dict[s]): - if 'pNext' == self.struct_dict[s][m]['name'] or is_type(self.struct_dict[s][m]['type'], 'struct'): - stp_list.append(self.struct_dict[s][m]) - if 'pNext' == self.struct_dict[s][m]['name']: - pl_dict[m] = ' PORT=\\"pNext\\"' - else: - pl_dict[m] = ' PORT=\\"struct%i\\"' % struct_num - struct_num += 1 - 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])) - num_stps = len(stp_list); - total_strlen_str = '' - if 0 != num_stps: - gv_funcs.append(" char* tmpStr;\n") - gv_funcs.append(" char nodeName[100];\n") - gv_funcs.append(' char* stp_strs[%i];\n' % num_stps) - for index in range(num_stps): - if (stp_list[index]['ptr']): - if 'pDescriptorInfo' == stp_list[index]['name']: - gv_funcs.append(' if (pStruct->pDescriptorInfo && (0 != pStruct->descriptorCount)) {\n') - else: - gv_funcs.append(' if (pStruct->%s) {\n' % stp_list[index]['name']) - if 'pNext' == stp_list[index]['name']: - gv_funcs.append(' sprintf(nodeName, "pNext_%p", (void*)pStruct->pNext);\n') - gv_funcs.append(' tmpStr = dynamic_gv_display((XGL_VOID*)pStruct->pNext, nodeName);\n') - gv_funcs.append(' stp_strs[%i] = (char*)malloc(256+strlen(tmpStr)+strlen(nodeName)+strlen(myNodeName));\n' % index) - gv_funcs.append(' sprintf(stp_strs[%i], "%%s\\n\\"%%s\\":pNext -> \\"%%s\\" [];\\n", tmpStr, myNodeName, nodeName);\n' % index) - gv_funcs.append(' free(tmpStr);\n') - else: - gv_funcs.append(' sprintf(nodeName, "%s_%%p", (void*)pStruct->%s);\n' % (stp_list[index]['name'], stp_list[index]['name'])) - if 'pDescriptorInfo' == stp_list[index]['name']: - 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'])) - else: - gv_funcs.append(' tmpStr = %s(pStruct->%s, nodeName);\n' % (self._get_gv_func_name(stp_list[index]['type']), stp_list[index]['name'])) - gv_funcs.append(' stp_strs[%i] = (char*)malloc(256+strlen(tmpStr)+strlen(nodeName)+strlen(myNodeName));\n' % (index)) - gv_funcs.append(' sprintf(stp_strs[%i], "%%s\\n\\"%%s\\":struct%i -> \\"%%s\\" [];\\n", tmpStr, myNodeName, nodeName);\n' % (index, index)) - gv_funcs.append(' }\n') - gv_funcs.append(" else\n stp_strs[%i] = \"\";\n" % (index)) - elif stp_list[index]['array']: # TODO : For now just printing first element of array - gv_funcs.append(' sprintf(nodeName, "%s_%%p", (void*)&pStruct->%s[0]);\n' % (stp_list[index]['name'], stp_list[index]['name'])) - gv_funcs.append(' tmpStr = %s(&pStruct->%s[0], nodeName);\n' % (self._get_gv_func_name(stp_list[index]['type']), stp_list[index]['name'])) - gv_funcs.append(' stp_strs[%i] = (char*)malloc(256+strlen(tmpStr)+strlen(nodeName)+strlen(myNodeName));\n' % (index)) - gv_funcs.append(' sprintf(stp_strs[%i], "%%s\\n\\"%%s\\":struct%i -> \\"%%s\\" [];\\n", tmpStr, myNodeName, nodeName);\n' % (index, index)) - else: - gv_funcs.append(' sprintf(nodeName, "%s_%%p", (void*)&pStruct->%s);\n' % (stp_list[index]['name'], stp_list[index]['name'])) - gv_funcs.append(' tmpStr = %s(&pStruct->%s, nodeName);\n' % (self._get_gv_func_name(stp_list[index]['type']), stp_list[index]['name'])) - gv_funcs.append(' stp_strs[%i] = (char*)malloc(256+strlen(tmpStr)+strlen(nodeName)+strlen(myNodeName));\n' % (index)) - gv_funcs.append(' sprintf(stp_strs[%i], "%%s\\n\\"%%s\\":struct%i -> \\"%%s\\" [];\\n", tmpStr, myNodeName, nodeName);\n' % (index, index)) - total_strlen_str += 'strlen(stp_strs[%i]) + ' % index - gv_funcs.append(' str = (char*)malloc(%ssizeof(char)*2048);\n' % (total_strlen_str)) - gv_funcs.append(' sprintf(str, "\\"%s\\" [\\nlabel = <') - p_args = ", myNodeName, myNodeName, pStruct" - for m in sorted(self.struct_dict[s]): - plabel = "" - if m in pl_dict: - plabel = pl_dict[m] - (p_out1, p_args1) = self._get_struct_gv_print_formatted(self.struct_dict[s][m], port_label=plabel) - p_out += p_out1 - p_args += p_args1 - p_out += '
%s (%p)
>\\n];\\n\\n"' - p_args += ");\n" - gv_funcs.append(p_out) - gv_funcs.append(p_args) - if 0 != num_stps: - gv_funcs.append(' for (int32_t stp_index = %i; stp_index >= 0; stp_index--) {\n' % (num_stps-1)) - gv_funcs.append(' if (0 < strlen(stp_strs[stp_index])) {\n') - gv_funcs.append(' strncat(str, stp_strs[stp_index], strlen(stp_strs[stp_index]));\n') - gv_funcs.append(' free(stp_strs[stp_index]);\n') - gv_funcs.append(' }\n') - gv_funcs.append(' }\n') - gv_funcs.append(" return str;\n}\n") - if s.lower().strip("_") in array_func_list: - 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])) - gv_funcs.append(' str = (char*)malloc(sizeof(char)*1024*count);\n') - gv_funcs.append(' sprintf(str, "\\"%s\\" [\\nlabel = <", myNodeName, myNodeName, pStruct);\n') - gv_funcs.append(' for (uint32_t i=0; i < count; i++) {\n') - gv_funcs.append(' sprintf(tmpStr, "'); - p_args = "" - p_out = "" - for m in sorted(self.struct_dict[s]): - if 2 == m: # TODO : Hard-coded hack to skip last element of union for xgl_descriptor_slot_info struct - continue - plabel = "" - (p_out1, p_args1) = self._get_struct_gv_print_formatted(self.struct_dict[s][m], port_label=plabel) - 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) - p_out1 = '%s' % (p_out1[:-5]) - p_args1 += ', i, i' - p_out += p_out1 - p_args += p_args1 - p_out += '"' - p_args += ");\n" - p_args = p_args.replace('->', '[i].') - gv_funcs.append(p_out); - gv_funcs.append(p_args); - gv_funcs.append(' strncat(str, tmpStr, strlen(tmpStr));\n') - gv_funcs.append(' }\n') - gv_funcs.append(' strncat(str, "
%s (%p)
%%u
>\\n];\\n\\n", 20);\n') - # TODO : Another hard-coded hack. Tie these slots to "magical" DS0_MEMORY slots that should appear separately - gv_funcs.append(' for (uint32_t i=0; i < count; i++) {\n') - gv_funcs.append(' if (XGL_SLOT_UNUSED != pStruct[i].slotObjectType) {\n') - gv_funcs.append(' sprintf(tmpStr, "\\"%s\\":slot%u -> \\"DS0_MEMORY\\":slot%u [];\\n", myNodeName, i, i);\n') - gv_funcs.append(' strncat(str, tmpStr, strlen(tmpStr));\n') - gv_funcs.append(' }\n') - gv_funcs.append(' }\n') - gv_funcs.append(' return str;\n}\n') - # Add function to dynamically print out unknown struct - gv_funcs.append("char* dynamic_gv_display(const XGL_VOID* pStruct, const char* nodeName)\n{\n") - gv_funcs.append(" // Cast to APP_INFO ptr initially just to pull sType off struct\n") - gv_funcs.append(" XGL_STRUCTURE_TYPE sType = ((XGL_APPLICATION_INFO*)pStruct)->sType;\n") - gv_funcs.append(" switch (sType)\n {\n") - for e in enum_type_dict: - if "_STRUCTURE_TYPE" in e: - for v in sorted(enum_type_dict[e]): - struct_name = v.replace("_STRUCTURE_TYPE", "") - print_func_name = self._get_gv_func_name(struct_name) - # TODO : Hand-coded fixes for some exceptions - if 'XGL_PIPELINE_CB_STATE_CREATE_INFO' in struct_name: - struct_name = 'XGL_PIPELINE_CB_STATE' - elif 'XGL_SEMAPHORE_CREATE_INFO' in struct_name: - struct_name = 'XGL_QUEUE_SEMAPHORE_CREATE_INFO' - print_func_name = self._get_gv_func_name(struct_name) - elif 'XGL_SEMAPHORE_OPEN_INFO' in struct_name: - struct_name = 'XGL_QUEUE_SEMAPHORE_OPEN_INFO' - print_func_name = self._get_gv_func_name(struct_name) - gv_funcs.append(' case %s:\n' % (v)) - gv_funcs.append(' return %s((%s*)pStruct, nodeName);\n' % (print_func_name, struct_name)) - #gv_funcs.append(' }\n') - #gv_funcs.append(' break;\n') - gv_funcs.append(" default:\n") - gv_funcs.append(" return NULL;\n") - gv_funcs.append(" }\n") - gv_funcs.append("}") - return "".join(gv_funcs) - - - - - -# def _generateHeader(self): -# hdr = [] -# hdr.append('digraph g {\ngraph [\nrankdir = "LR"\n];') -# hdr.append('node [\nfontsize = "16"\nshape = "plaintext"\n];') -# hdr.append('edge [\n];\n') -# return "\n".join(hdr) -# -# def _generateBody(self): -# body = [] -# for s in self.struc_dict: -# field_num = 1 -# body.append('"%s" [\nlabel = <' % (s, typedef_fwd_dict[s])) -# for m in sorted(self.struc_dict[s]): -# body.append('' % (field_num, self.struc_dict[s][m]['full_type'], field_num+1, self.struc_dict[s][m]['name'])) -# field_num += 2 -# body.append('
%s
%s%s
>\n];\n') -# return "".join(body) - -def main(argv=None): - opts = handle_args() - # Parse input file and fill out global dicts - hfp = HeaderFileParser(opts.input_file) - hfp.parse() - # TODO : Don't want these to be global, see note at top about wrapper classes - global enum_val_dict - global enum_type_dict - global struct_dict - global typedef_fwd_dict - global typedef_rev_dict - global types_dict - enum_val_dict = hfp.get_enum_val_dict() - enum_type_dict = hfp.get_enum_type_dict() - struct_dict = hfp.get_struct_dict() - # TODO : Would like to validate struct data here to verify that all of the bools for struct members are correct at this point - typedef_fwd_dict = hfp.get_typedef_fwd_dict() - typedef_rev_dict = hfp.get_typedef_rev_dict() - types_dict = hfp.get_types_dict() - #print(enum_val_dict) - #print(typedef_dict) - #print(struct_dict) - if (opts.abs_out_dir is not None): - enum_sh_filename = os.path.join(opts.abs_out_dir, os.path.basename(opts.input_file).strip(".h")+"_enum_string_helper.h") - else: - enum_sh_filename = os.path.join(os.getcwd(), opts.rel_out_dir, os.path.basename(opts.input_file).strip(".h")+"_enum_string_helper.h") - enum_sh_filename = os.path.abspath(enum_sh_filename) - if not os.path.exists(os.path.dirname(enum_sh_filename)): - print("Creating output dir %s" % os.path.dirname(enum_sh_filename)) - os.mkdir(os.path.dirname(enum_sh_filename)) - if opts.gen_enum_string_helper: - print("Generating enum string helper to %s" % enum_sh_filename) - enum_vh_filename = os.path.join(os.path.dirname(enum_sh_filename), os.path.basename(opts.input_file).strip(".h")+"_enum_validate_helper.h") - print("Generating enum validate helper to %s" % enum_vh_filename) - eg = EnumCodeGen(enum_type_dict, enum_val_dict, typedef_fwd_dict, os.path.basename(opts.input_file), enum_sh_filename, enum_vh_filename) - eg.generateStringHelper() - eg.generateEnumValidate() - #for struct in struct_dict: - #print(struct) - if opts.gen_struct_wrappers: - sw = StructWrapperGen(struct_dict, os.path.basename(opts.input_file).strip(".h"), os.path.dirname(enum_sh_filename)) - #print(sw.get_class_name(struct)) - sw.set_include_headers([os.path.basename(opts.input_file),os.path.basename(enum_sh_filename),"stdint.h","stdio.h","stdlib.h"]) - print("Generating struct wrapper header to %s" % sw.header_filename) - sw.generateHeader() - print("Generating struct wrapper class to %s" % sw.class_filename) - sw.generateBody() - sw.generateStringHelper() - # Generate a 2nd helper file that excludes addrs - sw.set_no_addr(True) - sw.generateStringHelper() - sw.set_no_addr(False) - 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"]) - sw.generateStringHelperCpp() - sw.set_no_addr(True) - sw.generateStringHelperCpp() - if opts.gen_cmake: - cmg = CMakeGen(sw, os.path.dirname(enum_sh_filename)) - cmg.generate() - if opts.gen_graphviz: - gv = GraphVizGen(struct_dict, os.path.basename(opts.input_file).strip(".h"), os.path.dirname(enum_sh_filename)) - gv.set_include_headers([os.path.basename(opts.input_file),os.path.basename(enum_sh_filename),"stdint.h","stdio.h","stdlib.h"]) - gv.generate() - print("DONE!") - #print(typedef_rev_dict) - #print(types_dict) - #recreate_structs() - -if __name__ == "__main__": - sys.exit(main()) diff --git a/xgl-layer-generate.py b/xgl-layer-generate.py index d19a63f8..7e2cb742 100755 --- a/xgl-layer-generate.py +++ b/xgl-layer-generate.py @@ -26,8 +26,10 @@ # Chia-I Wu import sys +import os import xgl +import xgl_helper class Subcommand(object): def __init__(self, argv): @@ -434,10 +436,9 @@ class Subcommand(object): (pft, pfi) = ("%s", '"addr"') log_func += '%s = %s, ' % (p.name, pft) print_vals += ', %s' % (pfi) - # TODO : Just want this to be simple check for params of STRUCT type - if "pCreateInfo" in p.name or ('const' in p.ty and '*' in p.ty and False not in [tmp_ty not in p.ty for tmp_ty in ['XGL_CHAR', 'XGL_VOID', 'XGL_CMD_BUFFER', 'XGL_QUEUE_SEMAPHORE', 'XGL_FENCE', 'XGL_SAMPLER', 'XGL_UINT32']]): - if 'Wsi' not in proto.name: - cis_param_index.append(pindex) + # 'format' gets special treatment as a small struct that we print inline + if 'Wsi' not in proto.name and 'format' != p.name and xgl_helper.is_type(p.ty.strip('*').strip('const '), 'struct'): + cis_param_index.append(pindex) pindex += 1 log_func = log_func.strip(', ') if proto.ret != "XGL_VOID": @@ -624,13 +625,96 @@ class Subcommand(object): '%s%s' '%s' '}' % (qual, decl, proto.params[0].name, using_line, ret_val, c_call, create_line, destroy_line, stmt)) - - # TODO : Put this code somewhere so it gets called at the end if objects not deleted : - # // Report any remaining objects in LL - # objNode *pTrav = pObjLLHead; - # while (pTrav) { - # printf("WARN : %s object %p has not been destroyed.\n", pTrav->objType, pTrav->pObj); - # } + elif "ParamChecker" == layer: + # TODO : Need to fix up the non-else cases below to do param checking as well + decl = proto.c_func(prefix="xgl", attr="XGLAPI") + param0_name = proto.params[0].name + ret_val = '' + stmt = '' + param_checks = [] + # Add code to check enums and structs + # TODO : Currently only validating enum values, need to validate everything + str_decl = False + for p in proto.params: + if xgl_helper.is_type(p.ty.strip('*').strip('const '), 'enum'): + if not str_decl: + param_checks.append(' char str[1024];') + str_decl = True + param_checks.append(' if (!validate_%s(%s)) {' % (p.ty, p.name)) + param_checks.append(' char str[1024];') + param_checks.append(' sprintf(str, "Parameter %s to function %s has invalid value of %%i.", (int)%s);' % (p.name, proto.name, p.name)) + param_checks.append(' layerCbMsg(XGL_DBG_MSG_ERROR, XGL_VALIDATION_LEVEL_0, NULL, 0, 1, "PARAMCHECK", str);') + param_checks.append(' }') + elif xgl_helper.is_type(p.ty.strip('*').strip('const '), 'struct') and 'const' in p.ty: + if not str_decl: + param_checks.append(' char str[1024];') + str_decl = True + if '*' in p.ty: # First check for null ptr + param_checks.append(' if (!%s) {' % p.name) + param_checks.append(' sprintf(str, "Struct ptr parameter %s to function %s is NULL.");' % (p.name, proto.name)) + param_checks.append(' layerCbMsg(XGL_DBG_MSG_UNKNOWN, XGL_VALIDATION_LEVEL_0, NULL, 0, 1, "PARAMCHECK", str);') + param_checks.append(' }') + param_checks.append(' else if (!xgl_validate_%s(%s)) {' % (p.ty.strip('*').strip('const ').lower(), p.name)) + else: + param_checks.append(' if (!xgl_validate_%s(%s)) {' % (p.ty.strip('const ').lower(), p.name)) + param_checks.append(' sprintf(str, "Parameter %s to function %s contains an invalid value.");' % (p.name, proto.name)) + param_checks.append(' layerCbMsg(XGL_DBG_MSG_ERROR, XGL_VALIDATION_LEVEL_0, NULL, 0, 1, "PARAMCHECK", str);') + param_checks.append(' }') + if proto.ret != "XGL_VOID": + ret_val = "XGL_RESULT result = " + stmt = " return result;\n" + if proto.name == "EnumerateLayers": + c_call = proto.c_call().replace("(" + proto.params[0].name, "((XGL_PHYSICAL_GPU)gpuw->nextObject", 1) + funcs.append('%s%s\n' + '{\n' + ' char str[1024];\n' + ' if (gpu != NULL) {\n' + ' XGL_BASE_LAYER_OBJECT* gpuw = (XGL_BASE_LAYER_OBJECT *) %s;\n' + ' sprintf(str, "At start of layered %s\\n");\n' + ' layerCbMsg(XGL_DBG_MSG_UNKNOWN, XGL_VALIDATION_LEVEL_0, gpu, 0, 0, "PARAMCHECK", str);\n' + ' pCurObj = gpuw;\n' + ' pthread_once(&tabOnce, initLayerTable);\n' + ' %snextTable.%s;\n' + ' sprintf(str, "Completed layered %s\\n");\n' + ' layerCbMsg(XGL_DBG_MSG_UNKNOWN, XGL_VALIDATION_LEVEL_0, gpu, 0, 0, "PARAMCHECK", str);\n' + ' fflush(stdout);\n' + ' %s' + ' } else {\n' + ' if (pOutLayerCount == NULL || pOutLayers == NULL || pOutLayers[0] == NULL)\n' + ' return XGL_ERROR_INVALID_POINTER;\n' + ' // This layer compatible with all GPUs\n' + ' *pOutLayerCount = 1;\n' + ' strncpy(pOutLayers[0], "%s", maxStringSize);\n' + ' return XGL_SUCCESS;\n' + ' }\n' + '}' % (qual, decl, proto.params[0].name, proto.name, ret_val, c_call, proto.name, stmt, layer_name)) + elif 'DbgRegisterMsgCallback' == proto.name: + funcs.append(self._gen_layer_dbg_callback_register()) + elif 'DbgUnregisterMsgCallback' == proto.name: + funcs.append(self._gen_layer_dbg_callback_unregister()) + elif proto.params[0].ty != "XGL_PHYSICAL_GPU": + funcs.append('%s%s\n' + '{\n' + '%s\n' + ' %snextTable.%s;\n' + '%s' + '}' % (qual, decl, "\n".join(param_checks), ret_val, proto.c_call(), stmt)) + else: + c_call = proto.c_call().replace("(" + proto.params[0].name, "((XGL_PHYSICAL_GPU)gpuw->nextObject", 1) + funcs.append('%s%s\n' + '{\n' + ' char str[1024];' + ' XGL_BASE_LAYER_OBJECT* gpuw = (XGL_BASE_LAYER_OBJECT *) %s;\n' + ' sprintf(str, "At start of layered %s\\n");\n' + ' layerCbMsg(XGL_DBG_MSG_UNKNOWN, XGL_VALIDATION_LEVEL_0, gpuw, 0, 0, "PARAMCHECK", str);\n' + ' pCurObj = gpuw;\n' + ' pthread_once(&tabOnce, initLayerTable);\n' + ' %snextTable.%s;\n' + ' sprintf(str, "Completed layered %s\\n");\n' + ' layerCbMsg(XGL_DBG_MSG_UNKNOWN, XGL_VALIDATION_LEVEL_0, gpuw, 0, 0, "PARAMCHECK", str);\n' + ' fflush(stdout);\n' + '%s' + '}' % (qual, decl, proto.params[0].name, proto.name, ret_val, c_call, proto.name, stmt)) return "\n\n".join(funcs) @@ -1086,6 +1170,18 @@ class ObjectTrackerSubcommand(Subcommand): return "\n\n".join(body) +class ParamCheckerSubcommand(Subcommand): + def generate_header(self): + return '#include \n#include \n#include \n#include \n#include \n#include "xglLayer.h"\n#include "xgl_enum_validate_helper.h"\n#include "xgl_struct_validate_helper.h"\n\nstatic XGL_LAYER_DISPATCH_TABLE nextTable;\nstatic XGL_BASE_LAYER_OBJECT *pCurObj;\nstatic pthread_once_t tabOnce = PTHREAD_ONCE_INIT;\n' + + def generate_body(self): + body = [self._gen_layer_dbg_callback_header(), + self._generate_layer_dispatch_table(), + self._generate_dispatch_entrypoints("XGL_LAYER_EXPORT", "ParamChecker"), + self._generate_layer_gpa_function()] + + return "\n\n".join(body) + def main(): subcommands = { "layer-funcs" : LayerFuncsSubcommand, @@ -1097,14 +1193,24 @@ def main(): "ApiDumpCpp" : ApiDumpCppSubcommand, "ApiDumpNoAddrCpp" : ApiDumpNoAddrCppSubcommand, "ObjectTracker" : ObjectTrackerSubcommand, + "ParamChecker" : ParamCheckerSubcommand, } - if len(sys.argv) < 2 or sys.argv[1] not in subcommands: - print("Usage: %s [options]" % sys.argv[0]) + if len(sys.argv) < 3 or sys.argv[1] not in subcommands or not os.path.exists(sys.argv[2]): + print("Usage: %s [options]" % sys.argv[0]) print print("Available sucommands are: %s" % " ".join(subcommands)) exit(1) + hfp = xgl_helper.HeaderFileParser(sys.argv[2]) + hfp.parse() + xgl_helper.enum_val_dict = hfp.get_enum_val_dict() + xgl_helper.enum_type_dict = hfp.get_enum_type_dict() + xgl_helper.struct_dict = hfp.get_struct_dict() + xgl_helper.typedef_fwd_dict = hfp.get_typedef_fwd_dict() + xgl_helper.typedef_rev_dict = hfp.get_typedef_rev_dict() + xgl_helper.types_dict = hfp.get_types_dict() + subcmd = subcommands[sys.argv[1]](sys.argv[2:]) subcmd.run() diff --git a/xgl_helper.py b/xgl_helper.py new file mode 100755 index 00000000..36e05ac0 --- /dev/null +++ b/xgl_helper.py @@ -0,0 +1,1367 @@ +#!/usr/bin/env python3 +# +# XGL +# +# Copyright (C) 2014 LunarG, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +# DEALINGS IN THE SOFTWARE. +import argparse +import os +import sys + +# code_gen.py overview +# This script generates code based on input headers +# Initially it's intended to support Mantle and XGL headers and +# generate wrappers functions that can be used to display +# structs in a human-readable txt format, as well as utility functions +# to print enum values as strings + + +def handle_args(): + parser = argparse.ArgumentParser(description='Perform analysis of vogl trace.') + parser.add_argument('input_file', help='The input header file from which code will be generated.') + 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.') + parser.add_argument('--abs_out_dir', required=False, default=None, help='Absolute path to write output files. Will be created if needed.') + 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.') + parser.add_argument('--gen_struct_wrappers', required=False, action='store_true', default=False, help='Enable generation of struct wrapper classes.') + parser.add_argument('--gen_cmake', required=False, action='store_true', default=False, help='Enable generation of cmake file for generated code.') + parser.add_argument('--gen_graphviz', required=False, action='store_true', default=False, help='Enable generation of graphviz dot file.') + #parser.add_argument('--test', action='store_true', default=False, help='Run simple test.') + return parser.parse_args() + +# TODO : Ideally these data structs would be opaque to user and could be wrapped +# in their own class(es) to make them friendly for data look-up +# Dicts for Data storage +# enum_val_dict[value_name] = dict keys are the string enum value names for all enums +# |-------->['type'] = the type of enum class into which the value falls +# |-------->['val'] = the value assigned to this particular value_name +# '-------->['unique'] = bool designating if this enum 'val' is unique within this enum 'type' +enum_val_dict = {} +# enum_type_dict['type'] = the type or class of of enum +# '----->['val_name1', 'val_name2'...] = each type references a list of val_names within this type +enum_type_dict = {} +# struct_dict['struct_basename'] = the base (non-typedef'd) name of the struct +# |->[] = members are stored via their integer placement in the struct +# | |->['name'] = string name of this struct member +# ... |->['full_type'] = complete type qualifier for this member +# |->['type'] = base type for this member +# |->['ptr'] = bool indicating if this member is ptr +# |->['const'] = bool indicating if this member is const +# |->['struct'] = bool indicating if this member is a struct type +# |->['array'] = bool indicating if this member is an array +# '->['array_size'] = int indicating size of array members (0 by default) +struct_dict = {} +# typedef_fwd_dict stores mapping from orig_type_name -> new_type_name +typedef_fwd_dict = {} +# typedef_rev_dict stores mapping from new_type_name -> orig_type_name +typedef_rev_dict = {} # store new_name -> orig_name mapping +# types_dict['id_name'] = identifier name will map to it's type +# '---->'type' = currently either 'struct' or 'enum' +types_dict = {} # store orig_name -> type mapping + + +# Class that parses header file and generates data structures that can +# Then be used for other tasks +class HeaderFileParser: + def __init__(self, header_file=None): + self.header_file = header_file + # store header data in various formats, see above for more info + self.enum_val_dict = {} + self.enum_type_dict = {} + self.struct_dict = {} + self.typedef_fwd_dict = {} + self.typedef_rev_dict = {} + self.types_dict = {} + + def setHeaderFile(self, header_file): + self.header_file = header_file + + def get_enum_val_dict(self): + return self.enum_val_dict + + def get_enum_type_dict(self): + return self.enum_type_dict + + def get_struct_dict(self): + return self.struct_dict + + def get_typedef_fwd_dict(self): + return self.typedef_fwd_dict + + def get_typedef_rev_dict(self): + return self.typedef_rev_dict + + def get_types_dict(self): + return self.types_dict + + # Parse header file into data structures + def parse(self): + # parse through the file, identifying different sections + parse_enum = False + parse_struct = False + member_num = 0 + # TODO : Comment parsing is very fragile but handles 2 known files + block_comment = False + with open(self.header_file) as f: + for line in f: + if block_comment: + if '*/' in line: + block_comment = False + continue + if '/*' in line: + block_comment = True + elif 0 == len(line.split()): + #print("Skipping empty line") + continue + elif line.split()[0].strip().startswith("//"): + #print("Skipping commented line %s" % line) + continue + elif 'typedef enum' in line: + (ty_txt, en_txt, base_type) = line.strip().split(None, 2) + #print("Found ENUM type %s" % base_type) + parse_enum = True + default_enum_val = 0 + self.types_dict[base_type] = 'enum' + elif 'typedef struct' in line: + (ty_txt, st_txt, base_type) = line.strip().split(None, 2) + #print("Found STRUCT type: %s" % base_type) + parse_struct = True + self.types_dict[base_type] = 'struct' + elif 'typedef union' in line: + (ty_txt, st_txt, base_type) = line.strip().split(None, 2) + #print("Found UNION type: %s" % base_type) + parse_struct = True + self.types_dict[base_type] = 'struct' + elif '}' in line and (parse_enum or parse_struct): + if len(line.split()) > 1: # deals with embedded union in one struct + parse_enum = False + parse_struct = False + member_num = 0 + # TODO : Can pull target of typedef here for remapping + (cur_char, targ_type) = line.strip().split(None, 1) + self.typedef_fwd_dict[base_type] = targ_type.strip(';') + self.typedef_rev_dict[targ_type.strip(';')] = base_type + elif parse_enum: + if 'XGL_MAX_ENUM' not in line and '{' not in line: + self._add_enum(line, base_type, default_enum_val) + default_enum_val += 1 + elif parse_struct: + if ';' in line: + self._add_struct(line, base_type, member_num) + member_num = member_num + 1 + #elif '(' in line: + #print("Function: %s" % line) + + # populate enum dicts based on enum lines + def _add_enum(self, line_txt, enum_type, def_enum_val): + #print("Parsing enum line %s" % line_txt) + if '=' in line_txt: + (enum_name, eq_char, enum_val) = line_txt.split(None, 2) + else: + enum_name = line_txt.split(',')[0] + enum_val = str(def_enum_val) + self.enum_val_dict[enum_name] = {} + self.enum_val_dict[enum_name]['type'] = enum_type + # strip comma and comment, then extra split in case of no comma w/ comments + enum_val = enum_val.strip().split(',', 1)[0] + self.enum_val_dict[enum_name]['val'] = enum_val.split()[0] + # account for negative values surrounded by parens + self.enum_val_dict[enum_name]['val'] = self.enum_val_dict[enum_name]['val'].strip(')').replace('-(', '-') + # Try to cast to int to determine if enum value is unique + try: + #print("ENUM val:", self.enum_val_dict[enum_name]['val']) + int(self.enum_val_dict[enum_name]['val'], 0) + self.enum_val_dict[enum_name]['unique'] = True + #print("ENUM has num value") + except ValueError: + self.enum_val_dict[enum_name]['unique'] = False + #print("ENUM is not a number value") + # Update enum_type_dict as well + if not enum_type in self.enum_type_dict: + self.enum_type_dict[enum_type] = [] + self.enum_type_dict[enum_type].append(enum_name) + + # populate struct dicts based on struct lines + # TODO : Handle ":" bitfield, "**" ptr->ptr and "const type*const*" + def _add_struct(self, line_txt, struct_type, num): + #print("Parsing struct line %s" % line_txt) + if not struct_type in self.struct_dict: + self.struct_dict[struct_type] = {} + members = line_txt.strip().split(';', 1)[0] # first strip semicolon & comments + # TODO : Handle bitfields more correctly + members = members.strip().split(':', 1)[0] # strip bitfield element + (member_type, member_name) = members.rsplit(None, 1) + self.struct_dict[struct_type][num] = {} + self.struct_dict[struct_type][num]['full_type'] = member_type + if '*' in member_type: + self.struct_dict[struct_type][num]['ptr'] = True + member_type = member_type.strip('*') + else: + self.struct_dict[struct_type][num]['ptr'] = False + if 'const' in member_type: + self.struct_dict[struct_type][num]['const'] = True + member_type = member_type.strip('const').strip() + else: + self.struct_dict[struct_type][num]['const'] = False + # TODO : There is a bug here where it seems that at the time we do this check, + # the data is not in the types or typedef_rev_dict, so we never pass this if check + if is_type(member_type, 'struct'): + self.struct_dict[struct_type][num]['struct'] = True + else: + self.struct_dict[struct_type][num]['struct'] = False + self.struct_dict[struct_type][num]['type'] = member_type + if '[' in member_name: + (member_name, array_size) = member_name.split('[', 1) + self.struct_dict[struct_type][num]['array'] = True + self.struct_dict[struct_type][num]['array_size'] = array_size.strip(']') + else: + self.struct_dict[struct_type][num]['array'] = False + self.struct_dict[struct_type][num]['array_size'] = 0 + self.struct_dict[struct_type][num]['name'] = member_name + +# check if given identifier if of specified type_to_check +def is_type(identifier, type_to_check): + if identifier in types_dict and type_to_check == types_dict[identifier]: + return True + if identifier in typedef_rev_dict: + new_id = typedef_rev_dict[identifier] + if new_id in types_dict and type_to_check == types_dict[new_id]: + return True + return False + +# This is a validation function to verify that we can reproduce the original structs +def recreate_structs(): + for struct_name in struct_dict: + sys.stdout.write("typedef struct %s\n{\n" % struct_name) + for mem_num in sorted(struct_dict[struct_name]): + sys.stdout.write(" ") + if struct_dict[struct_name][mem_num]['const']: + sys.stdout.write("const ") + #if struct_dict[struct_name][mem_num]['struct']: + # sys.stdout.write("struct ") + sys.stdout.write (struct_dict[struct_name][mem_num]['type']) + if struct_dict[struct_name][mem_num]['ptr']: + sys.stdout.write("*") + sys.stdout.write(" ") + sys.stdout.write(struct_dict[struct_name][mem_num]['name']) + if struct_dict[struct_name][mem_num]['array']: + sys.stdout.write("[") + sys.stdout.write(struct_dict[struct_name][mem_num]['array_size']) + sys.stdout.write("]") + sys.stdout.write(";\n") + sys.stdout.write("} ") + sys.stdout.write(typedef_fwd_dict[struct_name]) + sys.stdout.write(";\n\n") + +# class for writing common file elements +# Here's how this class lays out a file: +# COPYRIGHT +# HEADER +# BODY +# FOOTER +# +# For each of these sections, there's a "set*" function +# The class as a whole has a generate function which will write each section in order +class CommonFileGen: + def __init__(self, filename=None, copyright_txt="", header_txt="", body_txt="", footer_txt=""): + self.filename = filename + self.contents = {'copyright': copyright_txt, 'header': header_txt, 'body': body_txt, 'footer': footer_txt} + # TODO : Set a default copyright & footer at least + + def setFilename(self, filename): + self.filename = filename + + def setCopyright(self, c): + self.contents['copyright'] = c + + def setHeader(self, h): + self.contents['header'] = h + + def setBody(self, b): + self.contents['body'] = b + + def setFooter(self, f): + self.contents['footer'] = f + + def generate(self): + #print("Generate to file %s" % self.filename) + with open(self.filename, "w") as f: + f.write(self.contents['copyright']) + f.write(self.contents['header']) + f.write(self.contents['body']) + f.write(self.contents['footer']) + +# class for writing a wrapper class for structures +# The wrapper class wraps the structs and includes utility functions for +# setting/getting member values and displaying the struct data in various formats +class StructWrapperGen: + def __init__(self, in_struct_dict, prefix, out_dir): + self.struct_dict = in_struct_dict + self.include_headers = [] + self.api = prefix + self.header_filename = os.path.join(out_dir, self.api+"_struct_wrappers.h") + self.class_filename = os.path.join(out_dir, self.api+"_struct_wrappers.cpp") + self.string_helper_filename = os.path.join(out_dir, self.api+"_struct_string_helper.h") + self.string_helper_no_addr_filename = os.path.join(out_dir, self.api+"_struct_string_helper_no_addr.h") + self.string_helper_cpp_filename = os.path.join(out_dir, self.api+"_struct_string_helper_cpp.h") + self.string_helper_no_addr_cpp_filename = os.path.join(out_dir, self.api+"_struct_string_helper_no_addr_cpp.h") + self.validate_helper_filename = os.path.join(out_dir, self.api+"_struct_validate_helper.h") + self.no_addr = False + self.hfg = CommonFileGen(self.header_filename) + self.cfg = CommonFileGen(self.class_filename) + self.shg = CommonFileGen(self.string_helper_filename) + self.shcppg = CommonFileGen(self.string_helper_cpp_filename) + self.vhg = CommonFileGen(self.validate_helper_filename) + #print(self.header_filename) + self.header_txt = "" + self.definition_txt = "" + + def set_include_headers(self, include_headers): + self.include_headers = include_headers + + def set_no_addr(self, no_addr): + self.no_addr = no_addr + if self.no_addr: + self.shg = CommonFileGen(self.string_helper_no_addr_filename) + self.shcppg = CommonFileGen(self.string_helper_no_addr_cpp_filename) + else: + self.shg = CommonFileGen(self.string_helper_filename) + self.shcppg = CommonFileGen(self.string_helper_cpp_filename) + + # Return class name for given struct name + def get_class_name(self, struct_name): + class_name = struct_name.strip('_').lower() + "_struct_wrapper" + return class_name + + def get_file_list(self): + return [os.path.basename(self.header_filename), os.path.basename(self.class_filename), os.path.basename(self.string_helper_filename)] + + # Generate class header file + def generateHeader(self): + self.hfg.setCopyright(self._generateCopyright()) + self.hfg.setHeader(self._generateHeader()) + self.hfg.setBody(self._generateClassDeclaration()) + self.hfg.setFooter(self._generateFooter()) + self.hfg.generate() + + # Generate class definition + def generateBody(self): + self.cfg.setCopyright(self._generateCopyright()) + self.cfg.setHeader(self._generateCppHeader()) + self.cfg.setBody(self._generateClassDefinition()) + self.cfg.setFooter(self._generateFooter()) + self.cfg.generate() + + # Generate c-style .h file that contains functions for printing structs + def generateStringHelper(self): + print("Generating struct string helper") + self.shg.setCopyright(self._generateCopyright()) + self.shg.setHeader(self._generateStringHelperHeader()) + self.shg.setBody(self._generateStringHelperFunctions()) + self.shg.generate() + + # Generate cpp-style .h file that contains functions for printing structs + def generateStringHelperCpp(self): + print("Generating struct string helper cpp") + self.shcppg.setCopyright(self._generateCopyright()) + self.shcppg.setHeader(self._generateStringHelperHeaderCpp()) + self.shcppg.setBody(self._generateStringHelperFunctionsCpp()) + self.shcppg.generate() + + # Generate c-style .h file that contains functions for printing structs + def generateValidateHelper(self): + print("Generating struct validate helper") + self.vhg.setCopyright(self._generateCopyright()) + self.vhg.setHeader(self._generateValidateHelperHeader()) + self.vhg.setBody(self._generateValidateHelperFunctions()) + self.vhg.generate() + + def _generateCopyright(self): + return "//This is the copyright\n" + + def _generateCppHeader(self): + header = [] + header.append("//#includes, #defines, globals and such...\n") + header.append("#include \n#include <%s>\n#include <%s_enum_string_helper.h>\n" % (os.path.basename(self.header_filename), self.api)) + return "".join(header) + + def _generateClassDefinition(self): + class_def = [] + if 'xgl' == self.api: # Mantle doesn't have pNext to worry about + class_def.append(self._generateDynamicPrintFunctions()) + for s in self.struct_dict: + class_def.append("\n// %s class definition" % self.get_class_name(s)) + class_def.append(self._generateConstructorDefinitions(s)) + class_def.append(self._generateDestructorDefinitions(s)) + class_def.append(self._generateDisplayDefinitions(s)) + return "\n".join(class_def) + + def _generateConstructorDefinitions(self, s): + con_defs = [] + 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))) + # TODO : This is a shallow copy of ptrs + 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])) + 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])) + return "\n".join(con_defs) + + def _generateDestructorDefinitions(self, s): + return "%s::~%s() {}" % (self.get_class_name(s), self.get_class_name(s)) + + def _generateDynamicPrintFunctions(self): + dp_funcs = [] + 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") + dp_funcs.append(" XGL_STRUCTURE_TYPE sType = ((XGL_APPLICATION_INFO*)pStruct)->sType;\n") + dp_funcs.append(" switch (sType)\n {") + for e in enum_type_dict: + class_num = 0 + if "_STRUCTURE_TYPE" in e: + for v in sorted(enum_type_dict[e]): + struct_name = v.replace("_STRUCTURE_TYPE", "") + class_name = self.get_class_name(struct_name) + # TODO : Hand-coded fixes for some exceptions + if 'XGL_PIPELINE_CB_STATE_CREATE_INFO' in struct_name: + struct_name = 'XGL_PIPELINE_CB_STATE' + elif 'XGL_SEMAPHORE_CREATE_INFO' in struct_name: + struct_name = 'XGL_QUEUE_SEMAPHORE_CREATE_INFO' + class_name = self.get_class_name(struct_name) + elif 'XGL_SEMAPHORE_OPEN_INFO' in struct_name: + struct_name = 'XGL_QUEUE_SEMAPHORE_OPEN_INFO' + class_name = self.get_class_name(struct_name) + instance_name = "swc%i" % class_num + dp_funcs.append(" case %s:\n {" % (v)) + dp_funcs.append(" %s %s((%s*)pStruct);" % (class_name, instance_name, struct_name)) + dp_funcs.append(" %s.set_indent(indent);" % (instance_name)) + dp_funcs.append(" %s.display_full_txt();" % (instance_name)) + dp_funcs.append(" }") + dp_funcs.append(" break;") + class_num += 1 + dp_funcs.append(" }") + dp_funcs.append("}\n") + return "\n".join(dp_funcs) + + def _get_func_name(self, struct, mid_str): + return "%s_%s_%s" % (self.api, mid_str, struct.lower().strip("_")) + + def _get_sh_func_name(self, struct): + return self._get_func_name(struct, 'print') + + def _get_vh_func_name(self, struct): + return self._get_func_name(struct, 'validate') + + # Return elements to create formatted string for given struct member + def _get_struct_print_formatted(self, struct_member, pre_var_name="prefix", postfix = "\\n", struct_var_name="pStruct", struct_ptr=True, print_array=False): + struct_op = "->" + if not struct_ptr: + struct_op = "." + member_name = struct_member['name'] + print_type = "p" + cast_type = "" + member_post = "" + array_index = "" + member_print_post = "" + if struct_member['array'] and 'CHAR' in struct_member['type']: # just print char array as string + print_type = "s" + print_array = False + elif struct_member['array'] and not print_array: + # Just print base address of array when not full print_array + cast_type = "(void*)" + elif is_type(struct_member['type'], 'enum'): + cast_type = "string_%s" % struct_member['type'] + if struct_member['ptr']: + struct_var_name = "*" + struct_var_name + print_type = "s" + elif is_type(struct_member['type'], 'struct'): # print struct address for now + cast_type = "(void*)" + if not struct_member['ptr']: + cast_type = "(void*)&" + elif 'BOOL' in struct_member['type']: + print_type = "s" + member_post = ' ? "TRUE" : "FALSE"' + elif 'FLOAT' in struct_member['type']: + print_type = "f" + elif 'UINT64' in struct_member['type']: + print_type = "lu" + elif 'UINT8' in struct_member['type']: + print_type = "hu" + elif '_SIZE' in struct_member['type']: + print_type = "zu" + elif True in [ui_str in struct_member['type'] for ui_str in ['UINT', '_FLAGS', '_SAMPLE_MASK']]: + print_type = "u" + elif 'INT' in struct_member['type']: + print_type = "i" + elif struct_member['ptr']: + pass + else: + #print("Unhandled struct type: %s" % struct_member['type']) + cast_type = "(void*)" + if print_array and struct_member['array']: + member_print_post = "[%u]" + array_index = " i," + member_post = "[i]" + print_out = "%%s%s%s = %%%s%s" % (member_name, member_print_post, print_type, postfix) # section of print that goes inside of quotes + 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 + if self.no_addr and "p" == print_type: + print_out = "%%s%s%s = addr\\n" % (member_name, member_print_post) # section of print that goes inside of quotes + print_arg = ", %s" % (pre_var_name) + return (print_out, print_arg) + + def _generateStringHelperFunctions(self): + sh_funcs = [] + # We do two passes, first pass just generates prototypes for all the functsions + for s in self.struct_dict: + sh_funcs.append('char* %s(const %s* pStruct, const char* prefix);\n' % (self._get_sh_func_name(s), typedef_fwd_dict[s])) + sh_funcs.append('\n') + for s in self.struct_dict: + p_out = "" + p_args = "" + stp_list = [] # stp == "struct to print" a list of structs for this API call that should be printed as structs + # This isn't great but this pre-pass counts chars in struct members and flags structs w/ pNext + for m in self.struct_dict[s]: + if 'pNext' == self.struct_dict[s][m]['name'] or is_type(self.struct_dict[s][m]['type'], 'struct'): + stp_list.append(self.struct_dict[s][m]) + 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])) + sh_funcs.append(" size_t len;\n") + num_stps = len(stp_list); + total_strlen_str = '' + if 0 != num_stps: + sh_funcs.append(" char* tmpStr;\n") + sh_funcs.append(' char* extra_indent = (char*)malloc(strlen(prefix) + 3);\n') + sh_funcs.append(' strcpy(extra_indent, " ");\n') + sh_funcs.append(' strncat(extra_indent, prefix, strlen(prefix));\n') + sh_funcs.append(' char* stp_strs[%i];\n' % num_stps) + for index in range(num_stps): + if (stp_list[index]['ptr']): + sh_funcs.append(' if (pStruct->%s) {\n' % stp_list[index]['name']) + if 'pNext' == stp_list[index]['name']: + sh_funcs.append(' tmpStr = dynamic_display((XGL_VOID*)pStruct->pNext, prefix);\n') + sh_funcs.append(' len = 256+strlen(tmpStr);\n') + sh_funcs.append(' stp_strs[%i] = (char*)malloc(len);\n' % index) + if self.no_addr: + sh_funcs.append(' snprintf(stp_strs[%i], len, " %%spNext (addr)\\n%%s", prefix, tmpStr);\n' % index) + else: + sh_funcs.append(' snprintf(stp_strs[%i], len, " %%spNext (%%p)\\n%%s", prefix, (void*)pStruct->pNext, tmpStr);\n' % index) + sh_funcs.append(' free(tmpStr);\n') + else: + sh_funcs.append(' tmpStr = %s(pStruct->%s, extra_indent);\n' % (self._get_sh_func_name(stp_list[index]['type']), stp_list[index]['name'])) + sh_funcs.append(' len = 256+strlen(tmpStr)+strlen(prefix);\n') + sh_funcs.append(' stp_strs[%i] = (char*)malloc(len);\n' % (index)) + if self.no_addr: + sh_funcs.append(' snprintf(stp_strs[%i], len, " %%s%s (addr)\\n%%s", prefix, tmpStr);\n' % (index, stp_list[index]['name'])) + else: + 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'])) + sh_funcs.append(' }\n') + sh_funcs.append(" else\n stp_strs[%i] = \"\";\n" % (index)) + elif stp_list[index]['array']: # TODO : For now just printing first element of array + sh_funcs.append(' tmpStr = %s(&pStruct->%s[0], extra_indent);\n' % (self._get_sh_func_name(stp_list[index]['type']), stp_list[index]['name'])) + sh_funcs.append(' len = 256+strlen(tmpStr);\n') + sh_funcs.append(' stp_strs[%i] = (char*)malloc(len);\n' % (index)) + if self.no_addr: + sh_funcs.append(' snprintf(stp_strs[%i], len, " %%s%s[0] (addr)\\n%%s", prefix, tmpStr);\n' % (index, stp_list[index]['name'])) + else: + 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'])) + else: + sh_funcs.append(' tmpStr = %s(&pStruct->%s, extra_indent);\n' % (self._get_sh_func_name(stp_list[index]['type']), stp_list[index]['name'])) + sh_funcs.append(' len = 256+strlen(tmpStr);\n') + sh_funcs.append(' stp_strs[%i] = (char*)malloc(len);\n' % (index)) + if self.no_addr: + sh_funcs.append(' snprintf(stp_strs[%i], len, " %%s%s (addr)\\n%%s", prefix, tmpStr);\n' % (index, stp_list[index]['name'])) + else: + 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'])) + total_strlen_str += 'strlen(stp_strs[%i]) + ' % index + sh_funcs.append(' len = %ssizeof(char)*1024;\n' % (total_strlen_str)) + sh_funcs.append(' str = (char*)malloc(len);\n') + sh_funcs.append(' snprintf(str, len, "') + for m in sorted(self.struct_dict[s]): + (p_out1, p_args1) = self._get_struct_print_formatted(self.struct_dict[s][m]) + p_out += p_out1 + p_args += p_args1 + p_out += '"' + p_args += ");\n" + sh_funcs.append(p_out) + sh_funcs.append(p_args) + if 0 != num_stps: + sh_funcs.append(' for (int32_t stp_index = %i; stp_index >= 0; stp_index--) {\n' % (num_stps-1)) + sh_funcs.append(' if (0 < strlen(stp_strs[stp_index])) {\n') + sh_funcs.append(' strncat(str, stp_strs[stp_index], strlen(stp_strs[stp_index]));\n') + sh_funcs.append(' free(stp_strs[stp_index]);\n') + sh_funcs.append(' }\n') + sh_funcs.append(' }\n') + sh_funcs.append(" return str;\n}\n") + # Add function to dynamically print out unknown struct + sh_funcs.append("char* dynamic_display(const XGL_VOID* pStruct, const char* prefix)\n{\n") + sh_funcs.append(" // Cast to APP_INFO ptr initially just to pull sType off struct\n") + sh_funcs.append(" XGL_STRUCTURE_TYPE sType = ((XGL_APPLICATION_INFO*)pStruct)->sType;\n") + sh_funcs.append(' char indent[100];\n strcpy(indent, " ");\n strcat(indent, prefix);\n') + sh_funcs.append(" switch (sType)\n {\n") + for e in enum_type_dict: + if "_STRUCTURE_TYPE" in e: + for v in sorted(enum_type_dict[e]): + struct_name = v.replace("_STRUCTURE_TYPE", "") + print_func_name = self._get_sh_func_name(struct_name) + # TODO : Hand-coded fixes for some exceptions + if 'XGL_PIPELINE_CB_STATE_CREATE_INFO' in struct_name: + struct_name = 'XGL_PIPELINE_CB_STATE' + elif 'XGL_SEMAPHORE_CREATE_INFO' in struct_name: + struct_name = 'XGL_QUEUE_SEMAPHORE_CREATE_INFO' + print_func_name = self._get_sh_func_name(struct_name) + elif 'XGL_SEMAPHORE_OPEN_INFO' in struct_name: + struct_name = 'XGL_QUEUE_SEMAPHORE_OPEN_INFO' + print_func_name = self._get_sh_func_name(struct_name) + sh_funcs.append(' case %s:\n {\n' % (v)) + sh_funcs.append(' return %s((%s*)pStruct, indent);\n' % (print_func_name, struct_name)) + sh_funcs.append(' }\n') + sh_funcs.append(' break;\n') + sh_funcs.append(" default:\n") + sh_funcs.append(" return NULL;\n") + sh_funcs.append(" }\n") + sh_funcs.append("}") + return "".join(sh_funcs) + + def _generateStringHelperFunctionsCpp(self): + # declare str & tmp str + # declare array of stringstreams for every struct ptr in current struct + # declare array of stringstreams for every non-string element in current struct + # For every struct ptr, it non-Null, then set it's string, else set to NULL str + # For every non-string element, set it's string stream + # create and return final string + sh_funcs = [] + # First generate prototypes for every struct + for s in self.struct_dict: + sh_funcs.append('string %s(const %s* pStruct, const string prefix);' % (self._get_sh_func_name(s), typedef_fwd_dict[s])) + sh_funcs.append('\n') + for s in self.struct_dict: + num_non_enum_elems = [is_type(self.struct_dict[s][elem]['type'], 'enum') for elem in self.struct_dict[s]].count(False) + stp_list = [] # stp == "struct to print" a list of structs for this API call that should be printed as structs + # This isn't great but this pre-pass counts chars in struct members and flags structs w/ pNext + for m in self.struct_dict[s]: + if 'pNext' == self.struct_dict[s][m]['name'] or is_type(self.struct_dict[s][m]['type'], 'struct'): + stp_list.append(self.struct_dict[s][m]) + sh_funcs.append('string %s(const %s* pStruct, const string prefix)\n{' % (self._get_sh_func_name(s), typedef_fwd_dict[s])) + sh_funcs.append(' string final_str;') + sh_funcs.append(' string tmp_str;') + sh_funcs.append(' string extra_indent = " " + prefix;') + sh_funcs.append(' stringstream ss[%u];' % num_non_enum_elems) + num_stps = len(stp_list) + # First generate code for any embedded structs + if 0 < num_stps: + sh_funcs.append(' string stp_strs[%u];' % num_stps) + idx_ss_decl = False # Make sure to only decl this once + for index in range(num_stps): + addr_char = '&' + if stp_list[index]['ptr']: + addr_char = '' + if (stp_list[index]['ptr']): + sh_funcs.append(' if (pStruct->%s) {' % stp_list[index]['name']) + if 'pNext' == stp_list[index]['name']: + sh_funcs.append(' tmp_str = dynamic_display((XGL_VOID*)pStruct->pNext, prefix);') + else: + sh_funcs.append(' tmp_str = %s(pStruct->%s, extra_indent);' % (self._get_sh_func_name(stp_list[index]['type']), stp_list[index]['name'])) + sh_funcs.append(' ss[%u] << %spStruct->%s;' % (index, addr_char, stp_list[index]['name'])) + if self.no_addr: + sh_funcs.append(' stp_strs[%u] = " " + prefix + "%s (addr)\\n" + tmp_str;' % (index, stp_list[index]['name'])) + else: + sh_funcs.append(' stp_strs[%u] = " " + prefix + "%s (" + ss[%u].str() + ")\\n" + tmp_str;' % (index, stp_list[index]['name'], index)) + sh_funcs.append(' ss[%u].str("");' % (index)) + sh_funcs.append(' }') + sh_funcs.append(' else') + sh_funcs.append(' stp_strs[%u] = "";' % index) + elif (stp_list[index]['array']): + sh_funcs.append(' stp_strs[%u] = "";' % index) + if not idx_ss_decl: + sh_funcs.append(' stringstream index_ss;') + idx_ss_decl = True + sh_funcs.append(' for (uint32_t i = 0; i < %s; i++) {' % stp_list[index]['array_size']) + sh_funcs.append(' index_ss.str("");') + sh_funcs.append(' index_ss << i;') + sh_funcs.append(' ss[%u] << %spStruct->%s[i];' % (index, addr_char, stp_list[index]['name'])) + sh_funcs.append(' tmp_str = %s(&pStruct->%s[i], extra_indent);' % (self._get_sh_func_name(stp_list[index]['type']), stp_list[index]['name'])) + if self.no_addr: + sh_funcs.append(' stp_strs[%u] += " " + prefix + "%s[" + index_ss.str() + "] (addr)\\n" + tmp_str;' % (index, stp_list[index]['name'])) + else: + sh_funcs.append(' stp_strs[%u] += " " + prefix + "%s[" + index_ss.str() + "] (" + ss[%u].str() + ")\\n" + tmp_str;' % (index, stp_list[index]['name'], index)) + sh_funcs.append(' ss[%u].str("");' % index) + sh_funcs.append(' }') + else: + sh_funcs.append(' tmp_str = %s(&pStruct->%s, extra_indent);' % (self._get_sh_func_name(stp_list[index]['type']), stp_list[index]['name'])) + sh_funcs.append(' ss[%u] << %spStruct->%s;' % (index, addr_char, stp_list[index]['name'])) + if self.no_addr: + sh_funcs.append(' stp_strs[%u] = " " + prefix + "%s (addr)\\n" + tmp_str;' % (index, stp_list[index]['name'])) + else: + sh_funcs.append(' stp_strs[%u] = " " + prefix + "%s (" + ss[%u].str() + ")\\n" + tmp_str;' % (index, stp_list[index]['name'], index)) + sh_funcs.append(' ss[%u].str("");' % index) + # Now print non-enum data members + index = 0 + final_str = '' + for m in sorted(self.struct_dict[s]): + if not is_type(self.struct_dict[s][m]['type'], 'enum'): + if is_type(self.struct_dict[s][m]['type'], 'struct') and not self.struct_dict[s][m]['ptr']: + if self.no_addr: + sh_funcs.append(' ss[%u].str("addr");' % (index)) + else: + sh_funcs.append(' ss[%u] << &pStruct->%s;' % (index, self.struct_dict[s][m]['name'])) + elif 'BOOL' in self.struct_dict[s][m]['type']: + sh_funcs.append(' ss[%u].str(pStruct->%s ? "TRUE" : "FALSE");' % (index, self.struct_dict[s][m]['name'])) + elif 'UINT8' in self.struct_dict[s][m]['type']: + sh_funcs.append(' ss[%u] << (uint32_t)pStruct->%s;' % (index, self.struct_dict[s][m]['name'])) + else: + (po, pa) = self._get_struct_print_formatted(self.struct_dict[s][m]) + if "addr" in po or self.struct_dict[s][m]['ptr']: + sh_funcs.append(' ss[%u].str("addr");' % (index)) + else: + sh_funcs.append(' ss[%u] << pStruct->%s;' % (index, self.struct_dict[s][m]['name'])) + value_print = 'ss[%u].str()' % index + index += 1 + else: + value_print = 'string_%s(pStruct->%s)' % (self.struct_dict[s][m]['type'], self.struct_dict[s][m]['name']) + final_str += ' + prefix + "%s = " + %s + "\\n"' % (self.struct_dict[s][m]['name'], value_print) + final_str = final_str[3:] # strip off the initial ' + ' + if 0 != num_stps: + final_str += " + %s" % " + ".join(['stp_strs[%u]' % n for n in reversed(range(num_stps))]) + sh_funcs.append(' final_str = %s;' % final_str) + sh_funcs.append(' return final_str;\n}') + # Add function to dynamically print out unknown struct + sh_funcs.append("string dynamic_display(const XGL_VOID* pStruct, const string prefix)\n{") + sh_funcs.append(" // Cast to APP_INFO ptr initially just to pull sType off struct") + sh_funcs.append(" XGL_STRUCTURE_TYPE sType = ((XGL_APPLICATION_INFO*)pStruct)->sType;") + sh_funcs.append(' string indent = " ";') + sh_funcs.append(' indent += prefix;') + sh_funcs.append(" switch (sType)\n {") + for e in enum_type_dict: + if "_STRUCTURE_TYPE" in e: + for v in sorted(enum_type_dict[e]): + struct_name = v.replace("_STRUCTURE_TYPE", "") + print_func_name = self._get_sh_func_name(struct_name) + # TODO : Hand-coded fixes for some exceptions + if 'XGL_PIPELINE_CB_STATE_CREATE_INFO' in struct_name: + struct_name = 'XGL_PIPELINE_CB_STATE' + elif 'XGL_SEMAPHORE_CREATE_INFO' in struct_name: + struct_name = 'XGL_QUEUE_SEMAPHORE_CREATE_INFO' + print_func_name = self._get_sh_func_name(struct_name) + elif 'XGL_SEMAPHORE_OPEN_INFO' in struct_name: + struct_name = 'XGL_QUEUE_SEMAPHORE_OPEN_INFO' + print_func_name = self._get_sh_func_name(struct_name) + sh_funcs.append(' case %s:\n {' % (v)) + sh_funcs.append(' return %s((%s*)pStruct, indent);' % (print_func_name, struct_name)) + sh_funcs.append(' }') + sh_funcs.append(' break;') + sh_funcs.append(" default:") + sh_funcs.append(" return NULL;") + sh_funcs.append(" }") + sh_funcs.append("}") + return "\n".join(sh_funcs) + + def _genStructMemberPrint(self, member, s, array, struct_array): + (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) + extra_indent = "" + if array: + extra_indent = " " + if is_type(self.struct_dict[s][member]['type'], 'struct'): # print struct address for now + struct_array.insert(0, self.struct_dict[s][member]) + elif self.struct_dict[s][member]['ptr']: + # Special case for VOID* named "pNext" + if "VOID" in self.struct_dict[s][member]['type'] and "pNext" == self.struct_dict[s][member]['name']: + struct_array.insert(0, self.struct_dict[s][member]) + return (' %sprintf("%%*s %s", m_indent, ""%s);' % (extra_indent, p_out, p_arg), struct_array) + + def _generateDisplayDefinitions(self, s): + disp_def = [] + struct_array = [] + # Single-line struct print function + disp_def.append("// Output 'structname = struct_address' on a single line") + disp_def.append("void %s::display_single_txt()\n{" % self.get_class_name(s)) + disp_def.append(' printf(" %%*s%s = %%p", m_indent, "", (void*)m_origStructAddr);' % typedef_fwd_dict[s]) + disp_def.append("}\n") + # Private helper function to print struct members + disp_def.append("// Private helper function that displays the members of the wrapped struct") + disp_def.append("void %s::display_struct_members()\n{" % self.get_class_name(s)) + i_declared = False + for member in sorted(self.struct_dict[s]): + # TODO : Need to display each member based on its type + # TODO : Need to handle pNext which are structs, but of XGL_VOID* type + # Can grab struct type off of header of struct pointed to + # TODO : Handle Arrays + if self.struct_dict[s][member]['array']: + # Create for loop to print each element of array + if not i_declared: + disp_def.append(' uint32_t i;') + i_declared = True + disp_def.append(' for (i = 0; i<%s; i++) {' % self.struct_dict[s][member]['array_size']) + (return_str, struct_array) = self._genStructMemberPrint(member, s, True, struct_array) + disp_def.append(return_str) + disp_def.append(' }') + else: + (return_str, struct_array) = self._genStructMemberPrint(member, s, False, struct_array) + disp_def.append(return_str) + disp_def.append("}\n") + i_declared = False + # Basic print function to display struct members + disp_def.append("// Output all struct elements, each on their own line") + disp_def.append("void %s::display_txt()\n{" % self.get_class_name(s)) + disp_def.append(' printf("%%*s%s struct contents at %%p:\\n", m_indent, "", (void*)m_origStructAddr);' % typedef_fwd_dict[s]) + disp_def.append(' this->display_struct_members();') + disp_def.append("}\n") + # Advanced print function to display current struct and contents of any pointed-to structs + disp_def.append("// Output all struct elements, and for any structs pointed to, print complete contents") + disp_def.append("void %s::display_full_txt()\n{" % self.get_class_name(s)) + disp_def.append(' printf("%%*s%s struct contents at %%p:\\n", m_indent, "", (void*)m_origStructAddr);' % typedef_fwd_dict[s]) + disp_def.append(' this->display_struct_members();') + class_num = 0 + # TODO : Need to handle arrays of structs here + for ms in struct_array: + swc_name = "class%s" % str(class_num) + if ms['array']: + if not i_declared: + disp_def.append(' uint32_t i;') + i_declared = True + disp_def.append(' for (i = 0; i<%s; i++) {' % ms['array_size']) + #disp_def.append(" if (m_struct.%s[i]) {" % (ms['name'])) + disp_def.append(" %s %s(&(m_struct.%s[i]));" % (self.get_class_name(ms['type']), swc_name, ms['name'])) + disp_def.append(" %s.set_indent(m_indent + 4);" % (swc_name)) + disp_def.append(" %s.display_full_txt();" % (swc_name)) + #disp_def.append(' }') + disp_def.append(' }') + elif 'pNext' == ms['name']: + # Need some code trickery here + # I'm thinking have a generated function that takes pNext ptr value + # then it checks sType and in large switch statement creates appropriate + # wrapper class type and then prints contents + disp_def.append(" if (m_struct.%s) {" % (ms['name'])) + #disp_def.append(' printf("%*s This is where we would call dynamic print function\\n", m_indent, "");') + disp_def.append(' dynamic_display_full_txt(m_struct.%s, m_indent);' % (ms['name'])) + disp_def.append(" }") + else: + if ms['ptr']: + disp_def.append(" if (m_struct.%s) {" % (ms['name'])) + disp_def.append(" %s %s(m_struct.%s);" % (self.get_class_name(ms['type']), swc_name, ms['name'])) + else: + disp_def.append(" if (&m_struct.%s) {" % (ms['name'])) + disp_def.append(" %s %s(&m_struct.%s);" % (self.get_class_name(ms['type']), swc_name, ms['name'])) + disp_def.append(" %s.set_indent(m_indent + 4);" % (swc_name)) + disp_def.append(" %s.display_full_txt();\n }" % (swc_name)) + class_num += 1 + disp_def.append("}\n") + return "\n".join(disp_def) + + def _generateStringHelperHeader(self): + header = [] + header.append("//#includes, #defines, globals and such...\n") + for f in self.include_headers: + if 'xgl_enum_string_helper' not in f: + header.append("#include <%s>\n" % f) + header.append('#include "xgl_enum_string_helper.h"\n\n// Function Prototypes\n') + header.append("char* dynamic_display(const XGL_VOID* pStruct, const char* prefix);\n") + return "".join(header) + + def _generateStringHelperHeaderCpp(self): + header = [] + header.append("//#includes, #defines, globals and such...\n") + for f in self.include_headers: + if 'xgl_enum_string_helper' not in f: + header.append("#include <%s>\n" % f) + header.append('#include "xgl_enum_string_helper.h"\n') + header.append('using namespace std;\n\n// Function Prototypes\n') + header.append("string dynamic_display(const XGL_VOID* pStruct, const string prefix);\n") + return "".join(header) + + def _generateValidateHelperFunctions(self): + sh_funcs = [] + # We do two passes, first pass just generates prototypes for all the functsions + for s in self.struct_dict: + sh_funcs.append('uint32_t %s(const %s* pStruct);' % (self._get_vh_func_name(s), typedef_fwd_dict[s])) + sh_funcs.append('\n') + for s in self.struct_dict: + sh_funcs.append('uint32_t %s(const %s* pStruct)\n{' % (self._get_vh_func_name(s), typedef_fwd_dict[s])) + for m in sorted(self.struct_dict[s]): + if is_type(self.struct_dict[s][m]['type'], 'enum'): + sh_funcs.append(' if (!validate_%s(pStruct->%s))\n return 0;' % (self.struct_dict[s][m]['type'], self.struct_dict[s][m]['name'])) + sh_funcs.append(" return 1;\n}") + + return "\n".join(sh_funcs) + + def _generateValidateHelperHeader(self): + header = [] + header.append("//#includes, #defines, globals and such...\n") + for f in self.include_headers: + if 'xgl_enum_validate_helper' not in f: + header.append("#include <%s>\n" % f) + header.append('#include "xgl_enum_validate_helper.h"\n\n// Function Prototypes\n') + #header.append("char* dynamic_display(const XGL_VOID* pStruct, const char* prefix);\n") + return "".join(header) + + def _generateHeader(self): + header = [] + header.append("//#includes, #defines, globals and such...\n") + for f in self.include_headers: + header.append("#include <%s>\n" % f) + return "".join(header) + + # Declarations + def _generateConstructorDeclarations(self, s): + constructors = [] + constructors.append(" %s();\n" % self.get_class_name(s)) + constructors.append(" %s(%s* pInStruct);\n" % (self.get_class_name(s), typedef_fwd_dict[s])) + constructors.append(" %s(const %s* pInStruct);\n" % (self.get_class_name(s), typedef_fwd_dict[s])) + return "".join(constructors) + + def _generateDestructorDeclarations(self, s): + return " virtual ~%s();\n" % self.get_class_name(s) + + def _generateDisplayDeclarations(self, s): + return " void display_txt();\n void display_single_txt();\n void display_full_txt();\n" + + def _generateGetSetDeclarations(self, s): + get_set = [] + get_set.append(" void set_indent(uint32_t indent) { m_indent = indent; }\n") + for member in sorted(self.struct_dict[s]): + # TODO : Skipping array set/get funcs for now + if self.struct_dict[s][member]['array']: + continue + 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'])) + if not self.struct_dict[s][member]['const']: + 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'])) + return "".join(get_set) + + def _generatePrivateMembers(self, s): + priv = [] + priv.append("\nprivate:\n") + priv.append(" %s m_struct;\n" % typedef_fwd_dict[s]) + priv.append(" const %s* m_origStructAddr;\n" % typedef_fwd_dict[s]) + priv.append(" uint32_t m_indent;\n") + priv.append(" const char m_dummy_prefix;\n") + priv.append(" void display_struct_members();\n") + return "".join(priv) + + def _generateClassDeclaration(self): + class_decl = [] + for s in self.struct_dict: + class_decl.append("\n//class declaration") + class_decl.append("class %s\n{\npublic:" % self.get_class_name(s)) + class_decl.append(self._generateConstructorDeclarations(s)) + class_decl.append(self._generateDestructorDeclarations(s)) + class_decl.append(self._generateDisplayDeclarations(s)) + class_decl.append(self._generateGetSetDeclarations(s)) + class_decl.append(self._generatePrivateMembers(s)) + class_decl.append("};\n") + return "\n".join(class_decl) + + def _generateFooter(self): + return "\n//any footer info for class\n" + +class EnumCodeGen: + 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): + self.et_dict = enum_type_dict + self.ev_dict = enum_val_dict + self.tf_dict = typedef_fwd_dict + self.in_file = in_file + self.out_sh_file = out_sh_file + self.eshfg = CommonFileGen(self.out_sh_file) + self.out_vh_file = out_vh_file + self.evhfg = CommonFileGen(self.out_vh_file) + + def generateStringHelper(self): + self.eshfg.setHeader(self._generateSHHeader()) + self.eshfg.setBody(self._generateSHBody()) + self.eshfg.generate() + + def generateEnumValidate(self): + self.evhfg.setHeader(self._generateSHHeader()) + self.evhfg.setBody(self._generateVHBody()) + self.evhfg.generate() + + def _generateVHBody(self): + body = [] + for bet in self.et_dict: + fet = self.tf_dict[bet] + body.append("static uint32_t validate_%s(%s input_value)\n{\n switch ((%s)input_value)\n {" % (fet, fet, fet)) + for e in sorted(self.et_dict[bet]): + if (self.ev_dict[e]['unique']): + body.append(' case %s:' % (e)) + body.append(' return 1;\n default:\n return 0;\n }\n}\n\n') + return "\n".join(body) + + def _generateSHBody(self): + body = [] +# with open(self.out_file, "a") as hf: + # bet == base_enum_type, fet == final_enum_type + for bet in self.et_dict: + fet = self.tf_dict[bet] + body.append("static inline const char* string_%s(%s input_value)\n{\n switch ((%s)input_value)\n {\n" % (fet, fet, fet)) + for e in sorted(self.et_dict[bet]): + if (self.ev_dict[e]['unique']): + body.append(' case %s:\n return "%s";' % (e, e)) + body.append(' default:\n return "Unhandled %s";\n }\n}\n\n' % (fet)) + return "\n".join(body) + + def _generateSHHeader(self): + return "#pragma once\n\n#include <%s>\n\n" % self.in_file + + +class CMakeGen: + def __init__(self, struct_wrapper=None, out_dir=None): + self.sw = struct_wrapper + self.include_headers = [] + self.add_lib_file_list = self.sw.get_file_list() + self.out_dir = out_dir + self.out_file = os.path.join(self.out_dir, "CMakeLists.txt") + self.cmg = CommonFileGen(self.out_file) + + def generate(self): + self.cmg.setBody(self._generateBody()) + self.cmg.generate() + + def _generateBody(self): + body = [] + body.append("project(%s)" % os.path.basename(self.out_dir)) + body.append("cmake_minimum_required(VERSION 2.8)\n") + body.append("add_library(${PROJECT_NAME} %s)\n" % " ".join(self.add_lib_file_list)) + body.append('set(COMPILE_FLAGS "-fpermissive")') + body.append('set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${COMPILE_FLAGS}")\n') + body.append("include_directories(${SRC_DIR}/thirdparty/${GEN_API}/inc/)\n") + body.append("target_include_directories (%s PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})\n" % os.path.basename(self.out_dir)) + return "\n".join(body) + +class GraphVizGen: + def __init__(self, struct_dict, prefix, out_dir): + self.struct_dict = struct_dict + self.api = prefix + self.out_file = os.path.join(out_dir, self.api+"_struct_graphviz_helper.h") + self.gvg = CommonFileGen(self.out_file) + + def generate(self): + self.gvg.setCopyright("//This is the copyright\n") + self.gvg.setHeader(self._generateHeader()) + self.gvg.setBody(self._generateBody()) + #self.gvg.setFooter('}') + self.gvg.generate() + + def set_include_headers(self, include_headers): + self.include_headers = include_headers + + def _generateHeader(self): + header = [] + header.append("//#includes, #defines, globals and such...\n") + for f in self.include_headers: + if 'xgl_enum_string_helper' not in f: + header.append("#include <%s>\n" % f) + #header.append('#include "xgl_enum_string_helper.h"\n\n// Function Prototypes\n') + header.append("\nchar* dynamic_gv_display(const XGL_VOID* pStruct, const char* prefix);\n") + return "".join(header) + + def _get_gv_func_name(self, struct): + return "%s_gv_print_%s" % (self.api, struct.lower().strip("_")) + + # Return elements to create formatted string for given struct member + 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=""): + struct_op = "->" + pre_var_name = '"%s "' % struct_member['full_type'] + if not struct_ptr: + struct_op = "." + member_name = struct_member['name'] + print_type = "p" + cast_type = "" + member_post = "" + array_index = "" + member_print_post = "" + if struct_member['array'] and 'CHAR' in struct_member['type']: # just print char array as string + print_type = "s" + print_array = False + elif struct_member['array'] and not print_array: + # Just print base address of array when not full print_array + cast_type = "(void*)" + elif is_type(struct_member['type'], 'enum'): + if struct_member['ptr']: + struct_var_name = "*" + struct_var_name + cast_type = "string_%s" % struct_member['type'] + print_type = "s" + elif is_type(struct_member['type'], 'struct'): # print struct address for now + cast_type = "(void*)" + if not struct_member['ptr']: + cast_type = "(void*)&" + elif 'BOOL' in struct_member['type']: + print_type = "s" + member_post = ' ? "TRUE" : "FALSE"' + elif 'FLOAT' in struct_member['type']: + print_type = "f" + elif 'UINT64' in struct_member['type']: + print_type = "lu" + elif 'UINT8' in struct_member['type']: + print_type = "hu" + elif '_SIZE' in struct_member['type']: + print_type = "zu" + elif True in [ui_str in struct_member['type'] for ui_str in ['UINT', '_FLAGS', '_SAMPLE_MASK']]: + print_type = "u" + elif 'INT' in struct_member['type']: + print_type = "i" + elif struct_member['ptr']: + pass + else: + #print("Unhandled struct type: %s" % struct_member['type']) + cast_type = "(void*)" + if print_array and struct_member['array']: + member_print_post = "[%u]" + array_index = " i," + member_post = "[i]" + print_out = "%%s%s%s%%%s%s" % (member_name, member_print_post, port_label, print_type, postfix) # section of print that goes inside of quotes + 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 + return (print_out, print_arg) + + def _generateBody(self): + gv_funcs = [] + array_func_list = [] # structs for which we'll generate an array version of their print function + array_func_list.append('xgl_descriptor_slot_info') + # For first pass, generate prototype + for s in self.struct_dict: + gv_funcs.append('char* %s(const %s* pStruct, const char* myNodeName);\n' % (self._get_gv_func_name(s), typedef_fwd_dict[s])) + if s.lower().strip("_") in array_func_list: + 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])) + gv_funcs.append('\n') + for s in self.struct_dict: + p_out = "" + p_args = "" + stp_list = [] # stp == "struct to print" a list of structs for this API call that should be printed as structs + # the fields below are a super-hacky way for now to get port labels into GV output, TODO : Clean this up! + pl_dict = {} + struct_num = 0 + # This isn't great but this pre-pass counts chars in struct members and flags structs w/ pNext + for m in sorted(self.struct_dict[s]): + if 'pNext' == self.struct_dict[s][m]['name'] or is_type(self.struct_dict[s][m]['type'], 'struct'): + stp_list.append(self.struct_dict[s][m]) + if 'pNext' == self.struct_dict[s][m]['name']: + pl_dict[m] = ' PORT=\\"pNext\\"' + else: + pl_dict[m] = ' PORT=\\"struct%i\\"' % struct_num + struct_num += 1 + 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])) + num_stps = len(stp_list); + total_strlen_str = '' + if 0 != num_stps: + gv_funcs.append(" char* tmpStr;\n") + gv_funcs.append(" char nodeName[100];\n") + gv_funcs.append(' char* stp_strs[%i];\n' % num_stps) + for index in range(num_stps): + if (stp_list[index]['ptr']): + if 'pDescriptorInfo' == stp_list[index]['name']: + gv_funcs.append(' if (pStruct->pDescriptorInfo && (0 != pStruct->descriptorCount)) {\n') + else: + gv_funcs.append(' if (pStruct->%s) {\n' % stp_list[index]['name']) + if 'pNext' == stp_list[index]['name']: + gv_funcs.append(' sprintf(nodeName, "pNext_%p", (void*)pStruct->pNext);\n') + gv_funcs.append(' tmpStr = dynamic_gv_display((XGL_VOID*)pStruct->pNext, nodeName);\n') + gv_funcs.append(' stp_strs[%i] = (char*)malloc(256+strlen(tmpStr)+strlen(nodeName)+strlen(myNodeName));\n' % index) + gv_funcs.append(' sprintf(stp_strs[%i], "%%s\\n\\"%%s\\":pNext -> \\"%%s\\" [];\\n", tmpStr, myNodeName, nodeName);\n' % index) + gv_funcs.append(' free(tmpStr);\n') + else: + gv_funcs.append(' sprintf(nodeName, "%s_%%p", (void*)pStruct->%s);\n' % (stp_list[index]['name'], stp_list[index]['name'])) + if 'pDescriptorInfo' == stp_list[index]['name']: + 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'])) + else: + gv_funcs.append(' tmpStr = %s(pStruct->%s, nodeName);\n' % (self._get_gv_func_name(stp_list[index]['type']), stp_list[index]['name'])) + gv_funcs.append(' stp_strs[%i] = (char*)malloc(256+strlen(tmpStr)+strlen(nodeName)+strlen(myNodeName));\n' % (index)) + gv_funcs.append(' sprintf(stp_strs[%i], "%%s\\n\\"%%s\\":struct%i -> \\"%%s\\" [];\\n", tmpStr, myNodeName, nodeName);\n' % (index, index)) + gv_funcs.append(' }\n') + gv_funcs.append(" else\n stp_strs[%i] = \"\";\n" % (index)) + elif stp_list[index]['array']: # TODO : For now just printing first element of array + gv_funcs.append(' sprintf(nodeName, "%s_%%p", (void*)&pStruct->%s[0]);\n' % (stp_list[index]['name'], stp_list[index]['name'])) + gv_funcs.append(' tmpStr = %s(&pStruct->%s[0], nodeName);\n' % (self._get_gv_func_name(stp_list[index]['type']), stp_list[index]['name'])) + gv_funcs.append(' stp_strs[%i] = (char*)malloc(256+strlen(tmpStr)+strlen(nodeName)+strlen(myNodeName));\n' % (index)) + gv_funcs.append(' sprintf(stp_strs[%i], "%%s\\n\\"%%s\\":struct%i -> \\"%%s\\" [];\\n", tmpStr, myNodeName, nodeName);\n' % (index, index)) + else: + gv_funcs.append(' sprintf(nodeName, "%s_%%p", (void*)&pStruct->%s);\n' % (stp_list[index]['name'], stp_list[index]['name'])) + gv_funcs.append(' tmpStr = %s(&pStruct->%s, nodeName);\n' % (self._get_gv_func_name(stp_list[index]['type']), stp_list[index]['name'])) + gv_funcs.append(' stp_strs[%i] = (char*)malloc(256+strlen(tmpStr)+strlen(nodeName)+strlen(myNodeName));\n' % (index)) + gv_funcs.append(' sprintf(stp_strs[%i], "%%s\\n\\"%%s\\":struct%i -> \\"%%s\\" [];\\n", tmpStr, myNodeName, nodeName);\n' % (index, index)) + total_strlen_str += 'strlen(stp_strs[%i]) + ' % index + gv_funcs.append(' str = (char*)malloc(%ssizeof(char)*2048);\n' % (total_strlen_str)) + gv_funcs.append(' sprintf(str, "\\"%s\\" [\\nlabel = <') + p_args = ", myNodeName, myNodeName, pStruct" + for m in sorted(self.struct_dict[s]): + plabel = "" + if m in pl_dict: + plabel = pl_dict[m] + (p_out1, p_args1) = self._get_struct_gv_print_formatted(self.struct_dict[s][m], port_label=plabel) + p_out += p_out1 + p_args += p_args1 + p_out += '
%s (%p)
>\\n];\\n\\n"' + p_args += ");\n" + gv_funcs.append(p_out) + gv_funcs.append(p_args) + if 0 != num_stps: + gv_funcs.append(' for (int32_t stp_index = %i; stp_index >= 0; stp_index--) {\n' % (num_stps-1)) + gv_funcs.append(' if (0 < strlen(stp_strs[stp_index])) {\n') + gv_funcs.append(' strncat(str, stp_strs[stp_index], strlen(stp_strs[stp_index]));\n') + gv_funcs.append(' free(stp_strs[stp_index]);\n') + gv_funcs.append(' }\n') + gv_funcs.append(' }\n') + gv_funcs.append(" return str;\n}\n") + if s.lower().strip("_") in array_func_list: + 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])) + gv_funcs.append(' str = (char*)malloc(sizeof(char)*1024*count);\n') + gv_funcs.append(' sprintf(str, "\\"%s\\" [\\nlabel = <", myNodeName, myNodeName, pStruct);\n') + gv_funcs.append(' for (uint32_t i=0; i < count; i++) {\n') + gv_funcs.append(' sprintf(tmpStr, "'); + p_args = "" + p_out = "" + for m in sorted(self.struct_dict[s]): + if 2 == m: # TODO : Hard-coded hack to skip last element of union for xgl_descriptor_slot_info struct + continue + plabel = "" + (p_out1, p_args1) = self._get_struct_gv_print_formatted(self.struct_dict[s][m], port_label=plabel) + 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) + p_out1 = '%s' % (p_out1[:-5]) + p_args1 += ', i, i' + p_out += p_out1 + p_args += p_args1 + p_out += '"' + p_args += ");\n" + p_args = p_args.replace('->', '[i].') + gv_funcs.append(p_out); + gv_funcs.append(p_args); + gv_funcs.append(' strncat(str, tmpStr, strlen(tmpStr));\n') + gv_funcs.append(' }\n') + gv_funcs.append(' strncat(str, "
%s (%p)
%%u
>\\n];\\n\\n", 20);\n') + # TODO : Another hard-coded hack. Tie these slots to "magical" DS0_MEMORY slots that should appear separately + gv_funcs.append(' for (uint32_t i=0; i < count; i++) {\n') + gv_funcs.append(' if (XGL_SLOT_UNUSED != pStruct[i].slotObjectType) {\n') + gv_funcs.append(' sprintf(tmpStr, "\\"%s\\":slot%u -> \\"DS0_MEMORY\\":slot%u [];\\n", myNodeName, i, i);\n') + gv_funcs.append(' strncat(str, tmpStr, strlen(tmpStr));\n') + gv_funcs.append(' }\n') + gv_funcs.append(' }\n') + gv_funcs.append(' return str;\n}\n') + # Add function to dynamically print out unknown struct + gv_funcs.append("char* dynamic_gv_display(const XGL_VOID* pStruct, const char* nodeName)\n{\n") + gv_funcs.append(" // Cast to APP_INFO ptr initially just to pull sType off struct\n") + gv_funcs.append(" XGL_STRUCTURE_TYPE sType = ((XGL_APPLICATION_INFO*)pStruct)->sType;\n") + gv_funcs.append(" switch (sType)\n {\n") + for e in enum_type_dict: + if "_STRUCTURE_TYPE" in e: + for v in sorted(enum_type_dict[e]): + struct_name = v.replace("_STRUCTURE_TYPE", "") + print_func_name = self._get_gv_func_name(struct_name) + # TODO : Hand-coded fixes for some exceptions + if 'XGL_PIPELINE_CB_STATE_CREATE_INFO' in struct_name: + struct_name = 'XGL_PIPELINE_CB_STATE' + elif 'XGL_SEMAPHORE_CREATE_INFO' in struct_name: + struct_name = 'XGL_QUEUE_SEMAPHORE_CREATE_INFO' + print_func_name = self._get_gv_func_name(struct_name) + elif 'XGL_SEMAPHORE_OPEN_INFO' in struct_name: + struct_name = 'XGL_QUEUE_SEMAPHORE_OPEN_INFO' + print_func_name = self._get_gv_func_name(struct_name) + gv_funcs.append(' case %s:\n' % (v)) + gv_funcs.append(' return %s((%s*)pStruct, nodeName);\n' % (print_func_name, struct_name)) + #gv_funcs.append(' }\n') + #gv_funcs.append(' break;\n') + gv_funcs.append(" default:\n") + gv_funcs.append(" return NULL;\n") + gv_funcs.append(" }\n") + gv_funcs.append("}") + return "".join(gv_funcs) + + + + + +# def _generateHeader(self): +# hdr = [] +# hdr.append('digraph g {\ngraph [\nrankdir = "LR"\n];') +# hdr.append('node [\nfontsize = "16"\nshape = "plaintext"\n];') +# hdr.append('edge [\n];\n') +# return "\n".join(hdr) +# +# def _generateBody(self): +# body = [] +# for s in self.struc_dict: +# field_num = 1 +# body.append('"%s" [\nlabel = <' % (s, typedef_fwd_dict[s])) +# for m in sorted(self.struc_dict[s]): +# body.append('' % (field_num, self.struc_dict[s][m]['full_type'], field_num+1, self.struc_dict[s][m]['name'])) +# field_num += 2 +# body.append('
%s
%s%s
>\n];\n') +# return "".join(body) + +def main(argv=None): + opts = handle_args() + # Parse input file and fill out global dicts + hfp = HeaderFileParser(opts.input_file) + hfp.parse() + # TODO : Don't want these to be global, see note at top about wrapper classes + global enum_val_dict + global enum_type_dict + global struct_dict + global typedef_fwd_dict + global typedef_rev_dict + global types_dict + enum_val_dict = hfp.get_enum_val_dict() + enum_type_dict = hfp.get_enum_type_dict() + struct_dict = hfp.get_struct_dict() + # TODO : Would like to validate struct data here to verify that all of the bools for struct members are correct at this point + typedef_fwd_dict = hfp.get_typedef_fwd_dict() + typedef_rev_dict = hfp.get_typedef_rev_dict() + types_dict = hfp.get_types_dict() + #print(enum_val_dict) + #print(typedef_dict) + #print(struct_dict) + if (opts.abs_out_dir is not None): + enum_sh_filename = os.path.join(opts.abs_out_dir, os.path.basename(opts.input_file).strip(".h")+"_enum_string_helper.h") + else: + enum_sh_filename = os.path.join(os.getcwd(), opts.rel_out_dir, os.path.basename(opts.input_file).strip(".h")+"_enum_string_helper.h") + enum_sh_filename = os.path.abspath(enum_sh_filename) + if not os.path.exists(os.path.dirname(enum_sh_filename)): + print("Creating output dir %s" % os.path.dirname(enum_sh_filename)) + os.mkdir(os.path.dirname(enum_sh_filename)) + if opts.gen_enum_string_helper: + print("Generating enum string helper to %s" % enum_sh_filename) + enum_vh_filename = os.path.join(os.path.dirname(enum_sh_filename), os.path.basename(opts.input_file).strip(".h")+"_enum_validate_helper.h") + print("Generating enum validate helper to %s" % enum_vh_filename) + eg = EnumCodeGen(enum_type_dict, enum_val_dict, typedef_fwd_dict, os.path.basename(opts.input_file), enum_sh_filename, enum_vh_filename) + eg.generateStringHelper() + eg.generateEnumValidate() + #for struct in struct_dict: + #print(struct) + if opts.gen_struct_wrappers: + sw = StructWrapperGen(struct_dict, os.path.basename(opts.input_file).strip(".h"), os.path.dirname(enum_sh_filename)) + #print(sw.get_class_name(struct)) + sw.set_include_headers([os.path.basename(opts.input_file),os.path.basename(enum_sh_filename),"stdint.h","stdio.h","stdlib.h"]) + print("Generating struct wrapper header to %s" % sw.header_filename) + sw.generateHeader() + print("Generating struct wrapper class to %s" % sw.class_filename) + sw.generateBody() + sw.generateStringHelper() + sw.generateValidateHelper() + # Generate a 2nd helper file that excludes addrs + sw.set_no_addr(True) + sw.generateStringHelper() + sw.set_no_addr(False) + 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"]) + sw.generateStringHelperCpp() + sw.set_no_addr(True) + sw.generateStringHelperCpp() + if opts.gen_cmake: + cmg = CMakeGen(sw, os.path.dirname(enum_sh_filename)) + cmg.generate() + if opts.gen_graphviz: + gv = GraphVizGen(struct_dict, os.path.basename(opts.input_file).strip(".h"), os.path.dirname(enum_sh_filename)) + gv.set_include_headers([os.path.basename(opts.input_file),os.path.basename(enum_sh_filename),"stdint.h","stdio.h","stdlib.h"]) + gv.generate() + print("DONE!") + #print(typedef_rev_dict) + #print(types_dict) + #recreate_structs() + +if __name__ == "__main__": + sys.exit(main())