Best Python code snippet using tempest_python
validation_layer_generator.py
Source:validation_layer_generator.py  
1#!/usr/bin/python3 -i2#3# Copyright (c) 2017 The Khronos Group Inc.4# Copyright (c) 2017 Valve Corporation5# Copyright (c) 2017 LunarG, Inc.6#7# SPDX-License-Identifier: Apache-2.08#9# Licensed under the Apache License, Version 2.0 (the "License");10# you may not use this file except in compliance with the License.11# You may obtain a copy of the License at12#13#     http://www.apache.org/licenses/LICENSE-2.014#15# Unless required by applicable law or agreed to in writing, software16# distributed under the License is distributed on an "AS IS" BASIS,17# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.18# See the License for the specific language governing permissions and19# limitations under the License.20#21# Author: Mark Young <marky@lunarg.com>22import re23from automatic_source_generator import (AutomaticSourceOutputGenerator,24                                        undecorate)25from generator import write26# The following commands have a manually defined component to them.27VALID_USAGE_MANUALLY_DEFINED = set((28    'xrCreateInstance',29    'xrDestroyInstance',30    'xrCreateSession',31    # We manually implement some of the XR_EXT_debug_utils entry-points so that we32    # can return validation messages to known debug utils messengers33    'xrSetDebugUtilsObjectNameEXT',34    'xrCreateDebugUtilsMessengerEXT',35    'xrDestroyDebugUtilsMessengerEXT',36    'xrSessionBeginDebugUtilsLabelRegionEXT',37    'xrSessionEndDebugUtilsLabelRegionEXT',38    'xrSessionInsertDebugUtilsLabelEXT',39))40# ValidationSourceOutputGenerator - subclass of AutomaticSourceOutputGenerator.41class ValidationSourceOutputGenerator(AutomaticSourceOutputGenerator):42    """Generate core validation layer source using XML element attributes from registry"""43    # Override the base class header warning so the comment indicates this file.44    #   self            the ValidationSourceOutputGenerator object45    def outputGeneratedHeaderWarning(self):46        generated_warning = '// *********** THIS FILE IS GENERATED - DO NOT EDIT ***********\n'47        generated_warning += '//     See validation_layer_generator.py for modifications\n'48        generated_warning += '// ************************************************************\n'49        write(generated_warning, file=self.outFile)50    # Call the base class to properly begin the file, and then add51    # the file-specific header information.52    #   self            the ValidationSourceOutputGenerator object53    #   gen_opts        the ValidationSourceGeneratorOptions object54    def beginFile(self, genOpts):55        AutomaticSourceOutputGenerator.beginFile(self, genOpts)56        preamble = ''57        if self.genOpts.filename == 'xr_generated_core_validation.hpp':58            preamble += '#pragma once\n'59            preamble += '#include "xr_generated_dispatch_table.h"\n'60            preamble += '#include "validation_utils.h"\n'61            preamble += '#include "api_layer_platform_defines.h"\n'62            preamble += '#include "xr_dependencies.h"\n'63            preamble += '#include <openxr/openxr.h>\n'64            preamble += '#include <openxr/openxr_platform.h>\n\n'65            preamble += '#include <vector>\n'66            preamble += '#include <string>\n'67            preamble += '#include <unordered_map>\n'68            preamble += '#include <thread>\n'69            preamble += '#include <mutex>\n\n'70        elif self.genOpts.filename == 'xr_generated_core_validation.cpp':71            preamble += '#include "xr_generated_core_validation.hpp"\n'72            preamble += '\n'73            preamble += '#include "api_layer_platform_defines.h"\n'74            preamble += '#include "hex_and_handles.h"\n'75            preamble += '#include "validation_utils.h"\n'76            preamble += '#include "xr_dependencies.h"\n'77            preamble += '#include "xr_generated_dispatch_table.h"\n'78            preamble += '\n'79            preamble += '#include "api_layer_platform_defines.h"\n'80            preamble += '#include "xr_dependencies.h"\n'81            preamble += '#include <openxr/openxr.h>\n'82            preamble += '#include <openxr/openxr_platform.h>\n\n'83            preamble += '#include <algorithm>\n'84            preamble += '#include <cstring>\n'85            preamble += '#include <memory>\n'86            preamble += '#include <sstream>\n'87            preamble += '#include <string>\n'88            preamble += '#include <unordered_map>\n'89            preamble += '#include <utility>\n'90            preamble += '#include <vector>\n'91            preamble += '\n'92        write(preamble, file=self.outFile)93    # Write out all the information for the appropriate file,94    # and then call down to the base class to wrap everything up.95    #   self            the ValidationSourceOutputGenerator object96    def endFile(self):97        file_data = ''98        if self.genOpts.filename == 'xr_generated_core_validation.hpp':99            file_data += self.outputValidationHeaderInfo()100        elif self.genOpts.filename == 'xr_generated_core_validation.cpp':101            file_data += self.outputCommonTypesForValidation()102            file_data += self.outputValidationSourceFuncs()103        write(file_data, file=self.outFile)104        # Finish processing in superclass105        AutomaticSourceOutputGenerator.endFile(self)106    def makeInfoName(self, handle_type=None, handle_type_name=None):107        if not handle_type_name:108            handle_type_name = handle_type.name109        base_handle_name = undecorate(handle_type_name)110        return 'g_%s_info' % base_handle_name111    def outputInfoMapDeclarations(self, extern):112        lines = []113        extern_keyword = 'extern ' if extern else ''114        for handle in self.api_handles:115            handle_name = handle.name116            if handle.protect_value:117                lines.append('#if %s' % handle.protect_string)118            if handle.name == 'XrInstance':119                info_type = "InstanceHandleInfo"120            else:121                info_type = 'HandleInfo<%s>' % handle_name122            lines.append('%s%s %s;' % (extern_keyword,123                                       info_type, self.makeInfoName(handle)))124            if handle.protect_value:125                lines.append('#endif // %s' % handle.protect_string)126        return '\n'.join(lines)127    # Write out common internal types for validation128    #   self            the ValidationSourceOutputGenerator object129    def outputCommonTypesForValidation(self):130        common_validation_types = ''131        common_validation_types += '// Structure used for indicating status of \'flags\' test.\n'132        common_validation_types += 'enum ValidateXrFlagsResult {\n'133        common_validation_types += '    VALIDATE_XR_FLAGS_ZERO,\n'134        common_validation_types += '    VALIDATE_XR_FLAGS_INVALID,\n'135        common_validation_types += '    VALIDATE_XR_FLAGS_SUCCESS,\n'136        common_validation_types += '};\n\n'137        return common_validation_types138    # Generate C++ structures and maps used for validating the states identified139    # in the specification.140    #   self            the ValidationSourceOutputGenerator object141    def outputValidationStateCheckStructs(self):142        validation_state_checks = '// Structure used for state validation.\n'143        active_structures = dict()144        for cur_state in self.api_states:145            type_name = '%s' % cur_state.type146            cur_list = []147            if active_structures.get(type_name) is not None:148                cur_list = active_structures.get(type_name)149            cur_list.append(cur_state.variable)150            active_structures[type_name] = cur_list151        for type_name, variable_list in active_structures.items():152            validation_state_checks += 'struct %sValidationStates {\n' % type_name153            for variable in variable_list:154                validation_state_checks += '    bool %s;\n' % variable155            validation_state_checks += '};\n'156            validation_state_checks += 'std::unordered_map<%s, %sValidationStates*> g_%s_valid_states;\n' % (157                type_name, type_name, undecorate(type_name))158        validation_state_checks += '\n'159        return validation_state_checks160    # Generate C++ structure and utility function prototypes for validating161    # the 'next' chains in structures.162    #   self            the ValidationSourceOutputGenerator object163    def outputValidationSourceNextChainProtos(self):164        next_chain_info = ''165        next_chain_info += '// Result return value for next chain validation\n'166        next_chain_info += 'enum NextChainResult {\n'167        next_chain_info += '    NEXT_CHAIN_RESULT_VALID = 0,\n'168        next_chain_info += '    NEXT_CHAIN_RESULT_ERROR = -1,\n'169        next_chain_info += '    NEXT_CHAIN_RESULT_DUPLICATE_STRUCT = -2,\n'170        next_chain_info += '};\n\n'171        next_chain_info += '// Prototype for validateNextChain command (it uses the validate structure commands so add it after\n'172        next_chain_info += 'NextChainResult ValidateNextChain(GenValidUsageXrInstanceInfo *instance_info,\n'173        next_chain_info += '                                  const std::string &command_name,\n'174        next_chain_info += '                                  std::vector<GenValidUsageXrObjectInfo>& objects_info,\n'175        next_chain_info += '                                  const void* next,\n'176        next_chain_info += '                                  std::vector<XrStructureType>& valid_ext_structs,\n'177        next_chain_info += '                                  std::vector<XrStructureType>& encountered_structs,\n'178        next_chain_info += '                                  std::vector<XrStructureType>& duplicate_structs);\n\n'179        return next_chain_info180    # Generate C++ enum and utility function prototypes for validating181    # the flags in structures.182    #   self            the ValidationSourceOutputGenerator object183    def outputValidationSourceFlagBitValues(self):184        flag_value_validate = ''185        for flag_tuple in self.api_flags:186            if flag_tuple.protect_value:187                flag_value_validate += '#if %s\n' % flag_tuple.protect_string188            flag_value_validate += '// Function to validate %s flags\n' % flag_tuple.name189            flag_value_validate += 'ValidateXrFlagsResult ValidateXr%s(const %s value) {\n' % (190                flag_tuple.name[2:], flag_tuple.type)191            # We need to return a value indicating that the value is zero because in some192            # circumstances, 0 is ok.  However, in other cases, 0 is disallowed.  So, leave193            # it up to the calling function to decide what is correct.194            flag_value_validate += '    if (0 == value) {\n'195            flag_value_validate += '        return VALIDATE_XR_FLAGS_ZERO;\n'196            flag_value_validate += '    }\n'197            # If the flag has no values defined for this flag, then anything other than198            # zero generates an error.199            if flag_tuple.valid_flags is None:200                flag_value_validate += '    return VALIDATE_XR_FLAGS_INVALID;\n'201            else:202                # This flag has values set.  So, check (and remove) each valid value.  Once that's done203                # anything left over would be invalid.204                flag_value_validate += '    %s int_value = value;\n' % flag_tuple.type205                for mask_tuple in self.api_bitmasks:206                    if mask_tuple.name == flag_tuple.valid_flags:207                        for cur_value in mask_tuple.values:208                            if cur_value.protect_value and flag_tuple.protect_value != cur_value.protect_value:209                                flag_value_validate += '#if %s\n' % cur_value.protect_string210                            flag_value_validate += '    if ((int_value & %s) != 0) {\n' % cur_value.name211                            flag_value_validate += '        // Clear the value %s since it is valid\n' % cur_value.name212                            flag_value_validate += '        int_value &= ~%s;\n' % cur_value.name213                            flag_value_validate += '    }\n'214                            if cur_value.protect_value and flag_tuple.protect_value != cur_value.protect_value:215                                flag_value_validate += '#endif // %s\n' % cur_value.protect_string216                        break217                flag_value_validate += '    if (int_value != 0) {\n'218                flag_value_validate += '        // Something is left, it must be invalid\n'219                flag_value_validate += '        return VALIDATE_XR_FLAGS_INVALID;\n'220                flag_value_validate += '    }\n'221                flag_value_validate += '    return VALIDATE_XR_FLAGS_SUCCESS;\n'222            flag_value_validate += '}\n\n'223            if flag_tuple.protect_value:224                flag_value_validate += '#endif // %s\n' % flag_tuple.protect_string225        return flag_value_validate226    # Generate C++ functions for validating enums.227    #   self            the ValidationSourceOutputGenerator object228    def outputValidationSourceEnumValues(self):229        enum_value_validate = ''230        for enum_tuple in self.api_enums:231            if enum_tuple.protect_value:232                enum_value_validate += '#if %s\n' % enum_tuple.protect_string233            enum_value_validate += '// Function to validate %s enum\n' % enum_tuple.name234            enum_value_validate += 'bool ValidateXrEnum(GenValidUsageXrInstanceInfo *instance_info,\n'235            enum_value_validate += '                    const std::string &command_name,\n'236            enum_value_validate += '                    const std::string &validation_name,\n'237            enum_value_validate += '                    const std::string &item_name,\n'238            enum_value_validate += '                    std::vector<GenValidUsageXrObjectInfo>& objects_info,\n'239            enum_value_validate += '                    const %s value) {\n' % enum_tuple.name240            indent = 1241            enum_value_validate += self.writeIndent(indent)242            enum_value_validate += '(void)instance_info;  // quiet warnings\n'243            enum_value_validate += self.writeIndent(indent)244            enum_value_validate += '(void)command_name;  // quiet warnings\n'245            enum_value_validate += self.writeIndent(indent)246            enum_value_validate += '(void)validation_name;  // quiet warnings\n'247            enum_value_validate += self.writeIndent(indent)248            enum_value_validate += '(void)item_name;  // quiet warnings\n'249            enum_value_validate += self.writeIndent(indent)250            enum_value_validate += '(void)objects_info;  // quiet warnings\n'251            checked_extension = ''252            if enum_tuple.ext_name and not self.isCoreExtensionName(enum_tuple.ext_name):253                checked_extension = enum_tuple.ext_name254                enum_value_validate += self.writeIndent(indent)255                enum_value_validate += '// Enum requires extension %s, so check that it is enabled\n' % enum_tuple.ext_name256                enum_value_validate += self.writeIndent(indent)257                enum_value_validate += 'if (nullptr != instance_info && !ExtensionEnabled(instance_info->enabled_extensions, "%s")) {\n' % enum_tuple.ext_name258                indent += 1259                enum_value_validate += self.writeIndent(indent)260                enum_value_validate += 'std::string vuid = "VUID-";\n'261                enum_value_validate += self.writeIndent(indent)262                enum_value_validate += 'vuid += validation_name;\n'263                enum_value_validate += self.writeIndent(indent)264                enum_value_validate += 'vuid += "-";\n'265                enum_value_validate += self.writeIndent(indent)266                enum_value_validate += 'vuid += item_name;\n'267                enum_value_validate += self.writeIndent(indent)268                enum_value_validate += 'vuid += "-parameter";\n'269                enum_value_validate += self.writeIndent(indent)270                enum_value_validate += 'std::string error_str = "%s requires extension ";\n' % enum_tuple.name271                enum_value_validate += self.writeIndent(indent)272                enum_value_validate += 'error_str += " \\"%s\\" to be enabled, but it is not enabled";\n' % enum_tuple.ext_name273                enum_value_validate += self.writeIndent(indent)274                enum_value_validate += 'CoreValidLogMessage(instance_info, vuid,\n'275                enum_value_validate += self.writeIndent(indent)276                enum_value_validate += '                    VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,\n'277                enum_value_validate += self.writeIndent(indent)278                enum_value_validate += '                    objects_info, error_str);\n'279                enum_value_validate += self.writeIndent(indent)280                enum_value_validate += 'return false;\n'281                indent -= 1282                enum_value_validate += self.writeIndent(indent)283                enum_value_validate += '}\n'284            enum_value_validate += self.writeIndent(indent)285            enum_value_validate += 'switch (value) {\n'286            indent += 1287            for cur_value in enum_tuple.values:288                avoid_dupe = None289                if cur_value.alias:290                    aliased = [x for x in enum_tuple.values if x.name == cur_value.alias]291                    aliased_value = aliased[0]292                    if aliased_value.protect_value and aliased_value.protect_value != cur_value.protect_value and aliased_value.protect_value != enum_tuple.protect_value:293                        avoid_dupe = aliased_value.protect_string294                        enum_value_validate += '#if !(%s)\n' % avoid_dupe295                    else:296                        # This would unconditionally cause a duplicate case297                        continue298                value_protect = None299                if cur_value.protect_value and enum_tuple.protect_value != cur_value.protect_value:300                    value_protect = cur_value.protect_string301                    enum_value_validate += '#if %s\n' % value_protect302                enum_value_validate += self.writeIndent(indent)303                enum_value_validate += 'case %s:\n' % cur_value.name304                if cur_value.ext_name and cur_value.ext_name != checked_extension and not self.isCoreExtensionName(cur_value.ext_name):305                    indent += 1306                    enum_value_validate += self.writeIndent(indent)307                    enum_value_validate += '// Enum value %s requires extension %s, so check that it is enabled\n' % (308                        cur_value.name, cur_value.ext_name)309                    enum_value_validate += self.writeIndent(indent)310                    enum_value_validate += 'if (nullptr != instance_info && !ExtensionEnabled(instance_info->enabled_extensions, "%s")) {\n' % cur_value.ext_name311                    indent += 1312                    enum_value_validate += self.writeIndent(indent)313                    enum_value_validate += 'std::string vuid = "VUID-";\n'314                    enum_value_validate += self.writeIndent(indent)315                    enum_value_validate += 'vuid += validation_name;\n'316                    enum_value_validate += self.writeIndent(indent)317                    enum_value_validate += 'vuid += "-";\n'318                    enum_value_validate += self.writeIndent(indent)319                    enum_value_validate += 'vuid += item_name;\n'320                    enum_value_validate += self.writeIndent(indent)321                    enum_value_validate += 'vuid += "-parameter";\n'322                    enum_value_validate += self.writeIndent(indent)323                    enum_value_validate += 'std::string error_str = "%s value \\"%s\\"";\n' % (324                        enum_tuple.name, cur_value.name)325                    enum_value_validate += self.writeIndent(indent)326                    enum_value_validate += 'error_str += " being used, which requires extension ";\n'327                    enum_value_validate += self.writeIndent(indent)328                    enum_value_validate += 'error_str += " \\"%s\\" to be enabled, but it is not enabled";\n' % cur_value.ext_name329                    enum_value_validate += self.writeIndent(indent)330                    enum_value_validate += 'CoreValidLogMessage(instance_info, vuid,\n'331                    enum_value_validate += self.writeIndent(indent)332                    enum_value_validate += '                    VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,\n'333                    enum_value_validate += self.writeIndent(indent)334                    enum_value_validate += '                    objects_info, error_str);\n'335                    enum_value_validate += self.writeIndent(indent)336                    enum_value_validate += 'return false;\n'337                    indent -= 1338                    enum_value_validate += self.writeIndent(indent)339                    enum_value_validate += '}\n'340                    enum_value_validate += self.writeIndent(indent)341                    enum_value_validate += 'return true;\n'342                    indent -= 1343                elif cur_value.name == 'XR_TYPE_UNKNOWN':344                    enum_value_validate += self.writeIndent(indent + 1)345                    enum_value_validate += 'return false; // Invalid XrStructureType \n'346                else:347                    enum_value_validate += self.writeIndent(indent + 1)348                    enum_value_validate += 'return true;\n'349                if value_protect:350                    enum_value_validate += '#endif // %s\n' % value_protect351                if avoid_dupe:352                    enum_value_validate += '#endif // !(%s)\n' % avoid_dupe353            indent -= 1354            enum_value_validate += self.writeIndent(indent)355            enum_value_validate += 'default:\n'356            enum_value_validate += self.writeIndent(indent + 1)357            enum_value_validate += 'return false;\n'358            indent -= 1359            enum_value_validate += '}\n'360            enum_value_validate += '}\n\n'361            if enum_tuple.protect_value:362                enum_value_validate += '#endif // %s\n' % enum_tuple.protect_string363        return enum_value_validate364    # Generate prototypes for functions used internal to the source file so other functions can use them365    #   self            the ValidationSourceOutputGenerator object366    def outputValidationInternalProtos(self):367        validation_internal_protos = ''368        for handle in self.api_handles:369            if handle.protect_value:370                validation_internal_protos += '#if %s\n' % handle.protect_string371            validation_internal_protos += 'ValidateXrHandleResult Verify%sHandle(const %s* handle_to_check);\n' % (372                handle.name, handle.name)373            if handle.protect_value:374                validation_internal_protos += '#endif // %s\n' % handle.protect_string375        validation_internal_protos += '\n// Write out prototypes for handle parent verification functions\n'376        validation_internal_protos += 'bool VerifyXrParent(XrObjectType handle1_type, const uint64_t handle1,\n'377        validation_internal_protos += '                    XrObjectType handle2_type, const uint64_t handle2,\n'378        validation_internal_protos += '                    bool check_this);\n'379        validation_internal_protos += '\n// Function to check if an extension has been enabled\n'380        validation_internal_protos += 'bool ExtensionEnabled(const std::vector<std::string> &extensions, const char* const check_extension_name);\n'381        validation_internal_protos += '\n// Functions to validate structures\n'382        for xr_struct in self.api_structures:383            if xr_struct.protect_value:384                validation_internal_protos += '#if %s\n' % xr_struct.protect_string385            validation_internal_protos += 'XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,\n'386            validation_internal_protos += '                          std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,\n'387            validation_internal_protos += '                          const %s* value);\n' % xr_struct.name388            if xr_struct.protect_value:389                validation_internal_protos += '#endif // %s\n' % xr_struct.protect_string390        return validation_internal_protos391    # Generate C++ functions for validating 'next' chains in a structure.392    #   self            the ValidationSourceOutputGenerator object393    def outputValidationSourceNextChainFunc(self):394        next_chain_info = ''395        next_chain_info += 'NextChainResult ValidateNextChain(GenValidUsageXrInstanceInfo *instance_info,\n'396        next_chain_info += '                                  const std::string &command_name,\n'397        next_chain_info += '                                  std::vector<GenValidUsageXrObjectInfo>& objects_info,\n'398        next_chain_info += '                                  const void* next,\n'399        next_chain_info += '                                  std::vector<XrStructureType>& valid_ext_structs,\n'400        next_chain_info += '                                  std::vector<XrStructureType>& encountered_structs,\n'401        next_chain_info += '                                  std::vector<XrStructureType>& duplicate_structs) {\n'402        next_chain_info += self.writeIndent(1)403        next_chain_info += 'NextChainResult return_result = NEXT_CHAIN_RESULT_VALID;\n'404        next_chain_info += self.writeIndent(1)405        next_chain_info += '// NULL is valid\n'406        next_chain_info += self.writeIndent(1)407        next_chain_info += 'if (nullptr == next) {\n'408        next_chain_info += self.writeIndent(2)409        next_chain_info += 'return return_result;\n'410        next_chain_info += self.writeIndent(1)411        next_chain_info += '}\n'412        next_chain_info += self.writeIndent(1)413        next_chain_info += '// Non-NULL is not valid if there is no valid extension structs\n'414        next_chain_info += self.writeIndent(1)415        next_chain_info += 'if (nullptr != next && 0 == valid_ext_structs.size()) {\n'416        next_chain_info += self.writeIndent(2)417        next_chain_info += 'return NEXT_CHAIN_RESULT_ERROR;\n'418        next_chain_info += self.writeIndent(1)419        next_chain_info += '}\n'420        next_chain_info += self.writeIndent(1)421        next_chain_info += 'const XrBaseInStructure* next_header = reinterpret_cast<const XrBaseInStructure*>(next);\n'422        next_chain_info += self.writeIndent(1)423        next_chain_info += 'auto valid_ext = std::find(valid_ext_structs.begin(), valid_ext_structs.end(), next_header->type);\n'424        next_chain_info += self.writeIndent(1)425        next_chain_info += 'if (valid_ext == valid_ext_structs.end()) {\n'426        next_chain_info += self.writeIndent(2)427        next_chain_info += '// Not a valid extension structure type for this next chain.\n'428        next_chain_info += self.writeIndent(2)429        next_chain_info += 'return NEXT_CHAIN_RESULT_ERROR;\n'430        next_chain_info += self.writeIndent(1)431        next_chain_info += '} else {\n'432        next_chain_info += self.writeIndent(2)433        next_chain_info += '// Check to see if we\'ve already encountered this structure.\n'434        next_chain_info += self.writeIndent(2)435        next_chain_info += 'auto already_encountered_ext = std::find(encountered_structs.begin(), encountered_structs.end(), next_header->type);\n'436        next_chain_info += self.writeIndent(2)437        next_chain_info += 'if (already_encountered_ext != encountered_structs.end()) {\n'438        next_chain_info += self.writeIndent(3)439        next_chain_info += '// Make sure we only put in unique types into our duplicate list.\n'440        next_chain_info += self.writeIndent(3)441        next_chain_info += 'auto already_duplicate = std::find(duplicate_structs.begin(), duplicate_structs.end(), next_header->type);\n'442        next_chain_info += self.writeIndent(3)443        next_chain_info += 'if (already_duplicate == duplicate_structs.end()) {\n'444        next_chain_info += self.writeIndent(4)445        next_chain_info += 'duplicate_structs.push_back(next_header->type);\n'446        next_chain_info += self.writeIndent(3)447        next_chain_info += '}\n'448        next_chain_info += self.writeIndent(3)449        next_chain_info += 'return_result = NEXT_CHAIN_RESULT_DUPLICATE_STRUCT;\n'450        next_chain_info += self.writeIndent(2)451        next_chain_info += '}\n'452        next_chain_info += self.writeIndent(1)453        next_chain_info += '}\n'454        # Validate the rest of this struct455        next_chain_info += self.writeIndent(1)456        next_chain_info += 'switch (next_header->type) {\n'457        enum_tuple = [x for x in self.api_enums if x.name == 'XrStructureType'][0]458        for cur_value in enum_tuple.values:459            struct_define_name = self.genXrStructureName(460                cur_value.name)461            if not struct_define_name:462                continue463            struct_tuple = self.getStruct(struct_define_name)464            avoid_dupe = None465            if cur_value.alias:466                aliased_value = [x for x in enum_tuple.values if x.name == cur_value.alias][0]467                if aliased_value.protect_value and aliased_value.protect_value != cur_value.protect_value and aliased_value.protect_value != struct_tuple.protect_value:468                    avoid_dupe = aliased_value.protect_string469                    next_chain_info += '#if !(%s)\n' % avoid_dupe470                else:471                    # This would unconditionally cause a duplicate case472                    continue473            if struct_tuple.protect_value:474                next_chain_info += '#if %s\n' % struct_tuple.protect_string475                476            next_chain_info += self.writeIndent(2)477            next_chain_info += 'case %s:\n' % cur_value.name478            next_chain_info += self.writeIndent(3)479            next_chain_info += 'if (XR_SUCCESS != ValidateXrStruct(instance_info, command_name, objects_info, false,\n'480            next_chain_info += self.writeIndent(3)481            next_chain_info += '                                   reinterpret_cast<const %s*>(next))) {\n' % struct_define_name482            next_chain_info += self.writeIndent(4)483            next_chain_info += 'return NEXT_CHAIN_RESULT_ERROR;\n'484            next_chain_info += self.writeIndent(3)485            next_chain_info += '}\n'486            next_chain_info += self.writeIndent(3)487            next_chain_info += 'break;\n'488            if struct_tuple.protect_value:489                next_chain_info += '#endif // %s\n' % struct_tuple.protect_string490            if avoid_dupe:491                next_chain_info += '#endif // !(%s)\n' % avoid_dupe492        next_chain_info += self.writeIndent(2)493        next_chain_info += 'default:\n'494        next_chain_info += self.writeIndent(3)495        next_chain_info += 'return NEXT_CHAIN_RESULT_ERROR;\n'496        next_chain_info += self.writeIndent(1)497        next_chain_info += '}\n'498        # Validate any chained structs499        next_chain_info += self.writeIndent(1)500        next_chain_info += 'NextChainResult next_result = ValidateNextChain(instance_info, command_name,\n'501        next_chain_info += self.writeIndent(1)502        next_chain_info += '                                                objects_info, next_header->next,\n'503        next_chain_info += self.writeIndent(1)504        next_chain_info += '                                                valid_ext_structs,\n'505        next_chain_info += self.writeIndent(1)506        next_chain_info += '                                                encountered_structs,\n'507        next_chain_info += self.writeIndent(1)508        next_chain_info += '                                                duplicate_structs);\n'509        next_chain_info += self.writeIndent(1)510        next_chain_info += 'if (NEXT_CHAIN_RESULT_VALID == next_result && NEXT_CHAIN_RESULT_VALID != return_result) {\n'511        next_chain_info += self.writeIndent(2)512        next_chain_info += 'return return_result;\n'513        next_chain_info += self.writeIndent(1)514        next_chain_info += '} else {\n'515        next_chain_info += self.writeIndent(2)516        next_chain_info += 'return next_result;\n'517        next_chain_info += self.writeIndent(1)518        next_chain_info += '}\n'519        next_chain_info += '}\n\n'520        return next_chain_info521    # Generate C++ header information containing functionality used in both522    # the generated and manual code.523    #  - Structures used to store validation information on a per-handle basis.524    #  - Unordered_map and mutexes used for storing the structure information on a per handle basis.525    #   self            the ValidationSourceOutputGenerator object526    def outputValidationHeaderInfo(self):527        commands = []528        validation_header_info = ''529        cur_extension_name = ''530        validation_header_info += '// Unordered Map associating pointer to a vector of session label information to a session\'s handle\n'531        validation_header_info += 'extern std::unordered_map<XrSession, std::vector<GenValidUsageXrInternalSessionLabel*>*> g_xr_session_labels;\n\n'532        for x in range(0, 2):533            if x == 0:534                commands = self.core_commands535            else:536                commands = self.ext_commands537            for cur_cmd in commands:538                if cur_cmd.ext_name != cur_extension_name:539                    if 'XR_VERSION_' in cur_cmd.ext_name:540                        validation_header_info += '\n// ---- Core %s commands\n' % cur_cmd.ext_name[11:].replace(541                            "_", ".")542                    else:543                        validation_header_info += '\n// ---- %s extension commands\n' % cur_cmd.ext_name544                    cur_extension_name = cur_cmd.ext_name545                prototype = cur_cmd.cdecl546                # We need to always export xrGetInstanceProcAddr, even though we automatically generate it.547                # Also, we really only need the core function, not the others.548                if 'xrGetInstanceProcAddr' in cur_cmd.name:549                    validation_header_info += '%s\n' % prototype.replace(550                        " xr", " GenValidUsageXr")551                    continue552                elif cur_cmd.name in self.no_trampoline_or_terminator or not cur_cmd.name in VALID_USAGE_MANUALLY_DEFINED:553                    continue554                if cur_cmd.protect_value:555                    validation_header_info += '#if %s\n' % cur_cmd.protect_string556                # Core call, for us to make from here into the manually implemented code557                validation_header_info += '%s\n' % prototype.replace(558                    " xr", " CoreValidationXr")559                # Validate Inputs and Next calls for the validation to make560                validation_header_info += 'XrResult %s(' % cur_cmd.name.replace(561                    "xr", "GenValidUsageInputsXr")562                count = 0563                for param in cur_cmd.params:564                    if count > 0:565                        validation_header_info += ', '566                    count = count + 1567                    validation_header_info += param.cdecl.strip()568                validation_header_info += ');\n'569                validation_header_info += '%s\n' % prototype.replace(570                    " xr", " GenValidUsageNextXr")571                if cur_cmd.protect_value:572                    validation_header_info += '#endif // %s\n' % cur_cmd.protect_string573        validation_header_info += '\n// Current API version of the Core Validation API Layer\n#define XR_CORE_VALIDATION_API_VERSION '574        validation_header_info += self.api_version_define575        validation_header_info += '\n'576        validation_header_info += '#if defined(__GNUC__)\n'577        validation_header_info += '#pragma GCC diagnostic push\n'578        validation_header_info += '#pragma GCC diagnostic ignored "-Wunused-parameter"\n'579        validation_header_info += '#pragma GCC diagnostic ignored "-Wunused-variable"\n'580        validation_header_info += '#endif\n'581        validation_header_info += '\n// Externs for Core Validation\n'582        validation_header_info += self.outputInfoMapDeclarations(extern=True)583        validation_header_info += 'void GenValidUsageCleanUpMaps(GenValidUsageXrInstanceInfo *instance_info);\n\n'584        validation_header_info += '\n// Function to convert XrObjectType to string\n'585        validation_header_info += 'std::string GenValidUsageXrObjectTypeToString(const XrObjectType& type);\n\n'586        validation_header_info += '// Function to record all the core validation information\n'587        validation_header_info += 'extern void CoreValidLogMessage(GenValidUsageXrInstanceInfo *instance_info, const std::string &message_id,\n'588        validation_header_info += '                                GenValidUsageDebugSeverity message_severity, const std::string &command_name,\n'589        validation_header_info += '                                std::vector<GenValidUsageXrObjectInfo> objects_info, const std::string &message);\n'590        return validation_header_info591    # Generate C++ utility functions to verify that all the required extensions have been enabled.592    #   self            the ValidationSourceOutputGenerator object593    def writeVerifyExtensions(self):594        verify_extensions = 'bool ExtensionEnabled(const std::vector<std::string> &extensions, const char* const check_extension_name) {\n'595        verify_extensions += self.writeIndent(1)596        verify_extensions += 'for (const auto& enabled_extension: extensions) {\n'597        verify_extensions += self.writeIndent(2)598        verify_extensions += 'if (enabled_extension == check_extension_name) {\n'599        verify_extensions += self.writeIndent(3)600        verify_extensions += 'return true;\n'601        verify_extensions += self.writeIndent(2)602        verify_extensions += '}\n'603        verify_extensions += self.writeIndent(1)604        verify_extensions += '}\n'605        verify_extensions += self.writeIndent(1)606        verify_extensions += 'return false;\n'607        verify_extensions += '}\n\n'608        number_of_instance_extensions = 0609        number_of_system_extensions = 0610        for extension in self.extensions:611            if extension.type == 'instance':612                number_of_instance_extensions += 1613            elif extension.type == 'system':614                number_of_system_extensions += 1615        verify_extensions += 'bool ValidateInstanceExtensionDependencies(GenValidUsageXrInstanceInfo *gen_instance_info,\n'616        verify_extensions += '                                           const std::string &command,\n'617        verify_extensions += '                                           const std::string &struct_name,\n'618        verify_extensions += '                                           std::vector<GenValidUsageXrObjectInfo>& objects_info,\n'619        verify_extensions += '                                           std::vector<std::string> &extensions) {\n'620        indent = 1621        if number_of_instance_extensions > 0:622            verify_extensions += self.writeIndent(indent)623            verify_extensions += 'for (uint32_t cur_index = 0; cur_index < extensions.size(); ++cur_index) {\n'624            indent += 1625            for extension in self.extensions:626                number_of_required = len(extension.required_exts) - 1627                if extension.type == 'instance' and number_of_required > 0:628                    verify_extensions += self.writeIndent(indent)629                    verify_extensions += 'if (extensions[cur_index] == "%s") {\n' % extension.name630                    current_count = 0631                    indent += 1632                    verify_extensions += self.writeIndent(indent)633                    verify_extensions += 'for (uint32_t check_index = 0; check_index < extensions.size(); ++check_index) {\n'634                    indent += 1635                    verify_extensions += self.writeIndent(indent)636                    verify_extensions += 'if (cur_index == check_index) {\n'637                    verify_extensions += self.writeIndent(indent + 1)638                    verify_extensions += 'continue;\n'639                    verify_extensions += self.writeIndent(indent)640                    verify_extensions += '}\n'641                    current_count = 0642                    for required_ext in extension.required_exts:643                        if current_count > 0:644                            found = False645                            for extension_look in self.extensions:646                                if extension_look.name == required_ext:647                                    found = True648                                    if extension_look.type != 'instance':649                                        verify_extensions += self.printCodeGenErrorMessage('Instance extension "%s" requires non-instance extension "%s" which is not allowed' % (650                                            self.currentExtension, required_ext))651                            if not found:652                                verify_extensions += self.printCodeGenErrorMessage('Instance extension "%s" lists extension "%s" as a requirement, but'653                                                                                   ' it is not defined in the registry.' % (654                                                                                       self.currentExtension, required_ext))655                            verify_extensions += self.writeIndent(indent)656                            verify_extensions += 'if (!ExtensionEnabled(extensions, "%s")) {\n' % required_ext657                            indent += 1658                            verify_extensions += self.writeIndent(indent)659                            verify_extensions += 'if (nullptr != gen_instance_info) {\n'660                            indent += 1661                            verify_extensions += self.writeIndent(indent)662                            verify_extensions += 'std::string vuid = "VUID-";\n'663                            verify_extensions += self.writeIndent(indent)664                            verify_extensions += 'vuid += command;\n'665                            verify_extensions += self.writeIndent(indent)666                            verify_extensions += 'vuid += "-";\n'667                            verify_extensions += self.writeIndent(indent)668                            verify_extensions += 'vuid += struct_name;\n'669                            verify_extensions += self.writeIndent(indent)670                            verify_extensions += 'vuid += "-parameter";\n'671                            verify_extensions += self.writeIndent(indent)672                            verify_extensions += 'CoreValidLogMessage(gen_instance_info, vuid, VALID_USAGE_DEBUG_SEVERITY_ERROR,\n'673                            verify_extensions += self.writeIndent(indent)674                            verify_extensions += '                    command, objects_info,\n'675                            verify_extensions += self.writeIndent(indent)676                            verify_extensions += '                    "Missing extension dependency \\"%s\\" (required by extension" \\\n' % required_ext677                            verify_extensions += self.writeIndent(indent)678                            verify_extensions += '                    "\\"%s\\") from enabled extension list");\n' % extension.name679                            indent -= 1680                            verify_extensions += self.writeIndent(indent)681                            verify_extensions += '}\n'682                            verify_extensions += self.writeIndent(indent)683                            verify_extensions += 'return false;\n'684                            indent -= 1685                            verify_extensions += self.writeIndent(indent)686                            verify_extensions += '}\n'687                        current_count += 1688                    indent -= 1689                    verify_extensions += self.writeIndent(indent)690                    verify_extensions += '}\n'691                    indent -= 1692                    verify_extensions += self.writeIndent(indent)693                    verify_extensions += '}\n'694            indent -= 1695            verify_extensions += self.writeIndent(indent)696            verify_extensions += '}\n'697        else:698            verify_extensions += self.writeIndent(indent)699            verify_extensions += '// No instance extensions to check dependencies for\n'700        verify_extensions += self.writeIndent(indent)701        verify_extensions += 'return true;\n'702        verify_extensions += '}\n\n'703        verify_extensions += 'bool ValidateSystemExtensionDependencies(GenValidUsageXrInstanceInfo *gen_instance_info,\n'704        verify_extensions += '                                         const std::string &command,\n'705        verify_extensions += '                                         const std::string &struct_name,\n'706        verify_extensions += '                                         std::vector<GenValidUsageXrObjectInfo>& objects_info,\n'707        verify_extensions += '                                         std::vector<std::string> &extensions) {\n'708        indent = 1709        if number_of_system_extensions > 0:710            verify_extensions += self.writeIndent(indent)711            verify_extensions += 'for (uint32_t cur_index = 0; cur_index < extensions.size(); ++cur_index) {\n'712            indent += 1713            for extension in self.extensions:714                number_of_required = len(self.required_exts) - 1715                if extension.type == 'system' and number_of_required > 0:716                    verify_extensions += self.writeIndent(indent)717                    verify_extensions += 'if (extensions[cur_index] == "%s") {\n' % extension.name718                    current_count = 0719                    indent += 1720                    verify_extensions += self.writeIndent(indent)721                    verify_extensions += 'for (uint32_t check_index = 0; check_index < extensions.size(); ++check_index) {\n'722                    indent += 1723                    verify_extensions += self.writeIndent(indent)724                    verify_extensions += 'if (cur_index == check_index) {\n'725                    verify_extensions += self.writeIndent(indent + 1)726                    verify_extensions += 'continue;\n'727                    verify_extensions += self.writeIndent(indent)728                    verify_extensions += '}\n'729                    current_count = 0730                    for required_ext in extension.required_exts:731                        if current_count > 0:732                            found = False733                            is_instance = False734                            for extension_look in self.extensions:735                                if extension_look.name == required_ext:736                                    found = True737                                    if extension_look.type == 'instance':738                                        is_instance = True739                                    if not is_instance and extension_look.type != 'system':740                                        verify_extensions += self.printCodeGenErrorMessage('System extension "%s" has an extension dependency on extension "%s" '741                                                                                           'which is of an invalid type.' % (742                                                                                               self.currentExtension, required_ext))743                            if not found:744                                verify_extensions += self.printCodeGenErrorMessage('System extension "%s" lists extension "%s" as a requirement, but'745                                                                                   ' it is not defined in the registry.' % (746                                                                                       self.currentExtension, required_ext))747                            if is_instance:748                                verify_extensions += self.writeIndent(indent)749                                verify_extensions += '// This is an instance extension dependency, so make sure it is enabled in the instance\n'750                                verify_extensions += self.writeIndent(indent)751                                verify_extensions += 'if (!ExtensionEnabled(gen_instance_info->enabled_extensions, "%s") {\n' % required_ext752                            else:753                                verify_extensions += self.writeIndent(indent)754                                verify_extensions += 'if (!ExtensionEnabled(extensions, "%s")) {\n' % required_ext755                            indent += 1756                            verify_extensions += self.writeIndent(indent)757                            verify_extensions += 'std::string vuid = "VUID-";\n'758                            verify_extensions += self.writeIndent(indent)759                            verify_extensions += 'vuid += command;\n'760                            verify_extensions += self.writeIndent(indent)761                            verify_extensions += 'vuid += "-";\n'762                            verify_extensions += self.writeIndent(indent)763                            verify_extensions += 'vuid += struct_name;\n'764                            verify_extensions += self.writeIndent(indent)765                            verify_extensions += 'vuid += "-parameter";\n'766                            verify_extensions += self.writeIndent(indent)767                            verify_extensions += 'CoreValidLogMessage(gen_instance_info, vuid, VALID_USAGE_DEBUG_SEVERITY_ERROR,\n'768                            verify_extensions += self.writeIndent(indent)769                            verify_extensions += '                    command, objects_info,\n'770                            verify_extensions += self.writeIndent(indent)771                            verify_extensions += '                    "Missing extension dependency \\"%s\\" (required by extension" \\' % required_ext772                            verify_extensions += self.writeIndent(indent)773                            verify_extensions += '                    "\\"%s\\") from enabled extension list");\n' % extension.name774                            verify_extensions += self.writeIndent(indent)775                            verify_extensions += 'return false;\n'776                            indent -= 1777                            verify_extensions += self.writeIndent(indent)778                            verify_extensions += '}\n'779                        current_count += 1780                    indent -= 1781                    verify_extensions += self.writeIndent(indent)782                    verify_extensions += '}\n'783                    indent -= 1784                    verify_extensions += self.writeIndent(indent)785                    verify_extensions += '}\n'786            indent -= 1787            verify_extensions += self.writeIndent(indent)788            verify_extensions += '}\n'789        else:790            verify_extensions += self.writeIndent(indent)791            verify_extensions += '// No system extensions to check dependencies for\n'792        verify_extensions += self.writeIndent(indent)793        verify_extensions += 'return true;\n'794        verify_extensions += '}\n\n'795        return verify_extensions796    # Generate C++ enum and utility functions for verify that handles are valid.797    #   self            the ValidationSourceOutputGenerator object798    def writeValidateHandleChecks(self):799        verify_handle = ''800        for handle in self.api_handles:801            if handle.protect_value:802                verify_handle += '#if %s\n' % handle.protect_string803            indent = 1804            verify_handle += 'ValidateXrHandleResult Verify%sHandle(const %s* handle_to_check) {\n' % (805                handle.name, handle.name)806            verify_handle += self.writeIndent(indent)807            verify_handle += 'return %s.verifyHandle(handle_to_check);\n' % self.makeInfoName(handle)808            verify_handle += '}\n\n'809            if handle.protect_value:810                verify_handle += '#endif // %s\n' % handle.protect_string811        return verify_handle812    # Generate C++ utility functions for verify that handles share a parent.813    #   self            the ValidationSourceOutputGenerator object814    def writeValidateHandleParent(self):815        verify_parent = '// Implementation function to get parent handle information\n'816        verify_parent += 'bool GetXrParent(const XrObjectType inhandle_type, const uint64_t inhandle,\n'817        verify_parent += '                 XrObjectType& outhandle_type, uint64_t& outhandle) {\n'818        indent = 1819        for handle in self.api_handles:820            if handle.name == 'XrInstance':821                verify_parent += self.writeIndent(indent)822                verify_parent += 'if (inhandle_type == XR_OBJECT_TYPE_INSTANCE) {\n'823                verify_parent += self.writeIndent(indent + 1)824                verify_parent += 'return false;\n'825                verify_parent += self.writeIndent(indent)826                verify_parent += '}\n'827            else:828                handle_info = '%s.get(TreatIntegerAsHandle<%s>(inhandle))' % (self.makeInfoName(handle), handle.name)829                verify_parent += self.writeIndent(indent)830                verify_parent += 'if (inhandle_type == %s) {\n' % self.genXrObjectType(831                    handle.name)832                indent += 1833                verify_parent += self.writeIndent(indent)834                verify_parent += '// Get the object and parent of the handle\n'835                verify_parent += self.writeIndent(indent)836                verify_parent += 'GenValidUsageXrHandleInfo *handle_info = %s;\n' % handle_info837                verify_parent += self.writeIndent(indent)838                verify_parent += 'outhandle_type = handle_info->direct_parent_type;\n'839                verify_parent += self.writeIndent(indent)840                verify_parent += 'outhandle = handle_info->direct_parent_handle;\n'841                verify_parent += self.writeIndent(indent)842                verify_parent += 'return true;\n'843                indent -= 1844                verify_parent += self.writeIndent(indent)845                verify_parent += '}\n'846        verify_parent += '    return false;\n'847        verify_parent += '}\n\n'848        verify_parent += '// Implementation of VerifyXrParent function\n'849        verify_parent += 'bool VerifyXrParent(XrObjectType handle1_type, const uint64_t handle1,\n'850        verify_parent += '                    XrObjectType handle2_type, const uint64_t handle2,\n'851        verify_parent += '                    bool check_this) {\n'852        indent = 1853        verify_parent += self.writeIndent(indent)854        verify_parent += 'if (IsIntegerNullHandle(handle1) || IsIntegerNullHandle(handle2)) {\n'855        verify_parent += self.writeIndent(indent + 1)856        verify_parent += 'return false;\n'857        verify_parent += self.writeIndent(indent)858        verify_parent += '} else if (check_this && handle1_type == handle2_type) {\n'859        verify_parent += self.writeIndent(indent + 1)860        verify_parent += 'return (handle1 == handle2);\n'861        verify_parent += self.writeIndent(indent)862        verify_parent += '}\n'863        verify_parent += self.writeIndent(indent)864        verify_parent += 'if (handle1_type == XR_OBJECT_TYPE_INSTANCE && handle2_type != XR_OBJECT_TYPE_INSTANCE) {\n'865        indent += 1866        verify_parent += self.writeIndent(indent)867        verify_parent += 'XrObjectType parent_type;\n'868        verify_parent += self.writeIndent(indent)869        verify_parent += 'uint64_t parent_handle;\n'870        verify_parent += self.writeIndent(indent)871        verify_parent += 'if (!GetXrParent(handle2_type, handle2, parent_type, parent_handle)) {\n'872        verify_parent += self.writeIndent(indent + 1)873        verify_parent += 'return false;\n'874        verify_parent += self.writeIndent(indent)875        verify_parent += '}\n'876        verify_parent += self.writeIndent(indent)877        verify_parent += 'return VerifyXrParent(handle1_type, handle1, parent_type, parent_handle, true);\n'878        indent -= 1879        verify_parent += self.writeIndent(indent)880        verify_parent += '} else if (handle2_type == XR_OBJECT_TYPE_INSTANCE && handle1_type != XR_OBJECT_TYPE_INSTANCE) {\n'881        indent += 1882        verify_parent += self.writeIndent(indent)883        verify_parent += 'XrObjectType parent_type;\n'884        verify_parent += self.writeIndent(indent)885        verify_parent += 'uint64_t parent_handle;\n'886        verify_parent += self.writeIndent(indent)887        verify_parent += 'if (!GetXrParent(handle1_type, handle1, parent_type, parent_handle)) {\n'888        verify_parent += self.writeIndent(indent + 1)889        verify_parent += 'return false;\n'890        verify_parent += self.writeIndent(indent)891        verify_parent += '}\n'892        verify_parent += self.writeIndent(indent)893        verify_parent += 'return VerifyXrParent(parent_type, parent_handle, handle2_type, handle2, true);\n'894        indent -= 1895        verify_parent += self.writeIndent(indent)896        verify_parent += '} else {\n'897        indent += 1898        verify_parent += self.writeIndent(indent)899        verify_parent += 'XrObjectType parent1_type;\n'900        verify_parent += self.writeIndent(indent)901        verify_parent += 'uint64_t parent1_handle;\n'902        verify_parent += self.writeIndent(indent)903        verify_parent += self.writeIndent(indent)904        verify_parent += 'XrObjectType parent2_type;\n'905        verify_parent += self.writeIndent(indent)906        verify_parent += 'uint64_t parent2_handle;\n'907        verify_parent += self.writeIndent(indent)908        verify_parent += 'if (!GetXrParent(handle1_type, handle1, parent1_type, parent1_handle)) {\n'909        verify_parent += self.writeIndent(indent + 1)910        verify_parent += 'return false;\n'911        verify_parent += self.writeIndent(indent)912        verify_parent += '}\n'913        verify_parent += self.writeIndent(indent)914        verify_parent += 'if (!GetXrParent(handle2_type, handle2, parent2_type, parent2_handle)) {\n'915        verify_parent += self.writeIndent(indent + 1)916        verify_parent += 'return false;\n'917        verify_parent += self.writeIndent(indent)918        verify_parent += '}\n'919        verify_parent += self.writeIndent(indent)920        verify_parent += 'if (parent1_type == handle2_type) {\n'921        verify_parent += self.writeIndent(indent + 1)922        verify_parent += 'return (parent1_handle == handle2);\n'923        verify_parent += self.writeIndent(indent)924        verify_parent += '} else if (handle1_type == parent2_type) {\n'925        verify_parent += self.writeIndent(indent + 1)926        verify_parent += 'return (handle1 == parent2_handle);\n'927        verify_parent += self.writeIndent(indent)928        verify_parent += '} else {\n'929        verify_parent += self.writeIndent(indent + 1)930        verify_parent += 'return VerifyXrParent(parent1_type, parent1_handle, parent2_type, parent2_handle, true);\n'931        verify_parent += self.writeIndent(indent)932        verify_parent += '}\n'933        indent -= 1934        verify_parent += self.writeIndent(indent)935        verify_parent += '}\n'936        verify_parent += self.writeIndent(indent)937        verify_parent += 'return false;\n'938        indent -= 1939        verify_parent += '}\n\n'940        return verify_parent941    # Generate inline C++ code to check if a 'next' chain is valid for the current structure.942    #   self            the ValidationSourceOutputGenerator object943    #   struct_type     the name of the type of structure performing the validation check944    #   member          the member generated in automatic_source_generator.py to validate945    #   indent          the number of "tabs" to space in for the resulting C+ code.946    def writeValidateStructNextCheck(self, struct_type, struct_name, member, indent):947        validate_struct_next = self.writeIndent(indent)948        validate_struct_next += 'std::vector<XrStructureType> valid_ext_structs;\n'949        validate_struct_next += self.writeIndent(indent)950        validate_struct_next += 'std::vector<XrStructureType> duplicate_ext_structs;\n'951        validate_struct_next += self.writeIndent(indent)952        validate_struct_next += 'std::vector<XrStructureType> encountered_structs;\n'953        if member.valid_extension_structs:954            for valid_struct in member.valid_extension_structs:955                validate_struct_next += self.writeIndent(indent)956                validate_struct_next += 'valid_ext_structs.push_back(%s);\n' % self.genXrStructureType(957                    valid_struct)958        validate_struct_next += self.writeIndent(indent)959        validate_struct_next += 'NextChainResult next_result = ValidateNextChain(instance_info, command_name, objects_info,\n'960        validate_struct_next += self.writeIndent(indent)961        validate_struct_next += '                                                 %s->%s, valid_ext_structs,\n' % (962            struct_name, member.name)963        validate_struct_next += self.writeIndent(indent)964        validate_struct_next += '                                                 encountered_structs,\n'965        validate_struct_next += self.writeIndent(indent)966        validate_struct_next += '                                                 duplicate_ext_structs);\n'967        validate_struct_next += self.writeIndent(indent)968        validate_struct_next += '// No valid extension structs for this \'next\'.  Therefore, must be NULL\n'969        validate_struct_next += self.writeIndent(indent)970        validate_struct_next += '// or only contain a list of valid extension structures.\n'971        validate_struct_next += self.writeIndent(indent)972        validate_struct_next += 'if (NEXT_CHAIN_RESULT_ERROR == next_result) {\n'973        validate_struct_next += self.writeIndent(indent + 1)974        validate_struct_next += 'CoreValidLogMessage(instance_info, "VUID-%s-%s-next",\n' % (struct_type,975                                                                                             member.name)976        validate_struct_next += self.writeIndent(indent + 1)977        validate_struct_next += '                    VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,\n'978        validate_struct_next += self.writeIndent(indent + 1)979        validate_struct_next += '                    objects_info, "Invalid structure(s) in \\"next\\" chain for %s struct \\"%s\\"");\n' % (struct_type,980                                                                                                                                             member.name)981        validate_struct_next += self.writeIndent(indent + 1)982        validate_struct_next += 'xr_result = XR_ERROR_VALIDATION_FAILURE;\n'983        validate_struct_next += self.writeIndent(indent)984        validate_struct_next += '} else if (NEXT_CHAIN_RESULT_DUPLICATE_STRUCT == next_result) {\n'985        validate_struct_next += self.writeIndent(indent + 1)986        validate_struct_next += 'std::string error_message = "Multiple structures of the same type(s) in \\"next\\" chain for ";\n'987        validate_struct_next += self.writeIndent(indent + 1)988        validate_struct_next += 'error_message += "%s : ";\n' % struct_type989        validate_struct_next += self.writeIndent(indent + 1)990        validate_struct_next += 'error_message += StructTypesToString(instance_info, duplicate_ext_structs);\n'991        validate_struct_next += self.writeIndent(indent + 1)992        validate_struct_next += 'CoreValidLogMessage(instance_info, "VUID-%s-next-unique",\n' % struct_type993        validate_struct_next += self.writeIndent(indent + 1)994        validate_struct_next += '                    VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,\n'995        validate_struct_next += self.writeIndent(indent + 1)996        validate_struct_next += '                    objects_info,\n'997        validate_struct_next += self.writeIndent(indent + 1)998        validate_struct_next += '"Multiple structures of the same type(s) in \\"next\\" chain for %s struct");\n' %  struct_type999        validate_struct_next += self.writeIndent(indent + 1)1000        validate_struct_next += 'xr_result = XR_ERROR_VALIDATION_FAILURE;\n'1001        validate_struct_next += self.writeIndent(indent)1002        validate_struct_next += '}\n'1003        return validate_struct_next1004    # Generate inline C++ code to check if a pointer to a variable or array is valid.1005    #   self                the ValidationSourceOutputGenerator object1006    #   cmd_struct_name     the name of the structure or command generating this validation check.1007    #   member_param_name   the name of the member or parameter getting validated1008    #   member_param_type   the type of the member or parameter getting validated1009    #   pointer_to_check    the full name of the pointer to check (usually cmd_struct_name +1010    #                       member_param_name in some fashion)1011    #   full_count_var      the full name of the array count variable (if this is an array), or None1012    #   short_count_var     the short name of the array count variable (if this is an array), or None1013    #   is_in_cmd           Boolean indicating that this is being called directly from inside a command1014    #   indent              the number of "tabs" to space in for the resulting C+ code.1015    def writeValidatePointerArrayNonNull(self, cmd_struct_name, member_param_name, member_param_type,1016                                         pointer_to_check, full_count_var, short_count_var, is_in_cmd,1017                                         indent):1018        array_check = self.writeIndent(indent)1019        instance_info_string = 'instance_info'1020        command_string = 'command_name'1021        error_prefix = ''1022        if is_in_cmd:1023            if cmd_struct_name == 'xrCreateInstance':1024                instance_info_string = 'nullptr'1025            else:1026                instance_info_string = 'gen_instance_info'1027            command_string = '"%s"' % cmd_struct_name1028            error_prefix = 'Invalid NULL for'1029        else:1030            error_prefix = '%s contains invalid NULL for' % cmd_struct_name1031        if not full_count_var:1032            array_check += '// Non-optional pointer/array variable that needs to not be NULL\n'1033            array_check += self.writeIndent(indent)1034            array_check += 'if (nullptr == %s) {\n' % pointer_to_check1035            indent = indent + 11036            array_check += self.writeIndent(indent)1037            array_check += 'CoreValidLogMessage(%s, "VUID-%s-%s-parameter",\n' % (instance_info_string,1038                                                                                  cmd_struct_name,1039                                                                                  member_param_name)1040            array_check += self.writeIndent(indent)1041            array_check += '                    VALID_USAGE_DEBUG_SEVERITY_ERROR, %s, objects_info,\n' % command_string1042            array_check += self.writeIndent(indent)1043            array_check += '                    "%s %s \\"%s\\" which is not "\n' % (error_prefix,1044                                                                                     member_param_type,1045                                                                                     member_param_name)1046            array_check += self.writeIndent(indent)1047            array_check += '                    "optional and must be non-NULL");\n'1048        else:1049            array_check += '// Pointer/array variable with a length variable.  Make sure that\n'1050            array_check += self.writeIndent(indent)1051            array_check += '// if length variable is non-zero that the pointer is not NULL\n'1052            array_check += self.writeIndent(indent)1053            array_check += 'if (nullptr == %s && 0 != %s) {\n' % (1054                pointer_to_check, full_count_var)1055            indent = indent + 11056            array_check += self.writeIndent(indent)1057            array_check += 'CoreValidLogMessage(%s, "VUID-%s-%s-parameter",\n' % (instance_info_string,1058                                                                                  cmd_struct_name,1059                                                                                  member_param_name)1060            array_check += self.writeIndent(indent)1061            array_check += '                    VALID_USAGE_DEBUG_SEVERITY_ERROR, %s, objects_info,\n' % command_string1062            array_check += self.writeIndent(indent)1063            array_check += '                    "%s %s \\"%s\\" is which not "\n' % (error_prefix,1064                                                                                     member_param_type,1065                                                                                     member_param_name)1066            array_check += self.writeIndent(indent)1067            array_check += '                    "optional since \\"%s\\" is set and must be non-NULL");\n' % short_count_var1068        array_check += self.writeIndent(indent)1069        array_check += 'return XR_ERROR_VALIDATION_FAILURE;\n'1070        indent = indent - 11071        array_check += self.writeIndent(indent)1072        array_check += '}\n'1073        return array_check1074    # Write an inline check to make sure an Enum is valid1075    #   self                the ValidationSourceOutputGenerator object1076    #   cmd_struct_name     the name of the structure or command generating this validation check.1077    #   cmd_name_param      the name of the parameter containing the command name1078    #   param_type          the type of enum to validate getting validated1079    #   param_name          the name of the parameter to validate1080    #   full_param_name     the full name of the parameter to check (usually cmd_struct_name +1081    #                       member_param_name in some fashion)1082    #   param_is_pointer    Boolean indicate that the parameter is a pointer1083    #   is_in_cmd           Boolean indicating that this is being called directly from inside a command1084    #   indent              the number of "tabs" to space in for the resulting C+ code.1085    def writeValidateInlineEnum(self, cmd_struct_name, cmd_name_param, param_type, param_name, full_param_name,1086                                param_is_pointer, is_in_cmd, indent):1087        int_indent = indent1088        inline_enum_str = self.writeIndent(int_indent)1089        inline_enum_str += '// Make sure the enum type %s value is valid\n' % param_type1090        inline_enum_str += self.writeIndent(int_indent)1091        pointer_string = ''1092        if param_is_pointer:1093            pointer_string = '*'1094        instance_info_string = 'instance_info'1095        error_prefix = ''1096        if is_in_cmd:1097            if cmd_struct_name == 'xrCreateInstance':1098                instance_info_string = 'nullptr'1099            else:1100                instance_info_string = 'gen_instance_info'1101            error_prefix = 'Invalid'1102        else:1103            error_prefix = '%s contains invalid' % cmd_struct_name1104        inline_enum_str += 'if (!ValidateXrEnum(%s, %s, "%s", "%s", objects_info, %s%s)) {\n' % (1105            instance_info_string, cmd_name_param, cmd_struct_name, param_name, pointer_string, full_param_name)1106        int_indent = int_indent + 11107        inline_enum_str += self.writeIndent(int_indent)1108        inline_enum_str += 'std::ostringstream oss_enum;\n'1109        inline_enum_str += self.writeIndent(int_indent)1110        inline_enum_str += 'oss_enum << "%s %s \\"%s\\" enum value ";\n' % (error_prefix,1111                                                                            param_type,1112                                                                            param_name)1113        inline_enum_str += self.writeIndent(int_indent)1114        inline_enum_str += 'oss_enum << Uint32ToHexString(static_cast<uint32_t>(%s%s));\n' % (pointer_string,1115                                                                                              full_param_name)1116        inline_enum_str += self.writeIndent(int_indent)1117        inline_enum_str += 'CoreValidLogMessage(%s, "VUID-%s-%s-parameter",\n' % (instance_info_string,1118                                                                                  cmd_struct_name,1119                                                                                  param_name)1120        inline_enum_str += self.writeIndent(int_indent)1121        inline_enum_str += '                    VALID_USAGE_DEBUG_SEVERITY_ERROR, %s,\n' % cmd_name_param1122        inline_enum_str += self.writeIndent(int_indent)1123        inline_enum_str += '                    objects_info, oss_enum.str());\n'1124        inline_enum_str += self.writeIndent(int_indent)1125        inline_enum_str += 'return XR_ERROR_VALIDATION_FAILURE;\n'1126        int_indent = int_indent - 11127        inline_enum_str += self.writeIndent(int_indent)1128        inline_enum_str += '}\n'1129        return inline_enum_str1130    # Write an inline check to make sure a flag is valid1131    #   self                the ValidationSourceOutputGenerator object1132    #   cmd_struct_name     the name of the structure or command generating this validation check.1133    #   cmd_name_param      the name of the parameter containing the command name1134    #   param_type          the type of flag to validate getting validated1135    #   param_name          the name of the parameter to validate1136    #   full_param_name     the full name of the parameter to check (usually cmd_struct_name +1137    #                       member_param_name in some fashion)1138    #   param_is_pointer    Boolean indicating that the parameter is a pointer1139    #   is_optional         Boolean indicating that the parameter is optional1140    #   is_in_cmd           Boolean indicating that this is being called directly from inside a command1141    #   indent              the number of "tabs" to space in for the resulting C+ code.1142    def writeValidateInlineFlag(self, cmd_struct_name, cmd_name_param, param_type, param_name, full_param_name,1143                                param_is_pointer, is_optional, is_in_cmd, indent):1144        int_indent = indent1145        inline_flag_str = self.writeIndent(int_indent)1146        # Add underscore between lowercase then uppercase1147        result_name = re.sub('([a-z0-9])([A-Z])', r'\1_\2', param_type)1148        # Change to uppercase1149        result_name = result_name[3:].lower()1150        result_name += '_result'1151        pointer_string = ''1152        if param_is_pointer:1153            pointer_string = '*'1154        instance_info_string = 'instance_info'1155        error_prefix = ''1156        if is_in_cmd:1157            if cmd_struct_name == 'xrCreateInstance':1158                instance_info_string = 'nullptr'1159            else:1160                instance_info_string = 'gen_instance_info'1161            error_prefix = 'Invalid'1162        else:1163            error_prefix = '%s invalid member' % cmd_struct_name1164        inline_flag_str += 'ValidateXrFlagsResult %s = ValidateXr%s(%s%s);\n' % (result_name,1165                                                                                 param_type[2:],1166                                                                                 pointer_string,1167                                                                                 full_param_name)1168        if self.flagHasValidValues(param_type):1169            if not is_optional:1170                # Must be non-zero1171                inline_flag_str += self.writeIndent(int_indent)1172                inline_flag_str += '// Flags must be non-zero in this case.\n'1173                inline_flag_str += self.writeIndent(int_indent)1174                inline_flag_str += 'if (VALIDATE_XR_FLAGS_ZERO == %s) {\n' % result_name1175                int_indent = int_indent + 11176                inline_flag_str += self.writeIndent(int_indent)1177                inline_flag_str += 'CoreValidLogMessage(%s, "VUID-%s-%s-requiredbitmask",\n' % (instance_info_string,1178                                                                                                cmd_struct_name,1179                                                                                                param_name)1180                inline_flag_str += self.writeIndent(int_indent)1181                inline_flag_str += '                    VALID_USAGE_DEBUG_SEVERITY_ERROR, %s,\n' % cmd_name_param1182                inline_flag_str += self.writeIndent(int_indent)1183                inline_flag_str += '                    objects_info, "%s \\"%s\\" flag must be non-zero");\n' % (param_type,1184                                                                                                                  param_name)1185                inline_flag_str += self.writeIndent(int_indent)1186                inline_flag_str += 'return XR_ERROR_VALIDATION_FAILURE;\n'1187                int_indent = int_indent - 11188                inline_flag_str += self.writeIndent(int_indent)1189                inline_flag_str += '} else if (VALIDATE_XR_FLAGS_SUCCESS != %s) {\n' % result_name1190            else:1191                inline_flag_str += self.writeIndent(int_indent)1192                inline_flag_str += '// Valid flags available, so it must be invalid to fail.\n'1193                inline_flag_str += self.writeIndent(int_indent)1194                inline_flag_str += 'if (VALIDATE_XR_FLAGS_INVALID == %s) {\n' % result_name1195            int_indent = int_indent + 11196            inline_flag_str += self.writeIndent(int_indent)1197            inline_flag_str += '// Otherwise, flags must be valid.\n'1198            inline_flag_str += self.writeIndent(int_indent)1199            inline_flag_str += 'std::ostringstream oss_enum;\n'1200            inline_flag_str += self.writeIndent(int_indent)1201            inline_flag_str += 'oss_enum << "%s %s \\"%s\\" flag value ";\n' % (error_prefix,1202                                                                                param_type,1203                                                                                param_name)1204            inline_flag_str += self.writeIndent(int_indent)1205            inline_flag_str += 'oss_enum << Uint32ToHexString(static_cast<uint32_t>(%s%s));\n' % (pointer_string,1206                                                                                                  full_param_name)1207            inline_flag_str += self.writeIndent(int_indent)1208            inline_flag_str += 'oss_enum <<" contains illegal bit";\n'1209            inline_flag_str += self.writeIndent(int_indent)1210            inline_flag_str += 'CoreValidLogMessage(%s, "VUID-%s-%s-parameter",\n' % (instance_info_string,1211                                                                                      cmd_struct_name,1212                                                                                      param_name)1213            inline_flag_str += self.writeIndent(int_indent)1214            inline_flag_str += '                    VALID_USAGE_DEBUG_SEVERITY_ERROR, %s,\n' % cmd_name_param1215            inline_flag_str += self.writeIndent(int_indent)1216            inline_flag_str += '                    objects_info, oss_enum.str());\n'1217            inline_flag_str += self.writeIndent(int_indent)1218            inline_flag_str += 'return XR_ERROR_VALIDATION_FAILURE;\n'1219            int_indent = int_indent - 11220            inline_flag_str += self.writeIndent(int_indent)1221            inline_flag_str += '}\n'1222        else:1223            # Must be zero1224            inline_flag_str += self.writeIndent(int_indent)1225            inline_flag_str += '// Flags must be zero in this case.\n'1226            inline_flag_str += self.writeIndent(int_indent)1227            inline_flag_str += 'if (VALIDATE_XR_FLAGS_ZERO != %s) {\n' % result_name1228            int_indent = int_indent + 11229            inline_flag_str += self.writeIndent(int_indent)1230            inline_flag_str += 'CoreValidLogMessage(%s, "VUID-%s-%s-zerobitmask",\n' % (instance_info_string,1231                                                                                        cmd_struct_name,1232                                                                                        param_name)1233            inline_flag_str += self.writeIndent(int_indent)1234            inline_flag_str += '                    VALID_USAGE_DEBUG_SEVERITY_ERROR, %s,\n' % cmd_name_param1235            inline_flag_str += self.writeIndent(int_indent)1236            inline_flag_str += '                    objects_info, "%s \\"%s\\" flag must be zero");\n' % (param_type,1237                                                                                                          param_name)1238            inline_flag_str += self.writeIndent(int_indent)1239            inline_flag_str += 'return XR_ERROR_VALIDATION_FAILURE;\n'1240            int_indent = int_indent - 11241            inline_flag_str += self.writeIndent(int_indent)1242            inline_flag_str += '}\n'1243        return inline_flag_str1244    # Write an inline check to make sure a handle is valid1245    #   self                the ValidationSourceOutputGenerator object1246    #   cmd_name            the name of the command generating this validation check.1247    #   vuid_name           the name of the structure or command to put in the VUID1248    #   member_param        the member or parameter generated in automatic_source_generator.py to validate1249    #   mem_par_desc_name   Descriptive name of parameter1250    #   return_on_null      Boolean indicating we need to return immediately if we encounter a NULL1251    #   instance_info_name  Name of the parameter storing the instance information1252    #   element_in_array    This is a single element in an array1253    #   indent              the number of "tabs" to space in for the resulting C+ code.1254    def writeValidateInlineHandleValidation(self, cmd_name, vuid_name, member_param, mem_par_desc_name,1255                                            return_on_null, instance_info_name,1256                                            element_in_array, indent):1257        inline_validate_handle = ''1258        adjust_to_pointer = ''1259        if (not element_in_array and member_param.pointer_count == 0) or (element_in_array and member_param.pointer_count == 1):1260            adjust_to_pointer = '&'1261        inline_validate_handle += self.writeIndent(indent)1262        inline_validate_handle += '{\n'1263        indent += 11264        inline_validate_handle += self.writeIndent(indent) + "// writeValidateInlineHandleValidation\n"1265        inline_validate_handle += self.writeIndent(indent)1266        inline_validate_handle += 'ValidateXrHandleResult handle_result = Verify%sHandle(%s%s);\n' % (member_param.type, adjust_to_pointer,1267                                                                               mem_par_desc_name)1268        wrote_first_if = False1269        if member_param.is_optional:1270            # If we have to return on a Handle that has a value of XR_NULL_HANDLE, do so.1271            if return_on_null:1272                wrote_first_if = True1273                inline_validate_handle += self.writeIndent(indent)1274                inline_validate_handle += 'if (handle_result == VALIDATE_XR_HANDLE_NULL) {\n'1275                inline_validate_handle += self.writeIndent(indent + 1)1276                inline_validate_handle += '// Handle is optional so NULL is valid.  But we can\'t do anything else, either.\n'1277                inline_validate_handle += self.writeIndent(indent + 1)1278                inline_validate_handle += 'return XR_SUCCESS;\n'1279                inline_validate_handle += self.writeIndent(indent)1280                inline_validate_handle += '}'1281        # Otherwise, catch the non-success case.  If we catch the NULL handle above, we add an "else" to1282        # the if below.1283        if not member_param.no_auto_validity:1284            if wrote_first_if:1285                inline_validate_handle += ' else '1286            else:1287                inline_validate_handle += self.writeIndent(indent)1288            indent = indent + 11289            if member_param.is_optional:1290                inline_validate_handle += 'if (handle_result == VALIDATE_XR_HANDLE_INVALID) {\n'1291                inline_validate_handle += self.writeIndent(indent)1292                inline_validate_handle += '// Not a valid handle\n'1293            else:1294                inline_validate_handle += 'if (handle_result != VALIDATE_XR_HANDLE_SUCCESS) {\n'1295                inline_validate_handle += self.writeIndent(indent)1296                inline_validate_handle += '// Not a valid handle or NULL (which is not valid in this case)\n'1297            inline_validate_handle += self.writeIndent(indent)1298            inline_validate_handle += 'std::ostringstream oss;\n'1299            inline_validate_handle += self.writeIndent(indent)1300            inline_validate_handle += 'oss << "Invalid %s handle \\"%s\\" ";\n' % (member_param.type,1301                                                                                   member_param.name)1302            inline_validate_handle += self.writeIndent(indent)1303            inline_validate_handle += 'oss << HandleToHexString(%s);\n' % mem_par_desc_name1304            inline_validate_handle += self.writeIndent(indent)1305            inline_validate_handle += 'CoreValidLogMessage(%s, "VUID-%s-%s-parameter",\n' % (instance_info_name,1306                                                                                             vuid_name,1307                                                                                             member_param.name)1308            inline_validate_handle += self.writeIndent(indent)1309            inline_validate_handle += '                    VALID_USAGE_DEBUG_SEVERITY_ERROR, %s,\n' % cmd_name1310            inline_validate_handle += self.writeIndent(indent)1311            inline_validate_handle += '                    objects_info, oss.str());\n'1312            inline_validate_handle += self.writeIndent(indent)1313            inline_validate_handle += 'return XR_ERROR_HANDLE_INVALID;\n'1314            indent = indent - 11315            inline_validate_handle += self.writeIndent(indent)1316            inline_validate_handle += '}\n'1317        else:1318            inline_validate_handle += '\n'1319        indent -= 11320        inline_validate_handle += self.writeIndent(indent)1321        inline_validate_handle += '}\n'1322        return inline_validate_handle1323    def outputParamMemberContents(self, is_command, struct_command_name, param_member, param_member_prefix, instance_info_variable,1324                                  command_name_variable, is_first_param, primary_handle, primary_handle_desc_name, primary_handle_tuple,1325                                  wrote_handle_proto, indent):1326        param_member_contents = ''1327        is_loop = False1328        is_pointer = False1329        is_array = param_member.is_array1330        check_pointer_array_null = False1331        loop_string = ''1332        wrote_loop = False1333        prefixed_param_member_name = param_member_prefix1334        prefixed_param_member_name += param_member.name1335        pre_loop_prefixed_param_member_name = prefixed_param_member_name1336        loop_param_name = 'value_'1337        loop_param_name += param_member.name.lower()1338        loop_param_name += '_inc'1339        if param_member.array_count_var:1340            is_array = True1341            if param_member.pointer_count > 0:1342                is_pointer = True1343        elif param_member.pointer_count_var:1344            is_array = True1345            if param_member.pointer_count > 1:1346                is_pointer = True1347        elif param_member.pointer_count > 0:1348            is_pointer = True1349        if is_array or is_pointer:1350            check_pointer_array_null = not param_member.is_optional and not param_member.is_static_array1351        short_count_var = None1352        full_count_var = None1353        if is_array:1354            long_count_name = param_member_prefix1355            if param_member.is_static_array:1356                short_count_var = param_member.static_array_sizes[0]1357                long_count_name = param_member.static_array_sizes[0]1358            elif param_member.array_count_var:1359                short_count_var = param_member.array_count_var1360                if self.isAllUpperCase(param_member.array_count_var):1361                    long_count_name = param_member.array_count_var1362                else:1363                    long_count_name += param_member.array_count_var1364            else:1365                short_count_var = param_member.pointer_count_var1366                if self.isAllUpperCase(param_member.pointer_count_var):1367                    long_count_name = param_member.pointer_count_var1368                else:1369                    long_count_name += param_member.pointer_count_var1370            if check_pointer_array_null:1371                full_count_var = long_count_name1372                param_member_contents += self.writeValidatePointerArrayNonNull(struct_command_name,1373                                                                               param_member.name,1374                                                                               param_member.type,1375                                                                               prefixed_param_member_name,1376                                                                               full_count_var,1377                                                                               short_count_var,1378                                                                               is_command,1379                                                                               indent)1380            if (param_member.is_handle or self.isEnumType(param_member.type) or1381                    (self.isStruct(param_member.type) and not self.isStructAlwaysValid(param_member.type))):1382                loop_string += self.writeIndent(indent)1383                loop_string += 'if (%s) {\n' % (prefixed_param_member_name)1384                indent = indent + 11385                loop_string += self.writeIndent(indent)1386                loop_string += 'for (uint32_t %s = 0; %s < %s; ++%s) {\n' % (loop_param_name,1387                                                                             loop_param_name,1388                                                                             long_count_name,1389                                                                             loop_param_name)1390                indent = indent + 11391                prefixed_param_member_name = '%s[%s]' % (1392                    prefixed_param_member_name, loop_param_name)1393                is_loop = True1394        elif check_pointer_array_null:1395            param_member_contents += self.writeValidatePointerArrayNonNull(struct_command_name,1396                                                                           param_member.name,1397                                                                           param_member.type,1398                                                                           prefixed_param_member_name,1399                                                                           None,1400                                                                           None,1401                                                                           is_command,1402                                                                           indent)1403        if not param_member.is_static_array and param_member.array_length_for:1404            if param_member.is_optional:1405                param_member_contents += self.writeIndent(indent)1406                param_member_contents += '// Optional array must be non-NULL when %s is non-zero\n' % prefixed_param_member_name1407                param_member_contents += self.writeIndent(indent)1408                param_member_contents += 'if (0 != %s && nullptr == %s%s) {\n' % (1409                    prefixed_param_member_name, param_member_prefix, param_member.array_length_for)1410                param_member_contents += self.writeIndent(indent + 1)1411                param_member_contents += 'CoreValidLogMessage(%s, "VUID-%s-%s-parameter",\n' % (instance_info_variable,1412                                                                                                struct_command_name,1413                                                                                                param_member.array_length_for)1414                param_member_contents += self.writeIndent(indent + 1)1415                param_member_contents += '                    VALID_USAGE_DEBUG_SEVERITY_ERROR, %s,\n' % command_name_variable1416                param_member_contents += self.writeIndent(indent + 1)1417                param_member_contents += '                    objects_info,\n'1418                param_member_contents += self.writeIndent(indent + 1)1419                param_member_contents += '                    '1420                if is_command:1421                    param_member_contents += '"Command %s param %s' % (1422                        struct_command_name, param_member.array_length_for)1423                else:1424                    param_member_contents += '"Structure %s member %s' % (1425                        struct_command_name, param_member.name)1426                param_member_contents += ' is NULL, but %s is greater than 0");\n' % prefixed_param_member_name1427                param_member_contents += self.writeIndent(indent + 1)1428                param_member_contents += 'return XR_ERROR_VALIDATION_FAILURE;\n'1429                param_member_contents += self.writeIndent(indent)1430                param_member_contents += '}\n'1431            else:1432                param_member_contents += self.writeIndent(indent)1433                param_member_contents += '// Non-optional array length must be non-zero\n'1434                param_member_contents += self.writeIndent(indent)1435                param_member_contents += 'if (0 >= %s && nullptr != %s%s) {\n' % (1436                    prefixed_param_member_name, param_member_prefix, param_member.array_length_for)1437                param_member_contents += self.writeIndent(indent + 1)1438                param_member_contents += 'CoreValidLogMessage(%s, "VUID-%s-%s-arraylength",\n' % (instance_info_variable,1439                                                                                                  struct_command_name,1440                                                                                                  param_member.name)1441                param_member_contents += self.writeIndent(indent + 1)1442                param_member_contents += '                    VALID_USAGE_DEBUG_SEVERITY_ERROR, %s,\n' % command_name_variable1443                param_member_contents += self.writeIndent(indent + 1)1444                param_member_contents += '                    objects_info,\n'1445                param_member_contents += self.writeIndent(indent + 1)1446                param_member_contents += '                    '1447                if is_command:1448                    param_member_contents += '"Command %s param %s' % (1449                        struct_command_name, param_member.name)1450                else:1451                    param_member_contents += '"Structure %s member %s' % (1452                        struct_command_name, param_member.name)1453                param_member_contents += ' is non-optional and must be greater than 0");\n'1454                param_member_contents += self.writeIndent(indent + 1)1455                param_member_contents += 'xr_result = XR_ERROR_VALIDATION_FAILURE;\n'1456                param_member_contents += self.writeIndent(indent)1457                param_member_contents += '}\n'1458        first_time_handle_check = not wrote_handle_proto1459        if param_member.is_handle:1460            if param_member.pointer_count == 0:1461                param_member_contents += self.writeValidateInlineHandleValidation(command_name_variable,1462                                                                                  struct_command_name,1463                                                                                  param_member,1464                                                                                  prefixed_param_member_name,1465                                                                                  is_command,1466                                                                                  instance_info_variable,1467                                                                                  False,1468                                                                                  indent)1469                # If the first item is a handle, and this is a different handle, we need to verify that1470                # one is either the parent of the other, or that they share a common ancestor.1471                if primary_handle_tuple is not None and not first_time_handle_check:1472                    current_handle_tuple = self.getHandle(param_member.type)1473                    param_member_contents += self.writeInlineParentCheckCall(instance_info_variable,1474                                                                             primary_handle_tuple,1475                                                                             primary_handle,1476                                                                             primary_handle_desc_name,1477                                                                             current_handle_tuple,1478                                                                             param_member,1479                                                                             prefixed_param_member_name,1480                                                                             struct_command_name,1481                                                                             command_name_variable,1482                                                                             indent)1483                elif not is_command:1484                    primary_handle_tuple = self.getHandle(param_member.type)1485                    primary_handle = param_member1486                    primary_handle_desc_name = prefixed_param_member_name1487            elif is_array:1488                param_member_contents += loop_string1489                wrote_loop = True1490                param_member_contents += self.writeValidateInlineHandleValidation(command_name_variable,1491                                                                                  struct_command_name,1492                                                                                  param_member,1493                                                                                  prefixed_param_member_name,1494                                                                                  is_command,1495                                                                                  instance_info_variable,1496                                                                                  True,1497                                                                                  indent)1498        elif self.isStruct(param_member.type) and not self.isStructAlwaysValid(param_member.type):1499            param_member_contents += loop_string1500            wrote_loop = True1501            # Check to see if this struct is the base of a relation group1502            relation_group = self.getRelationGroupForBaseStruct(param_member.type)1503            is_relation_group = (relation_group is not None)1504            # If this struct is the base of a relation group, check to see if this call really should go to any one of1505            # it's children instead of itself.1506            if is_relation_group:1507                for child in relation_group.child_struct_names:1508                    child_struct = self.getStruct(child)1509                    if child_struct.protect_value:1510                        param_member_contents += '#if %s\n' % child_struct.protect_string1511                    param_member_contents += self.writeIndent(indent)1512                    param_member_contents += '// Validate if %s is a child structure of type %s and it is valid\n' % (1513                        param_member.type, child)1514                    param_member_contents += self.writeIndent(indent)1515                    param_member_contents += '{\n'1516                    indent = indent + 11517                    param_member_contents += self.writeIndent(indent)1518                    base_child_struct_name = undecorate(child)1519                    if is_pointer or is_array:1520                        new_type_info = param_member.cdecl.replace(1521                            param_member.type, child)1522                        new_type_info = new_type_info.replace(1523                            param_member.name, "")1524                        new_type_info = new_type_info.strip().rstrip()1525                        param_member_contents += '%s new_%s_value = reinterpret_cast<%s>(%s);\n' % (1526                            new_type_info, base_child_struct_name, new_type_info, pre_loop_prefixed_param_member_name)1527                        param_member_contents += self.writeIndent(indent)1528                        deref_string = '->' if is_pointer else '.'1529                        if is_array:1530                            param_member_contents += 'if (new_%s_value[%s]%stype == %s) {\n' % (1531                                base_child_struct_name, loop_param_name, deref_string, self.genXrStructureType(child))1532                        else:1533                            param_member_contents += 'if (new_%s_value%stype == %s) {\n' % (1534                                base_child_struct_name, deref_string, self.genXrStructureType(child))1535                    else:1536                        param_member_contents += 'const %s* new_%s_value = reinterpret_cast<const %s*>(&%s);\n' % (1537                            child, base_child_struct_name, child, pre_loop_prefixed_param_member_name)1538                        param_member_contents += self.writeIndent(indent)1539                        param_member_contents += 'if (new_%s_value->type == %s) {\n' % (1540                            base_child_struct_name, self.genXrStructureType(child))1541                    indent = indent + 11542                    if param_member.is_optional:1543                        param_member_contents += self.writeIndent(indent)1544                        param_member_contents += 'if (nullptr != new_%s_value) {\n' % base_child_struct_name1545                        indent = indent + 11546                        param_member_contents += self.writeIndent(indent)1547                        param_member_contents += 'xr_result = ValidateXrStruct(%s, %s,\n' % (1548                            instance_info_variable, command_name_variable)1549                        param_member_contents += self.writeIndent(indent)1550                        param_member_contents += '                                                objects_info,'1551                        if is_command:1552                            param_member_contents += ' false,'1553                        else:1554                            param_member_contents += ' check_members,'1555                        if is_array:1556                            if is_pointer:1557                                param_member_contents += ' new_%s_value[%s]);\n' % (1558                                    base_child_struct_name, loop_param_name)1559                            else:1560                                param_member_contents += ' &new_%s_value[%s]);\n' % (1561                                    base_child_struct_name, loop_param_name)1562                        else:1563                            param_member_contents += ' new_%s_value);\n' % base_child_struct_name1564                    else:1565                        param_member_contents += self.writeIndent(indent)1566                        param_member_contents += 'xr_result = ValidateXrStruct(%s, %s,\n' % (1567                            instance_info_variable, command_name_variable)1568                        param_member_contents += self.writeIndent(indent)1569                        param_member_contents += '                                                objects_info,'1570                        if is_command:1571                            param_member_contents += 'false,'1572                        else:1573                            param_member_contents += ' check_members,'1574                        if is_array:1575                            param_member_contents += ' new_%s_value[%s]);\n' % (1576                                base_child_struct_name, loop_param_name)1577                        else:1578                            param_member_contents += ' new_%s_value);\n' % base_child_struct_name1579                    param_member_contents += self.writeIndent(indent)1580                    param_member_contents += 'if (XR_SUCCESS != xr_result) {\n'1581                    indent = indent + 11582                    param_member_contents += self.writeIndent(indent)1583                    param_member_contents += 'std::string error_message = "'1584                    if is_command:1585                        param_member_contents += 'Command %s param %s";\n' % (1586                            struct_command_name, param_member.name)1587                    else:1588                        param_member_contents += 'Structure %s member %s";\n' % (1589                            struct_command_name, param_member.name)1590                    if is_array:1591                        param_member_contents += self.writeIndent(indent)1592                        param_member_contents += 'error_message += "[";\n'1593                        param_member_contents += self.writeIndent(indent)1594                        param_member_contents += 'error_message += std::to_string(%s);\n' % loop_param_name1595                        param_member_contents += self.writeIndent(indent)1596                        param_member_contents += 'error_message += "]";\n'1597                    param_member_contents += self.writeIndent(indent)1598                    param_member_contents += 'error_message += " is invalid";\n'1599                    param_member_contents += self.writeIndent(indent)1600                    param_member_contents += 'CoreValidLogMessage(%s, "VUID-%s-%s-parameter",\n' % (1601                        instance_info_variable, struct_command_name, param_member.name)1602                    param_member_contents += self.writeIndent(indent)1603                    param_member_contents += '                    VALID_USAGE_DEBUG_SEVERITY_ERROR, %s,\n' % command_name_variable1604                    param_member_contents += self.writeIndent(indent)1605                    param_member_contents += '                    objects_info,\n'1606                    param_member_contents += self.writeIndent(indent)1607                    param_member_contents += '                    error_message);\n'1608                    param_member_contents += self.writeIndent(indent)1609                    param_member_contents += 'return XR_ERROR_VALIDATION_FAILURE;\n'1610                    if is_array:1611                        param_member_contents += self.writeIndent(indent)1612                        param_member_contents += 'break;\n'1613                        param_member_contents += self.writeIndent(indent - 1)1614                        param_member_contents += '} else {\n'1615                        param_member_contents += self.writeIndent(indent)1616                        param_member_contents += 'continue;\n'1617                    if param_member.is_optional:1618                        param_member_contents += self.writeIndent(indent)1619                        param_member_contents += '}\n'1620                        indent = indent - 11621                    indent = indent - 11622                    param_member_contents += self.writeIndent(indent)1623                    param_member_contents += '}\n'1624                    indent = indent - 11625                    param_member_contents += self.writeIndent(indent)1626                    param_member_contents += '}\n'1627                    indent = indent - 11628                    param_member_contents += self.writeIndent(indent)1629                    param_member_contents += '}\n'1630                    if child_struct.protect_value:1631                        param_member_contents += '#endif // %s\n' % child_struct.protect_string1632            param_member_contents += self.writeIndent(indent)1633            if is_relation_group:1634                param_member_contents += '// Validate that the base-structure %s is valid\n' % (1635                                         param_member.type)1636            else:1637                param_member_contents += '// Validate that the structure %s is valid\n' % (1638                                         param_member.type)1639            param_member_contents += self.writeIndent(indent)1640            if is_pointer:1641                if param_member.is_optional:1642                    param_member_contents += 'if (nullptr != %s) {\n' % prefixed_param_member_name1643                    indent = indent + 11644                    param_member_contents += self.writeIndent(indent)1645                    param_member_contents += 'xr_result = ValidateXrStruct(%s, %s,\n' % (1646                        instance_info_variable, command_name_variable)1647                    param_member_contents += self.writeIndent(indent)1648                    param_member_contents += '                                                objects_info,'1649                    if is_command:1650                        param_member_contents += ' false,'1651                    else:1652                        param_member_contents += ' check_members,'1653                    param_member_contents += ' %s);\n' % prefixed_param_member_name1654                else:1655                    param_member_contents += 'xr_result = ValidateXrStruct(%s, %s, objects_info,\n' % (1656                        instance_info_variable, command_name_variable)1657                    param_member_contents += self.writeIndent(indent)1658                    param_member_contents += '                                                '1659                    if is_command:1660                        if param_member.is_const:1661                            param_member_contents += 'true,'1662                        else:1663                            param_member_contents += 'false,'1664                    else:1665                        param_member_contents += 'check_members,'1666                    param_member_contents += ' %s);\n' % prefixed_param_member_name1667            else:1668                param_member_contents += 'xr_result = ValidateXrStruct(%s, %s, objects_info,\n' % (1669                    instance_info_variable, command_name_variable)1670                param_member_contents += self.writeIndent(indent)1671                param_member_contents += '                                                '1672                if is_command:1673                    param_member_contents += 'true,'1674                else:1675                    param_member_contents += 'check_members,'1676                param_member_contents += ' &%s);\n' % prefixed_param_member_name1677            param_member_contents += self.writeIndent(indent)1678            param_member_contents += 'if (XR_SUCCESS != xr_result) {\n'1679            indent = indent + 11680            param_member_contents += self.writeIndent(indent)1681            param_member_contents += 'CoreValidLogMessage(%s, "VUID-%s-%s-parameter",\n' % (1682                instance_info_variable, struct_command_name, param_member.name)1683            param_member_contents += self.writeIndent(indent)1684            param_member_contents += '                    VALID_USAGE_DEBUG_SEVERITY_ERROR, %s,\n' % command_name_variable1685            param_member_contents += self.writeIndent(indent)1686            param_member_contents += '                    objects_info,\n'1687            param_member_contents += self.writeIndent(indent)1688            param_member_contents += '                    '1689            if is_command:1690                param_member_contents += '"Command %s param %s' % (1691                    struct_command_name, param_member.name)1692            else:1693                param_member_contents += '"Structure %s member %s' % (1694                    struct_command_name, param_member.name)1695            param_member_contents += ' is invalid");\n'1696            param_member_contents += self.writeIndent(indent)1697            param_member_contents += 'return xr_result;\n'1698            indent = indent - 11699            if is_pointer and param_member.is_optional:1700                param_member_contents += self.writeIndent(indent)1701                param_member_contents += '}\n'1702                indent = indent - 11703            param_member_contents += self.writeIndent(indent)1704            param_member_contents += '}\n'1705        elif self.isEnumType(param_member.type):1706            if is_array and not param_member.is_const:1707                param_member_contents += self.writeIndent(indent)1708                param_member_contents += '// NOTE: Can\'t validate "VUID-%s-%s-parameter" output enum buffer\n' % (struct_command_name, param_member.name)1709            else:1710                if is_array:1711                    param_member_contents += loop_string1712                    wrote_loop = True1713                param_member_contents += self.writeValidateInlineEnum(struct_command_name,1714                                                                    command_name_variable,1715                                                                    param_member.type,1716                                                                    param_member.name,1717                                                                    prefixed_param_member_name,1718                                                                    is_pointer,1719                                                                    is_command,1720                                                                    indent)1721        elif self.isFlagType(param_member.type):1722            param_member_contents += self.writeValidateInlineFlag(struct_command_name,1723                                                                  command_name_variable,1724                                                                  param_member.type,1725                                                                  param_member.name,1726                                                                  prefixed_param_member_name,1727                                                                  is_pointer,1728                                                                  param_member.is_optional,1729                                                                  is_command,1730                                                                  indent)1731        elif "void" not in param_member.type:1732            if param_member.is_null_terminated:1733                param_member_contents += self.writeIndent(indent)1734                param_member_contents += '// NOTE: Can\'t validate "VUID-%s-%s-parameter" null-termination\n' % (struct_command_name,1735                                                                                                                 param_member.name)1736            elif param_member.pointer_count > 0:1737                param_member_contents += self.writeIndent(indent)1738                param_member_contents += '// NOTE: Can\'t validate "VUID-%s-%s-parameter" type\n' % (struct_command_name,1739                                                                                                     param_member.name)1740            elif param_member.is_static_array and "char" in param_member.type:1741                param_member_contents += self.writeIndent(indent)1742                param_member_contents += 'if (%s < std::strlen(%s)) {\n' % (1743                    param_member.static_array_sizes[0], prefixed_param_member_name)1744                indent = indent + 11745                param_member_contents += self.writeIndent(indent)1746                param_member_contents += 'CoreValidLogMessage(%s, "VUID-%s-%s-parameter",\n' % (1747                    instance_info_variable, struct_command_name, param_member.name)1748                param_member_contents += self.writeIndent(indent)1749                param_member_contents += '                    VALID_USAGE_DEBUG_SEVERITY_ERROR, %s,\n' % command_name_variable1750                param_member_contents += self.writeIndent(indent)1751                param_member_contents += '                    objects_info,\n'1752                param_member_contents += self.writeIndent(indent)1753                param_member_contents += '                    '1754                if is_command:1755                    param_member_contents += '"Command %s param %s' % (1756                        struct_command_name, param_member.name)1757                else:1758                    param_member_contents += '"Structure %s member %s' % (1759                        struct_command_name, param_member.name)1760                param_member_contents += ' length is too long.");\n'1761                param_member_contents += self.writeIndent(indent)1762                param_member_contents += 'return XR_ERROR_VALIDATION_FAILURE;\n'1763                indent = indent - 11764                param_member_contents += self.writeIndent(indent)1765                param_member_contents += '}\n'1766        if is_loop:1767            indent = indent - 21768            if wrote_loop:1769                param_member_contents += self.writeIndent(indent + 1)1770                param_member_contents += '}\n'1771                param_member_contents += self.writeIndent(indent)1772                param_member_contents += '}\n'1773        return param_member_contents1774    # Write the validation function for every struct we know about.1775    #   self            the ValidationSourceOutputGenerator object1776    def writeValidateStructFuncs(self):1777        struct_check = ''1778        # Now write out the actual functions1779        for xr_struct in self.api_structures:1780            if xr_struct.name in self.structs_with_no_type:1781                continue1782            indent = 11783            is_base_type = False1784            relation_group = None1785            if xr_struct.protect_value:1786                struct_check += '#if %s\n' % xr_struct.protect_string1787            struct_check += 'XrResult ValidateXrStruct(GenValidUsageXrInstanceInfo *instance_info, const std::string &command_name,\n'1788            struct_check += '                          std::vector<GenValidUsageXrObjectInfo>& objects_info, bool check_members,\n'1789            struct_check += '                          const %s* value) {\n' % xr_struct.name1790            setup_bail = False1791            struct_check += '    XrResult xr_result = XR_SUCCESS;\n'1792            # Check to see if this struct is the base of a relation group1793            relation_group = self.getRelationGroupForBaseStruct(xr_struct.name)1794            if relation_group is not None:1795                is_base_type = True1796            # If this struct is the base of a relation group, check to see if this call really should go to any one of1797            # it's children instead of itself.1798            if is_base_type:1799                for member in xr_struct.members:1800                    if member.name == 'next':1801                        struct_check += self.writeIndent(indent)1802                        struct_check += '// NOTE: Can\'t validate "VUID-%s-next-next" because it is a base structure\n' % xr_struct.name1803                    else:1804                        struct_check += self.writeIndent(indent)1805                        struct_check += '// NOTE: Can\'t validate "VUID-%s-%s-parameter" because it is a base structure\n' % (1806                            xr_struct.name, member.name)1807                for child in relation_group.child_struct_names:1808                    child_struct = self.getStruct(child)1809                    if child_struct.protect_value:1810                        struct_check += '#if %s\n' % child_struct.protect_string1811                    struct_check += self.writeIndent(indent)1812                    struct_check += 'if (value->type == %s) {\n' % self.genXrStructureType(1813                        child)1814                    indent += 11815                    struct_check += self.writeIndent(indent)1816                    struct_check += 'const %s* new_value = reinterpret_cast<const %s*>(value);\n' % (1817                        child, child)1818                    if child_struct.ext_name and not self.isCoreExtensionName(child_struct.ext_name):1819                        struct_check += self.writeIndent(indent)1820                        struct_check += 'if (nullptr != instance_info && !ExtensionEnabled(instance_info->enabled_extensions, "%s")) {\n' % child_struct.ext_name1821                        indent += 11822                        struct_check += self.writeIndent(indent)1823                        struct_check += 'std::string error_str = "%s being used with child struct type ";\n' % xr_struct.name1824                        struct_check += self.writeIndent(indent)1825                        struct_check += 'error_str += "\\"%s\\"";\n' % self.genXrStructureType(1826                            child)1827                        struct_check += self.writeIndent(indent)1828                        struct_check += 'error_str += " which requires extension \\"%s\\" to be enabled, but it is not enabled";\n' % child_struct.ext_name1829                        struct_check += self.writeIndent(indent)1830                        struct_check += 'CoreValidLogMessage(instance_info, "VUID-%s-type-type",\n' % (1831                            xr_struct.name)1832                        struct_check += self.writeIndent(indent)1833                        struct_check += '                    VALID_USAGE_DEBUG_SEVERITY_ERROR, command_name,\n'1834                        struct_check += self.writeIndent(indent)1835                        struct_check += '                    objects_info, error_str);\n'1836                        struct_check += self.writeIndent(indent)1837                        struct_check += 'return XR_ERROR_VALIDATION_FAILURE;\n'1838                        indent -= 11839                        struct_check += self.writeIndent(indent)1840                        struct_check += '}\n'1841                    struct_check += self.writeIndent(indent)1842                    struct_check += 'return ValidateXrStruct(instance_info, command_name, objects_info, check_members, new_value);\n'1843                    indent -= 11844                    struct_check += self.writeIndent(indent)1845                    struct_check += '}\n'1846                    if child_struct.protect_value:1847                        struct_check += '#endif // %s\n' % child_struct.protect_string1848                struct_check += self.writeIndent(indent)1849                struct_check += 'InvalidStructureType(instance_info, command_name, objects_info, "%s",\n' % xr_struct.name1850                struct_check += self.writeIndent(indent)1851                struct_check += '                     value->type, "VUID-%s-type-type");\n' % xr_struct.name1852                struct_check += self.writeIndent(indent)1853                struct_check += 'return XR_ERROR_VALIDATION_FAILURE;\n'1854                struct_check += '}\n\n'1855                continue1856            first_member_handle_tuple = None1857            first_member_handle = None1858            count = 01859            wrote_handle_check_proto = False1860            has_enable_extension_count = False1861            has_enable_extension_names = False1862            for member in xr_struct.members:1863                # If we're not supposed to check this, then skip it1864                if member.no_auto_validity:1865                    continue1866                if member.name == 'type':1867                    struct_check += self.writeIndent(indent)1868                    struct_check += '// Make sure the structure type is correct\n'1869                    struct_check += self.writeIndent(indent)1870                    struct_check += 'if (value->type != %s) {\n' % self.genXrStructureType(1871                        xr_struct.name)1872                    indent = indent + 11873                    expected = self.genXrStructureType(xr_struct.name)1874                    struct_check += self.writeIndent(indent)1875                    struct_check += 'InvalidStructureType(instance_info, command_name, objects_info, "%s",\n' % xr_struct.name1876                    struct_check += self.writeIndent(indent)1877                    struct_check += '                     value->type, "VUID-%s-type-type", %s, "%s");\n' % (1878                        xr_struct.name, expected, expected)1879                    struct_check += self.writeIndent(indent)1880                    struct_check += 'xr_result = XR_ERROR_VALIDATION_FAILURE;\n'1881                    indent = indent - 11882                    struct_check += self.writeIndent(indent)1883                    struct_check += '}\n'1884                    continue1885                elif member.name == 'next':1886                    struct_check += self.writeValidateStructNextCheck(1887                        xr_struct.name, 'value', member, indent)1888                elif member.name == 'enabledExtensionCount':1889                    has_enable_extension_count = True1890                elif member.name == 'enabledExtensionNames':1891                    has_enable_extension_names = True1892                elif not setup_bail:1893                    struct_check += self.writeIndent(indent)1894                    struct_check += '// If we are not to check the rest of the members, just return here.\n'1895                    struct_check += self.writeIndent(indent)1896                    struct_check += 'if (!check_members || XR_SUCCESS != xr_result) {\n'1897                    struct_check += self.writeIndent(indent + 1)1898                    struct_check += 'return xr_result;\n'1899                    struct_check += self.writeIndent(indent)1900                    struct_check += '}\n'1901                    setup_bail = True1902                struct_check += self.outputParamMemberContents(False, xr_struct.name, member, 'value->',1903                                                               "instance_info", "command_name",1904                                                               count == 0,1905                                                               first_member_handle,1906                                                               first_member_handle,1907                                                               first_member_handle_tuple,1908                                                               wrote_handle_check_proto,1909                                                               indent)1910                if member.is_handle:1911                    wrote_handle_check_proto = True1912                count = count + 11913            # We only have extensions to check if both the count and enable fields are there1914            if has_enable_extension_count and has_enable_extension_names:1915                # This is create instance, so check all instance extensions1916                struct_check += self.writeIndent(indent)1917                struct_check += 'std::vector<std::string> enabled_extension_vec;\n'1918                struct_check += self.writeIndent(indent)1919                struct_check += 'for (uint32_t extension = 0; extension < value->enabledExtensionCount; ++extension) {\n'1920                struct_check += self.writeIndent(indent + 1)1921                struct_check += 'enabled_extension_vec.push_back(value->enabledExtensionNames[extension]);\n'1922                struct_check += self.writeIndent(indent)1923                struct_check += '}\n'1924                if xr_struct.name == 'XrInstanceCreateInfo':1925                    struct_check += self.writeIndent(indent)1926                    struct_check += 'if (!ValidateInstanceExtensionDependencies(nullptr, command_name, "%s",\n' % xr_struct.name1927                    struct_check += self.writeIndent(indent)1928                    struct_check += '                                           objects_info, enabled_extension_vec)) {\n'1929                    struct_check += self.writeIndent(indent + 1)1930                    struct_check += 'return XR_ERROR_VALIDATION_FAILURE;\n'1931                    struct_check += self.writeIndent(indent)1932                    struct_check += '}\n'1933                else:1934                    struct_check += self.writeIndent(indent)1935                    struct_check += 'if (!ValidateSystemExtensionDependencies(instance_info, command_name, "%s",\n' % xr_struct.name1936                    struct_check += self.writeIndent(indent)1937                    struct_check += '                                         objects_info, enabled_extension_vec)) {\n'1938                    struct_check += self.writeIndent(indent + 1)1939                    struct_check += 'return XR_ERROR_VALIDATION_FAILURE;\n'1940                    struct_check += self.writeIndent(indent)1941                    struct_check += '}\n'1942            struct_check += self.writeIndent(indent)1943            struct_check += '// Everything checked out properly\n'1944            struct_check += self.writeIndent(indent)1945            struct_check += 'return xr_result;\n'1946            struct_check += '}\n\n'1947            if xr_struct.protect_value:1948                struct_check += '#endif // %s\n' % xr_struct.protect_string1949        struct_check += '\n'1950        return struct_check1951    # Write an inline validation check for handle parents1952    #   self                    the ValidationSourceOutputGenerator object1953    #   instance_info_string    string used to identify the variable associated with the instance information struct.1954    #   first_handle_tuple      the handle tuple associated with the type of the first handle1955    #   first_handle_mem_param  the member/param of the first handle1956    #   first_handle_desc_name  the descriptive name of the first handle1957    #   cur_handle_tuple        the handle tuple associated with the type of the current handle1958    #   cur_handle_mem_param    the member/param of the current handle1959    #   cur_handle_desc_name    the descriptive name of the current handle1960    #   vuid_name               the VUID identifier to associate this check and member/param name with1961    #   cmd_name_param          the parameter containing the associated command name1962    #   indent                  the number of tab-stops to indent the current inline strings1963    def writeInlineParentCheckCall(self, instance_info_string, first_handle_tuple, first_handle_mem_param, first_handle_desc_name,1964                                   cur_handle_tuple, cur_handle_mem_param, cur_handle_desc_name, vuid_name,1965                                   cmd_name_param, indent):1966        parent_check_string = ''1967        parent_id = 'commonparent'1968        if (first_handle_tuple.name == cur_handle_tuple.parent or1969                cur_handle_tuple.name == first_handle_tuple.parent):1970            parent_id = '%s-parent' % cur_handle_mem_param.name1971        parent_check_string += self.writeIndent(indent)1972        pointer_deref = ''1973        if cur_handle_mem_param.pointer_count > 0:1974            pointer_deref = '*'1975        compare_flag = 'true'1976        if first_handle_mem_param.type == cur_handle_mem_param.type:1977            compare_flag = 'false'1978        if cur_handle_mem_param.is_optional:1979            parent_check_string += '// If the second handle is optional, only check for a common parent if\n'1980            parent_check_string += self.writeIndent(indent)1981            parent_check_string += '// it is not XR_NULL_HANDLE\n'1982            parent_check_string += self.writeIndent(indent)1983            parent_check_string += 'if (!IsIntegerNullHandle(%s) && !VerifyXrParent(%s, MakeHandleGeneric(%s),\n' % (1984                cur_handle_desc_name,1985                self.genXrObjectType(first_handle_mem_param.type),1986                first_handle_desc_name)1987            parent_check_string += '                                                                                  %s,  MakeHandleGeneric(%s%s), %s)) {\n' % (1988                self.genXrObjectType(cur_handle_mem_param.type),1989                pointer_deref,1990                cur_handle_desc_name,1991                compare_flag)1992        else:1993            parent_check_string += '// Verify that the handles share a common ancestry\n'1994            parent_check_string += self.writeIndent(indent)1995            parent_check_string += 'if (!VerifyXrParent(%s,  MakeHandleGeneric(%s),\n' % (1996                self.genXrObjectType(first_handle_mem_param.type), first_handle_desc_name)1997            parent_check_string += '                    %s,  MakeHandleGeneric(%s%s), %s)) {\n' % (1998                self.genXrObjectType(cur_handle_mem_param.type), pointer_deref, cur_handle_desc_name, compare_flag)1999        indent = indent + 12000        parent_check_string += self.writeIndent(indent)2001        parent_check_string += 'std::ostringstream oss_error;\n'2002        parent_check_string += self.writeIndent(indent)2003        parent_check_string += 'oss_error << "%s " << HandleToHexString(%s);\n' % (2004            first_handle_mem_param.type, first_handle_desc_name)2005        if first_handle_tuple.name == cur_handle_tuple.parent:2006            parent_check_string += self.writeIndent(indent)2007            parent_check_string += 'oss_error << " must be a parent to %s ";\n' % cur_handle_mem_param.type2008            parent_check_string += self.writeIndent(indent)2009            parent_check_string += 'oss_error << HandleToHexString(%s);\n' % cur_handle_desc_name2010        elif cur_handle_tuple.name == first_handle_tuple.parent:2011            parent_check_string += self.writeIndent(indent)2012            parent_check_string += 'oss_error << " must be a child of %s ";\n' % cur_handle_mem_param.type2013            parent_check_string += self.writeIndent(indent)2014            parent_check_string += 'oss_error << HandleToHexString(%s);\n' % cur_handle_desc_name2015        else:2016            parent_check_string += self.writeIndent(indent)2017            parent_check_string += 'oss_error <<  " and %s ";\n' % cur_handle_mem_param.type2018            parent_check_string += self.writeIndent(indent)2019            parent_check_string += 'oss_error << HandleToHexString(%s);\n' % cur_handle_desc_name2020            parent_check_string += self.writeIndent(indent)2021            parent_check_string += 'oss_error <<  " must share a parent";\n'2022        parent_check_string += self.writeIndent(indent)2023        parent_check_string += 'CoreValidLogMessage(%s, "VUID-%s-%s",\n' % (instance_info_string,2024                                                                            vuid_name,2025                                                                            parent_id)2026        parent_check_string += self.writeIndent(indent)2027        parent_check_string += '                    VALID_USAGE_DEBUG_SEVERITY_ERROR, %s,\n' % cmd_name_param2028        parent_check_string += self.writeIndent(indent)2029        parent_check_string += '                    objects_info, oss_error.str());\n'2030        parent_check_string += self.writeIndent(indent)2031        parent_check_string += 'return XR_ERROR_VALIDATION_FAILURE;\n'2032        indent = indent - 12033        parent_check_string += self.writeIndent(indent)2034        parent_check_string += '}\n'2035        return parent_check_string2036    # Generate C++ code to validate the inputs of the current command.2037    #   self            the ValidationSourceOutputGenerator object2038    #   cur_command     the command generated in automatic_source_generator.py to validate2039    def genValidateInputsFunc(self, cur_command):2040        pre_validate_func = ''2041        pre_validate_func += 'XrResult %s(' % cur_command.name.replace("xr",2042                                                                       "GenValidUsageInputsXr")2043        pre_validate_func += '\n'2044        pre_validate_func += ',\n'.join((param.cdecl.strip() for param in cur_command.params))2045        pre_validate_func += ') {\n'2046        wrote_handle_check_proto = False2047        command_name_string = '"%s"' % cur_command.name2048        # If the first parameter is a handle and we either have to validate that handle, or check2049        # for extension information, then we will need the instance information.2050        indent = 12051        pre_validate_func += self.writeIndent(indent)2052        pre_validate_func += 'try {\n'2053        indent = indent + 12054        pre_validate_func += self.writeIndent(indent)2055        pre_validate_func += 'XrResult xr_result = XR_SUCCESS;\n'2056        pre_validate_func += self.writeIndent(indent)2057        pre_validate_func += 'std::vector<GenValidUsageXrObjectInfo> objects_info;\n'2058        first_param = cur_command.params[0]2059        first_param_tuple = self.getHandle(first_param.type)2060        if first_param_tuple is not None:2061            first_handle_name = self.getFirstHandleName(first_param)2062            obj_type = self.genXrObjectType(first_param.type)2063            pre_validate_func += self.writeIndent(indent)2064            pre_validate_func += 'objects_info.emplace_back(%s, %s);\n\n'% (first_handle_name, obj_type)2065            # Must verify this param first.2066            # Can skip validating it later.2067            pre_validate_func += self.outputParamMemberContents(True, cur_command.name, first_param, '',2068                                                                'nullptr', # no instance_info yet!2069                                                                command_name_string,2070                                                                True,2071                                                                first_param,2072                                                                first_param.name,2073                                                                first_param_tuple,2074                                                                wrote_handle_check_proto,2075                                                                indent)2076            wrote_handle_check_proto = True2077            if first_param_tuple.name == 'XrInstance':2078                pre_validate_func += self.writeIndent(indent)2079                pre_validate_func += 'GenValidUsageXrInstanceInfo *gen_instance_info = g_instance_info.get(%s);\n' % first_handle_name2080            else:2081                pre_validate_func += self.writeIndent(indent)2082                pre_validate_func += 'auto info_with_instance = %s.getWithInstanceInfo(%s);\n' % (2083                    self.makeInfoName(handle_type_name=first_param.type), first_handle_name)2084                pre_validate_func += self.writeIndent(indent)2085                pre_validate_func += 'GenValidUsageXrHandleInfo *gen_%s_info = info_with_instance.first;\n' % undecorate(first_param_tuple.name)2086                pre_validate_func += self.writeIndent(indent)2087                pre_validate_func += '(void)gen_%s_info;  // quiet warnings\n' % undecorate(first_param_tuple.name)2088                pre_validate_func += self.writeIndent(indent)2089                pre_validate_func += 'GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;\n'2090            pre_validate_func += self.writeIndent(indent)2091            pre_validate_func += '(void)gen_instance_info;  // quiet warnings\n'2092        # If any of the associated handles has validation state tracking, get the2093        # appropriate struct setup for validation later in the function2094        valid_type_list = []2095        if cur_command.checks_state:2096            for cur_state in self.api_states:2097                if cur_command.name in cur_state.check_commands:2098                    command_param_of_type = ''2099                    for param in cur_command.params:2100                        if param.type == cur_state.type:2101                            command_param_of_type = param.name2102                            break2103                    if command_param_of_type and cur_state.type not in valid_type_list:2104                        valid_type_list.append(cur_state.type)2105                        pre_validate_func += self.writeIndent(2)2106                        pre_validate_func += 'auto %s_valid = g_%s_valid_states[%s];\n' % (2107                            undecorate(cur_state.type), undecorate(cur_state.type), command_param_of_type)2108            for additional_ext in cur_command.required_exts:2109                pre_validate_func += self.writeIndent(indent)2110                pre_validate_func += '// Check to make sure that the extension this command is in has been enabled\n'2111                pre_validate_func += self.writeIndent(indent)2112                pre_validate_func += 'if (!ExtensionEnabled(gen_instance_info->enabled_extensions, "%s")) {\n' % additional_ext2113                pre_validate_func += self.writeIndent(indent + 1)2114                pre_validate_func += 'return XR_ERROR_VALIDATION_FAILURE;\n'2115                pre_validate_func += self.writeIndent(indent)2116                pre_validate_func += '}\n'2117        instance_info_variable = 'gen_instance_info' if first_param_tuple else 'nullptr'2118        # Check for non-optional null pointers2119        for count, param in enumerate(cur_command.params):2120            is_first = (count == 0)2121            if is_first and first_param_tuple:2122                # This is the first param, which we already validated as being a handle above. Skip this here.2123                continue2124            if not is_first and param.is_handle and not param.pointer_count > 0:2125                pre_validate_func += self.writeIndent(indent)2126                pre_validate_func += 'objects_info.emplace_back(%s, %s);\n' % (param.name, self.genXrObjectType(2127                    param.type))2128            if not param.no_auto_validity:2129                pre_validate_func += self.outputParamMemberContents(True, cur_command.name, param, '',2130                                                                    instance_info_variable,2131                                                                    command_name_string,2132                                                                    is_first,2133                                                                    first_param,2134                                                                    first_param.name,2135                                                                    first_param_tuple,2136                                                                    wrote_handle_check_proto,2137                                                                    indent)2138                wrote_handle_check_proto = True2139            count = count + 12140        # If this command needs to be checked to ensure that it is executing between2141        # a "begin" and an "end" command, do so.2142        if cur_command.checks_state:2143            for cur_state in self.api_states:2144                if cur_command.name in cur_state.check_commands:2145                    for param in cur_command.params:2146                        if param.type == cur_state.type:2147                            break2148                    pre_validate_func += self.writeIndent(2)2149                    pre_validate_func += '// Validate that this command is called at the proper time between the\n'2150                    pre_validate_func += self.writeIndent(2)2151                    pre_validate_func += '// appropriate commands\n'2152                    pre_validate_func += self.writeIndent(2)2153                    pre_validate_func += 'if (!%s_valid->%s) {\n' % (2154                        undecorate(cur_state.type), cur_state.variable)2155                    pre_validate_func += self.writeIndent(3)2156                    pre_validate_func += 'std::string error_msg = "%s is required to be called between successful calls to ";\n' % cur_command.name2157                    pre_validate_func += self.writeIndent(3)2158                    pre_validate_func += 'error_msg += "'2159                    cur_count = 02160                    for begin_command in cur_state.begin_commands:2161                        if cur_count > 0:2162                            pre_validate_func += '/'2163                        cur_count += 12164                        pre_validate_func += '%s' % begin_command2165                    pre_validate_func += ' and '2166                    cur_count = 02167                    for end_command in cur_state.end_commands:2168                        if cur_count > 0:2169                            pre_validate_func += '/'2170                        cur_count += 12171                        pre_validate_func += '%s' % end_command2172                    pre_validate_func += ' commands";\n'2173                    pre_validate_func += self.writeIndent(3)2174                    pre_validate_func += 'CoreValidLogMessage(%s, "VUID-%s-%s-checkstate",\n' % (2175                        instance_info_variable, cur_command.name, cur_state.state)2176                    pre_validate_func += self.writeIndent(3)2177                    pre_validate_func += '                    VALID_USAGE_DEBUG_SEVERITY_ERROR, "%s", objects_info,\n' % cur_command.name2178                    pre_validate_func += self.writeIndent(3)2179                    pre_validate_func += '                    error_msg);\n'2180                    pre_validate_func += self.writeIndent(3)2181                    pre_validate_func += 'return XR_ERROR_VALIDATION_FAILURE;\n'2182                    pre_validate_func += self.writeIndent(2)2183                    pre_validate_func += '}\n'2184        # If this command needs to indicate that a validation state has begun, do so.2185        if cur_command.begins_state:2186            for cur_state in self.api_states:2187                if cur_command.name in cur_state.check_commands:2188                    for param in cur_command.params:2189                        if param.type == cur_state.type:2190                            break2191                    # First, make sure we're not calling two (or more) "begins" in a row2192                    pre_validate_func += self.writeIndent(2)2193                    pre_validate_func += '// Validate that this command is called first or only after the corresponding\n'2194                    pre_validate_func += self.writeIndent(2)2195                    pre_validate_func += '// "completion" commands\n'2196                    pre_validate_func += self.writeIndent(2)2197                    pre_validate_func += 'if (%s_valid->%s) {\n' % (2198                        undecorate(cur_state.type), cur_state.variable)2199                    pre_validate_func += self.writeIndent(3)2200                    pre_validate_func += 'std::string error_msg = "%s is called again without first successfully calling ";\n' % cur_command.name2201                    pre_validate_func += self.writeIndent(3)2202                    pre_validate_func += 'error_msg += "'2203                    cur_count = 02204                    for end_command in cur_state.end_commands:2205                        if cur_count > 0:2206                            pre_validate_func += '/'2207                        cur_count += 12208                        pre_validate_func += '%s' % end_command2209                    pre_validate_func += '";\n'2210                    pre_validate_func += self.writeIndent(3)2211                    pre_validate_func += 'CoreValidLogMessage(%s, "VUID-%s-%s-beginstate",\n' % (2212                        instance_info_variable, cur_command.name, cur_state.state)2213                    pre_validate_func += self.writeIndent(3)2214                    pre_validate_func += '                    VALID_USAGE_DEBUG_SEVERITY_ERROR, "%s", objects_info,\n' % cur_command.name2215                    pre_validate_func += self.writeIndent(3)2216                    pre_validate_func += '                    error_msg);\n'2217                    pre_validate_func += self.writeIndent(3)2218                    pre_validate_func += 'return XR_ERROR_VALIDATION_FAILURE;\n'2219                    pre_validate_func += self.writeIndent(2)2220                    pre_validate_func += '}\n'2221                    # Begin the appropriate state2222                    pre_validate_func += self.writeIndent(2)2223                    pre_validate_func += '// Begin the %s state\n' % cur_state.state2224                    pre_validate_func += self.writeIndent(2)2225                    pre_validate_func += '%s_valid->%s = true;\n' % (2226                        undecorate(cur_state.type), cur_state.variable)2227        # If this command needs to indicate an end of a validation state, do so.2228        if cur_command.ends_state:2229            for cur_state in self.api_states:2230                if cur_command.name in cur_state.check_commands:2231                    for param in cur_command.params:2232                        if param.type == cur_state.type:2233                            break2234                    # First, make sure we're not calling two (or more) "ends" in a row (or before a "begin")2235                    pre_validate_func += self.writeIndent(2)2236                    pre_validate_func += '// Validate that this command is called after the corresponding\n'2237                    pre_validate_func += self.writeIndent(2)2238                    pre_validate_func += '// "begin" commands\n'2239                    pre_validate_func += self.writeIndent(2)2240                    pre_validate_func += 'if (!%s_valid->%s) {\n' % (2241                        undecorate(cur_state.type), cur_state.variable)2242                    pre_validate_func += self.writeIndent(3)2243                    pre_validate_func += 'std::string error_msg = "%s is called again without first successfully calling ";\n' % cur_command.name2244                    pre_validate_func += self.writeIndent(3)2245                    pre_validate_func += 'error_msg += "'2246                    cur_count = 02247                    for begin_command in cur_state.begin_commands:2248                        if cur_count > 0:2249                            pre_validate_func += '/'2250                        cur_count += 12251                        pre_validate_func += '%s' % begin_command2252                    pre_validate_func += '";\n'2253                    pre_validate_func += self.writeIndent(3)2254                    pre_validate_func += 'CoreValidLogMessage(%s, "VUID-%s-%s-endstate",\n' % (2255                        instance_info_variable, cur_command.name, cur_state.state)2256                    pre_validate_func += self.writeIndent(3)2257                    pre_validate_func += '                    VALID_USAGE_DEBUG_SEVERITY_ERROR, "%s", objects_info,\n' % cur_command.name2258                    pre_validate_func += self.writeIndent(3)2259                    pre_validate_func += '                    error_msg);\n'2260                    pre_validate_func += self.writeIndent(3)2261                    pre_validate_func += 'return XR_ERROR_VALIDATION_FAILURE;\n'2262                    pre_validate_func += self.writeIndent(2)2263                    pre_validate_func += '}\n'2264                    # End the appropriate state2265                    pre_validate_func += self.writeIndent(2)2266                    pre_validate_func += '// End the %s state\n' % cur_state.state2267                    pre_validate_func += self.writeIndent(2)2268                    pre_validate_func += '%s_valid->%s = false;\n' % (2269                        undecorate(cur_state.type), cur_state.variable)2270        pre_validate_func += self.writeIndent(indent)2271        pre_validate_func += 'return xr_result;\n'2272        indent = indent - 12273        pre_validate_func += self.writeIndent(indent)2274        pre_validate_func += '} catch (...) {\n'2275        pre_validate_func += self.writeIndent(indent + 1)2276        pre_validate_func += 'return XR_ERROR_VALIDATION_FAILURE;\n'2277        pre_validate_func += self.writeIndent(indent)2278        pre_validate_func += '}\n'2279        pre_validate_func += '}\n\n'2280        return pre_validate_func2281    # Generate C++ code to call down to the next layer/loader terminator/runtime2282    #   self            the ValidationSourceOutputGenerator object2283    #   cur_command     the command generated in automatic_source_generator.py to validate2284    #   has_return      Boolean indicating that the command must return a value (usually XrResult)2285    #   is_create       Boolean indicating that the command is a create command2286    #   is_destroy      Boolean indicating that the command is a destroy command2287    #   is_sempath_query Boolean indicating that this is a semantic path query (treat similar to a create)2288    def genNextValidateFunc(self, cur_command, has_return, is_create, is_destroy, is_sempath_query):2289        next_validate_func = ''2290        # Note: We don't make a "next" call for xrCreateInstance in a layer because we2291        # actually have to call xrCreateApiLayerInstance.  Also, we have to setup the first2292        # entry into the dispatch table so it's a special case all around.2293        if 'xrCreateInstance' in cur_command.name:2294            return ''2295        prototype = cur_command.cdecl.replace(" xr", " GenValidUsageNextXr")2296        prototype = prototype.replace(";", " {")2297        next_validate_func += '%s\n' % (prototype)2298        if has_return:2299            return_prefix = '    '2300            return_prefix += cur_command.return_type.text2301            return_prefix += ' result'2302            if cur_command.return_type.text == 'XrResult':2303                return_prefix += ' = XR_SUCCESS;\n'2304            else:2305                return_prefix += ';\n'2306            next_validate_func += return_prefix2307        next_validate_func += '    try {\n'2308        first_param = cur_command.params[0]2309        # Next, we have to call down to the next implementation of this command in the call chain.2310        # Before we can do that, we have to figure out what the dispatch table is2311        base_handle_name = undecorate(first_param.type)2312        if first_param.is_handle:2313            first_handle_tuple = self.getHandle(first_param.type)2314            first_handle_name = self.getFirstHandleName(first_param)2315            if first_handle_tuple.name == 'XrInstance':2316                next_validate_func += '        GenValidUsageXrInstanceInfo *gen_instance_info = g_instance_info.get(%s);\n' % first_handle_name2317            else:2318                next_validate_func += '        auto info_with_instance = %s.getWithInstanceInfo(%s);\n' % (2319                    self.makeInfoName(handle_type_name=first_handle_tuple.name), first_handle_name)2320                next_validate_func += '        GenValidUsageXrHandleInfo *gen_%s_info = info_with_instance.first;\n' % base_handle_name2321                next_validate_func += '        (void)gen_%s_info;  // quiet warnings\n' % base_handle_name2322                next_validate_func += '        GenValidUsageXrInstanceInfo *gen_instance_info = info_with_instance.second;\n'2323        else:2324            next_validate_func += '#error("Bug")\n'2325        # Call down, looking for the returned result if required.2326        next_validate_func += '        '2327        if has_return:2328            next_validate_func += 'result = '2329        next_validate_func += 'gen_instance_info->dispatch_table->%s(' % cur_command.name[2:]2330        count = 02331        for param in cur_command.params:2332            if count > 0:2333                next_validate_func += ', '2334            next_validate_func += param.name2335            count = count + 12336        next_validate_func += ');\n'2337        # If this is a create command, we have to create an entry in the appropriate2338        # unordered_map pointing to the correct dispatch table for the newly created2339        # object.  Likewise, if it's a delete command, we have to remove the entry2340        # for the dispatch table from the unordered_map2341        last_param = cur_command.params[-1]2342        if last_param.is_handle:2343            first_param = cur_command.params[0]2344            last_handle_tuple = self.getHandle(last_param.type)2345            last_handle_name = last_param.name2346            if is_create:2347                assert(last_handle_tuple.name != 'XrInstance')2348                next_validate_func += '        if (XR_SUCCESS == result && nullptr != %s) {\n' % last_handle_name2349                next_validate_func += '            std::unique_ptr<GenValidUsageXrHandleInfo> handle_info(new GenValidUsageXrHandleInfo());\n'2350                next_validate_func += '            handle_info->instance_info = gen_instance_info;\n'2351                next_validate_func += '            handle_info->direct_parent_type = %s;\n' % self.genXrObjectType(2352                    first_param.type)2353                next_validate_func += '            handle_info->direct_parent_handle = MakeHandleGeneric(%s);\n' % first_param.name2354                next_validate_func += '            %s.insert(*%s, std::move(handle_info));\n' % (self.makeInfoName(last_handle_tuple), last_handle_name)2355                # If this object contains a state that needs tracking, allocate it2356                valid_type_list = []2357                for cur_state in self.api_states:2358                    if last_handle_tuple.name == cur_state.type and cur_state.type not in valid_type_list:2359                        valid_type_list.append(cur_state.type)2360                        next_validate_func += self.writeIndent(3)2361                        next_validate_func += '// Check to see if this object that has been created has a validation\n'2362                        next_validate_func += self.writeIndent(3)2363                        next_validate_func += '// state structure that needs to be created as well.\n'2364                        next_validate_func += self.writeIndent(3)2365                        next_validate_func += '%sValidationStates *%s_valid_state = new %sValidationStates;\n' % (2366                            cur_state.type, undecorate(cur_state.type), cur_state.type)2367                        next_validate_func += self.writeIndent(3)2368                        next_validate_func += '(*%s_valid_state) = {};\n' % undecorate(cur_state.type)2369                        next_validate_func += self.writeIndent(3)2370                        next_validate_func += 'g_%s_valid_states[(*%s)] = %s_valid_state;\n' % (2371                            undecorate(cur_state.type), last_handle_name, undecorate(cur_state.type))2372                next_validate_func += '        }\n'2373            elif is_destroy:2374                if last_param.type == 'XrSession':2375                    next_validate_func += '\n        // Clean up any labels associated with this session\n'2376                    next_validate_func += '        CoreValidationDeleteSessionLabels(session);\n\n'2377                # Only remove the handle from our map if the runtime returned success2378                next_validate_func += '        if (XR_SUCCEEDED(result)) {\n'2379                # If this object contains a state that needs tracking, free it2380                valid_type_list = []2381                for cur_state in self.api_states:2382                    if last_handle_tuple.name == cur_state.type and cur_state.type not in valid_type_list:2383                        valid_type_list.append(cur_state.type)2384                        next_validate_func += self.writeIndent(3)2385                        next_validate_func += '// Check to see if this object that is about to be destroyed has a\n'2386                        next_validate_func += self.writeIndent(3)2387                        next_validate_func += '// validation state structure that needs to be cleaned up.\n'2388                        next_validate_func += self.writeIndent(3)2389                        next_validate_func += '%sValidationStates *%s_valid_state = g_%s_valid_states[%s];\n' % (2390                            cur_state.type, undecorate(cur_state.type), undecorate(cur_state.type), last_handle_name)2391                        next_validate_func += self.writeIndent(3)2392                        next_validate_func += 'if (nullptr != %s_valid_state) {\n' % cur_state.type[2:].lower(2393                        )2394                        next_validate_func += self.writeIndent(4)2395                        next_validate_func += 'delete %s_valid_state;\n' % cur_state.type[2:].lower(2396                        )2397                        next_validate_func += self.writeIndent(4)2398                        next_validate_func += 'g_%s_valid_states.erase(%s);\n' % (2399                            undecorate(cur_state.type), last_handle_name)2400                        next_validate_func += self.writeIndent(3)2401                        next_validate_func += '}\n'2402                next_validate_func += '            %s.erase(%s);\n' % (self.makeInfoName(handle_type=last_handle_tuple), last_handle_name)2403                next_validate_func += '        }\n'2404                if 'xrDestroyInstance' in cur_command.name:2405                    next_validate_func += '        GenValidUsageCleanUpMaps(gen_instance_info);\n'2406        # Catch any exceptions that may have occurred.  If any occurred between any of the2407        # valid mutex lock/unlock statements, perform the unlock now.  Notice that a create can2408        # also allocate items, so we want to special case catching the failure of the allocation.2409        if is_create or is_sempath_query:2410            next_validate_func += '    } catch (std::bad_alloc&) {\n'2411            next_validate_func += '        result = XR_ERROR_OUT_OF_MEMORY;\n'2412        next_validate_func += '    } catch (...) {\n'2413        if has_return:2414            next_validate_func += '        result = XR_ERROR_VALIDATION_FAILURE;\n'2415        next_validate_func += '    }\n'2416        if has_return:2417            next_validate_func += '    return result;\n'2418        next_validate_func += '}\n\n'2419        return next_validate_func2420    # Generate a top-level automatic C++ validation function which will be used until2421    # a manual function is defined.2422    #   self            the ValidationSourceOutputGenerator object2423    #   cur_command     the command generated in automatic_source_generator.py to validate2424    #   has_return      Boolean indicating that the command must return a value (usually XrResult)2425    def genAutoValidateFunc(self, cur_command, has_return):2426        auto_validate_func = ''2427        prototype = cur_command.cdecl.replace(" xr", " GenValidUsageXr")2428        prototype = prototype.replace(";", " {")2429        auto_validate_func += '%s\n' % (prototype)2430        auto_validate_func += self.writeIndent(1)2431        if has_return:2432            auto_validate_func += '%s test_result = ' % cur_command.return_type.text2433        # Define the pre-validate call2434        auto_validate_func += '%s(' % cur_command.name.replace("xr",2435                                                               "GenValidUsageInputsXr")2436        count = 02437        for param in cur_command.params:2438            if count > 0:2439                auto_validate_func += ', '2440            count = count + 12441            auto_validate_func += param.name2442        auto_validate_func += ');\n'2443        if has_return and cur_command.return_type.text == 'XrResult':2444            auto_validate_func += self.writeIndent(1)2445            auto_validate_func += 'if (XR_SUCCESS != test_result) {\n'2446            auto_validate_func += self.writeIndent(2)2447            auto_validate_func += 'return test_result;\n'2448            auto_validate_func += self.writeIndent(1)2449            auto_validate_func += '}\n'2450        # Make the calldown to the next layer2451        auto_validate_func += self.writeIndent(1)2452        if has_return:2453            auto_validate_func += 'return '2454        auto_validate_func += '%s(' % cur_command.name.replace("xr",2455                                                               "GenValidUsageNextXr")2456        count = 02457        for param in cur_command.params:2458            if count > 0:2459                auto_validate_func += ', '2460            count = count + 12461            auto_validate_func += param.name2462        auto_validate_func += ');\n'2463        auto_validate_func += '}\n\n'2464        return auto_validate_func2465    # Implementation for generated validation commands2466    #   self                the ValidationSourceOutputGenerator object2467    def outputValidationSourceFuncs(self):2468        commands = []2469        validation_source_funcs = ''2470        cur_extension_name = ''2471        # First, output the mapping and mutex items2472        validation_source_funcs += '// Unordered Map associating pointer to a vector of session label information to a session\'s handle\n'2473        validation_source_funcs += 'std::unordered_map<XrSession, std::vector<GenValidUsageXrInternalSessionLabel*>*> g_xr_session_labels;\n\n'2474        validation_source_funcs += self.outputInfoMapDeclarations(extern=False)2475        validation_source_funcs += '\n'2476        validation_source_funcs += self.outputValidationInternalProtos()2477        validation_source_funcs += '// Function used to clean up any residual map values that point to an instance prior to that\n'2478        validation_source_funcs += '// instance being deleted.\n'2479        validation_source_funcs += 'void GenValidUsageCleanUpMaps(GenValidUsageXrInstanceInfo *instance_info) {\n'2480        for handle in self.api_handles:2481            if handle.protect_value:2482                validation_source_funcs += '#if %s\n' % handle.protect_string2483            if handle.name == 'XrInstance':2484                validation_source_funcs += '    EraseAllInstanceTableMapElements(instance_info);\n'2485            else:2486                validation_source_funcs += '    %s.removeHandlesForInstance(instance_info);\n' % self.makeInfoName(handle_type=handle)2487            if handle.protect_value:2488                validation_source_funcs += '#endif // %s\n' % handle.protect_string2489        validation_source_funcs += '}\n'2490        validation_source_funcs += '\n'2491        validation_source_funcs += '// Function to convert XrObjectType to string\n'2492        validation_source_funcs += 'std::string GenValidUsageXrObjectTypeToString(const XrObjectType& type) {\n'2493        validation_source_funcs += '    std::string object_string;\n'2494        count = 02495        for object_type in self.api_object_types:2496            object_string = object_type.name.replace("XR_OBJECT_TYPE_", "").replace("_", "")2497            if object_string == "UNKNOWN":2498                if count == 0:2499                    validation_source_funcs += '    if '2500                else:2501                    validation_source_funcs += '    } else if '2502                validation_source_funcs += '(type == XR_OBJECT_TYPE_UNKNOWN) {\n'2503                validation_source_funcs += '        object_string = "Unknown XR Object";\n'2504            else:2505                for handle in self.api_handles:2506                    handle_name = handle.name[2:].upper()2507                    if handle_name != object_string:2508                        continue2509                    if object_type.protect_value:2510                        validation_source_funcs += '#if %s\n' % object_type.protect_string2511                    if count == 0:2512                        validation_source_funcs += '    if '2513                    else:2514                        validation_source_funcs += '    } else if '2515                    validation_source_funcs += '(type == %s) {\n' % object_type.name2516                    validation_source_funcs += '        object_string = "%s";\n' % handle.name2517                    if object_type.protect_value:2518                        validation_source_funcs += '#endif // %s\n' % object_type.protect_string2519            count = count + 12520        validation_source_funcs += '    }\n'2521        validation_source_funcs += '    return object_string;\n'2522        validation_source_funcs += '}\n\n'2523        validation_source_funcs += self.outputValidationStateCheckStructs()2524        validation_source_funcs += self.outputValidationSourceNextChainProtos()2525        validation_source_funcs += self.outputValidationSourceFlagBitValues()2526        validation_source_funcs += self.outputValidationSourceEnumValues()2527        validation_source_funcs += self.writeVerifyExtensions()2528        validation_source_funcs += self.writeValidateHandleChecks()2529        validation_source_funcs += self.writeValidateHandleParent()2530        validation_source_funcs += self.writeValidateStructFuncs()2531        validation_source_funcs += self.outputValidationSourceNextChainFunc()2532        for x in range(0, 2):2533            if x == 0:2534                commands = self.core_commands2535            else:2536                commands = self.ext_commands2537            for cur_cmd in commands:2538                if cur_cmd.ext_name != cur_extension_name:2539                    if 'XR_VERSION_' in cur_cmd.ext_name:2540                        validation_source_funcs += '\n// ---- Core %s commands\n' % cur_cmd.ext_name[11:].replace(2541                            "_", ".")2542                    else:2543                        validation_source_funcs += '\n// ---- %s extension commands\n' % cur_cmd.ext_name2544                    cur_extension_name = cur_cmd.ext_name2545                if cur_cmd.name in self.no_trampoline_or_terminator:2546                    continue2547                # We fill in the GetInstanceProcAddr manually at the end2548                if cur_cmd.name == 'xrGetInstanceProcAddr':2549                    continue2550                if cur_cmd.protect_value:2551                    validation_source_funcs += '#if %s\n' % cur_cmd.protect_string2552                    validation_source_funcs += '\n'2553                is_create = False2554                is_destroy = False2555                has_return = False2556                is_sempath_query = False2557                last_param = cur_cmd.params[-1]2558                if ('xrCreate' in cur_cmd.name or 'xrConnect' in cur_cmd.name) and last_param.is_handle:2559                    is_create = True2560                    has_return = True2561                elif ('xrDestroy' in cur_cmd.name or 'xrDisconnect' in cur_cmd.name) and last_param.is_handle:2562                    is_destroy = True2563                    has_return = True2564                elif cur_cmd.return_type is not None:2565                    has_return = True2566                validation_source_funcs += self.genValidateInputsFunc(cur_cmd)2567                validation_source_funcs += self.genNextValidateFunc(2568                    cur_cmd, has_return, is_create, is_destroy, is_sempath_query)2569                if cur_cmd.name not in VALID_USAGE_MANUALLY_DEFINED:2570                    validation_source_funcs += self.genAutoValidateFunc(2571                        cur_cmd, has_return)2572                if cur_cmd.protect_value:2573                    validation_source_funcs += '#endif // %s\n' % cur_cmd.protect_string2574                    validation_source_funcs += '\n'2575        validation_source_funcs += '\n// API Layer\'s xrGetInstanceProcAddr\n'2576        validation_source_funcs += 'XRAPI_ATTR XrResult XRAPI_CALL GenValidUsageXrGetInstanceProcAddr(\n'2577        validation_source_funcs += '    XrInstance          instance,\n'2578        validation_source_funcs += '    const char*         name,\n'2579        validation_source_funcs += '    PFN_xrVoidFunction* function) {\n'2580        validation_source_funcs += '    try {\n'2581        validation_source_funcs += '        std::string func_name = name;\n'2582        validation_source_funcs += '        std::vector<GenValidUsageXrObjectInfo> objects;\n'2583        validation_source_funcs += '        if (g_instance_info.verifyHandle(&instance) == VALIDATE_XR_HANDLE_INVALID) {\n'2584        validation_source_funcs += '            // Make sure the instance is valid if it is not XR_NULL_HANDLE\n'2585        validation_source_funcs += '            std::vector<GenValidUsageXrObjectInfo> objects;\n'2586        validation_source_funcs += '            objects.resize(1);\n'2587        validation_source_funcs += '            objects[0].handle = MakeHandleGeneric(instance);\n'2588        validation_source_funcs += '            objects[0].type = XR_OBJECT_TYPE_INSTANCE;\n'2589        validation_source_funcs += '            CoreValidLogMessage(nullptr, "VUID-xrGetInstanceProcAddr-instance-parameter",\n'2590        validation_source_funcs += '                                VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrGetInstanceProcAddr", objects,\n'2591        validation_source_funcs += '                                "Invalid instance handle provided.");\n'2592        validation_source_funcs += '        }\n'2593        validation_source_funcs += '        // NOTE: Can\'t validate "VUID-xrGetInstanceProcAddr-name-parameter" null-termination\n'2594        validation_source_funcs += '        // If we setup the function, just return\n'2595        validation_source_funcs += '        if (function == nullptr) {\n'2596        validation_source_funcs += '            CoreValidLogMessage(nullptr, "VUID-xrGetInstanceProcAddr-function-parameter",\n'2597        validation_source_funcs += '                                VALID_USAGE_DEBUG_SEVERITY_ERROR, "xrGetInstanceProcAddr", objects,\n'2598        validation_source_funcs += '                                "function is NULL");\n'2599        validation_source_funcs += '            return XR_ERROR_VALIDATION_FAILURE;\n'2600        validation_source_funcs += '        }\n'2601        count = 02602        for x in range(0, 2):2603            if x == 0:2604                commands = self.core_commands2605            else:2606                commands = self.ext_commands2607            for cur_cmd in commands:2608                if cur_cmd.ext_name != cur_extension_name:2609                    if 'XR_VERSION_' in cur_cmd.ext_name:2610                        validation_source_funcs += '\n        // ---- Core %s commands\n' % cur_cmd.ext_name[11:].replace(2611                            "_", ".")2612                    else:2613                        validation_source_funcs += '\n        // ---- %s extension commands\n' % cur_cmd.ext_name2614                    cur_extension_name = cur_cmd.ext_name2615                if cur_cmd.name in self.no_trampoline_or_terminator:2616                    continue2617                has_return = False2618                if cur_cmd.return_type is not None:2619                    has_return = True2620                if cur_cmd.name in VALID_USAGE_MANUALLY_DEFINED:2621                    # Remove 'xr' from proto name and use manual name2622                    layer_command_name = cur_cmd.name.replace(2623                        "xr", "CoreValidationXr")2624                else:2625                    # Remove 'xr' from proto name and use generated name2626                    layer_command_name = cur_cmd.name.replace(2627                        "xr", "GenValidUsageXr")2628                if cur_cmd.protect_value:2629                    validation_source_funcs += '#if %s\n' % cur_cmd.protect_string2630                if count == 0:2631                    validation_source_funcs += '        if (func_name == "%s") {\n' % cur_cmd.name2632                else:2633                    validation_source_funcs += '        } else if (func_name == "%s") {\n' % cur_cmd.name2634                count = count + 12635                validation_source_funcs += '            *function = reinterpret_cast<PFN_xrVoidFunction>(%s);\n' % layer_command_name2636                if cur_cmd.protect_value:2637                    validation_source_funcs += '#endif // %s\n' % cur_cmd.protect_string2638        validation_source_funcs += '        }\n'2639        validation_source_funcs += '        // If we setup the function, just return\n'2640        validation_source_funcs += '        if (*function != nullptr) {\n'2641        validation_source_funcs += '            return XR_SUCCESS;\n'2642        validation_source_funcs += '        }\n'2643        validation_source_funcs += '        // We have not found it, so pass it down to the next layer/runtime\n'2644        validation_source_funcs += '        GenValidUsageXrInstanceInfo* instance_valid_usage_info = g_instance_info.get(instance);\n'2645        validation_source_funcs += '        if (nullptr == instance_valid_usage_info) {\n'2646        validation_source_funcs += '            return XR_ERROR_HANDLE_INVALID;\n'2647        validation_source_funcs += '        }\n'2648        validation_source_funcs += '        return instance_valid_usage_info->dispatch_table->GetInstanceProcAddr(instance, name, function);\n'2649        validation_source_funcs += '    } catch (...) {\n'2650        validation_source_funcs += '        return XR_ERROR_VALIDATION_FAILURE;\n'2651        validation_source_funcs += '    }\n'2652        validation_source_funcs += '}\n'...Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!
