1e5c31af7Sopenharmony_ci#!/usr/bin/python3 -i 2e5c31af7Sopenharmony_ci# 3e5c31af7Sopenharmony_ci# Copyright 2013-2024 The Khronos Group Inc. 4e5c31af7Sopenharmony_ci# 5e5c31af7Sopenharmony_ci# SPDX-License-Identifier: Apache-2.0 6e5c31af7Sopenharmony_ci 7e5c31af7Sopenharmony_cifrom generator import OutputGenerator, enquote, noneStr 8e5c31af7Sopenharmony_ci 9e5c31af7Sopenharmony_cidef mostOfficial(api, newapi): 10e5c31af7Sopenharmony_ci """Return the 'most official' of two related names, api and newapi. 11e5c31af7Sopenharmony_ci KHR is more official than EXT is more official than everything else. 12e5c31af7Sopenharmony_ci If there is ambiguity, return api. 13e5c31af7Sopenharmony_ci Accommodate APIs using lower-case vendor suffixes.""" 14e5c31af7Sopenharmony_ci 15e5c31af7Sopenharmony_ci apicat = api[-3:].upper() 16e5c31af7Sopenharmony_ci newapicat = newapi[-3:].upper() 17e5c31af7Sopenharmony_ci 18e5c31af7Sopenharmony_ci if apicat == 'KHR': 19e5c31af7Sopenharmony_ci return api 20e5c31af7Sopenharmony_ci if newapicat == 'KHR': 21e5c31af7Sopenharmony_ci return newapi; 22e5c31af7Sopenharmony_ci if apicat == 'EXT': 23e5c31af7Sopenharmony_ci return api 24e5c31af7Sopenharmony_ci if newapicat == 'EXT': 25e5c31af7Sopenharmony_ci return newapi; 26e5c31af7Sopenharmony_ci return api 27e5c31af7Sopenharmony_ci 28e5c31af7Sopenharmony_ciclass ScriptOutputGenerator(OutputGenerator): 29e5c31af7Sopenharmony_ci """ScriptOutputGenerator - subclass of OutputGenerator. 30e5c31af7Sopenharmony_ci Base class to Generate script (Python/Ruby/JS/etc.) data structures 31e5c31af7Sopenharmony_ci describing API names and relationships. 32e5c31af7Sopenharmony_ci Similar to DocOutputGenerator, but writes a single file.""" 33e5c31af7Sopenharmony_ci 34e5c31af7Sopenharmony_ci def apiName(self, name): 35e5c31af7Sopenharmony_ci """Return True if name is in the reserved API namespace. 36e5c31af7Sopenharmony_ci 37e5c31af7Sopenharmony_ci Delegates to the conventions object. """ 38e5c31af7Sopenharmony_ci return self.genOpts.conventions.is_api_name(name) 39e5c31af7Sopenharmony_ci 40e5c31af7Sopenharmony_ci def __init__(self, *args, **kwargs): 41e5c31af7Sopenharmony_ci super().__init__(*args, **kwargs) 42e5c31af7Sopenharmony_ci 43e5c31af7Sopenharmony_ci # Track features being generated 44e5c31af7Sopenharmony_ci self.features = [] 45e5c31af7Sopenharmony_ci 46e5c31af7Sopenharmony_ci # Reverse map from interface names to features requiring them 47e5c31af7Sopenharmony_ci self.apimap = {} 48e5c31af7Sopenharmony_ci 49e5c31af7Sopenharmony_ci # Reverse map from unsupported APIs in this build to aliases which 50e5c31af7Sopenharmony_ci # are supported 51e5c31af7Sopenharmony_ci self.nonexistent = {} 52e5c31af7Sopenharmony_ci 53e5c31af7Sopenharmony_ci def beginFile(self, genOpts): 54e5c31af7Sopenharmony_ci OutputGenerator.beginFile(self, genOpts) 55e5c31af7Sopenharmony_ci # 56e5c31af7Sopenharmony_ci # Dictionaries are keyed by the name of the entity (e.g. 57e5c31af7Sopenharmony_ci # self.structs is keyed by structure names). Values are 58e5c31af7Sopenharmony_ci # the names of related entities (e.g. structs contain 59e5c31af7Sopenharmony_ci # a list of type names of members, enums contain a list 60e5c31af7Sopenharmony_ci # of enumerants belong to the enumerated type, etc.), or 61e5c31af7Sopenharmony_ci # just None if there are no directly related entities. 62e5c31af7Sopenharmony_ci # 63e5c31af7Sopenharmony_ci # Collect the mappings, then emit the Python script in endFile 64e5c31af7Sopenharmony_ci self.basetypes = {} 65e5c31af7Sopenharmony_ci self.consts = {} 66e5c31af7Sopenharmony_ci self.enums = {} 67e5c31af7Sopenharmony_ci self.flags = {} 68e5c31af7Sopenharmony_ci self.funcpointers = {} 69e5c31af7Sopenharmony_ci self.protos = {} 70e5c31af7Sopenharmony_ci self.structs = {} 71e5c31af7Sopenharmony_ci self.handles = {} 72e5c31af7Sopenharmony_ci self.defines = {} 73e5c31af7Sopenharmony_ci self.alias = {} 74e5c31af7Sopenharmony_ci # Dictionary containing the type of a type name 75e5c31af7Sopenharmony_ci # (e.g. the string name of the dictionary with its contents). 76e5c31af7Sopenharmony_ci self.typeCategory = {} 77e5c31af7Sopenharmony_ci self.mapDict = {} 78e5c31af7Sopenharmony_ci 79e5c31af7Sopenharmony_ci def addInterfaceMapping(self, api, feature, required): 80e5c31af7Sopenharmony_ci """Add a reverse mapping in self.apimap from an API to a feature 81e5c31af7Sopenharmony_ci requiring that API. 82e5c31af7Sopenharmony_ci 83e5c31af7Sopenharmony_ci - api - name of the API 84e5c31af7Sopenharmony_ci - feature - name of the feature requiring it 85e5c31af7Sopenharmony_ci - required - None, or an additional feature dependency within 86e5c31af7Sopenharmony_ci 'feature'. The additional dependency is a boolean expression of 87e5c31af7Sopenharmony_ci one or more extension and/or core version names, which is passed 88e5c31af7Sopenharmony_ci through to the output script intact.""" 89e5c31af7Sopenharmony_ci 90e5c31af7Sopenharmony_ci # Each entry in self.apimap contains one or more 91e5c31af7Sopenharmony_ci # ( feature, required ) tuples. 92e5c31af7Sopenharmony_ci deps = ( feature, required ) 93e5c31af7Sopenharmony_ci 94e5c31af7Sopenharmony_ci if api in self.apimap: 95e5c31af7Sopenharmony_ci self.apimap[api].append(deps) 96e5c31af7Sopenharmony_ci else: 97e5c31af7Sopenharmony_ci self.apimap[api] = [ deps ] 98e5c31af7Sopenharmony_ci 99e5c31af7Sopenharmony_ci def mapInterfaceKeys(self, feature, key): 100e5c31af7Sopenharmony_ci """Construct reverse mapping of APIs to features requiring them in 101e5c31af7Sopenharmony_ci self.apimap. 102e5c31af7Sopenharmony_ci 103e5c31af7Sopenharmony_ci - feature - name of the feature being generated 104e5c31af7Sopenharmony_ci - key - API category - 'define', 'basetype', etc.""" 105e5c31af7Sopenharmony_ci 106e5c31af7Sopenharmony_ci dict = self.featureDictionary[feature][key] 107e5c31af7Sopenharmony_ci 108e5c31af7Sopenharmony_ci if dict: 109e5c31af7Sopenharmony_ci # Not clear why handling of command vs. type APIs is different - 110e5c31af7Sopenharmony_ci # see interfacedocgenerator.py, which this was based on. 111e5c31af7Sopenharmony_ci if key == 'command': 112e5c31af7Sopenharmony_ci for required in dict: 113e5c31af7Sopenharmony_ci for api in dict[required]: 114e5c31af7Sopenharmony_ci self.addInterfaceMapping(api, feature, required) 115e5c31af7Sopenharmony_ci else: 116e5c31af7Sopenharmony_ci for required in dict: 117e5c31af7Sopenharmony_ci for parent in dict[required]: 118e5c31af7Sopenharmony_ci for api in dict[required][parent]: 119e5c31af7Sopenharmony_ci self.addInterfaceMapping(api, feature, required) 120e5c31af7Sopenharmony_ci 121e5c31af7Sopenharmony_ci def mapInterfaces(self, feature): 122e5c31af7Sopenharmony_ci """Construct reverse mapping of APIs to features requiring them in 123e5c31af7Sopenharmony_ci self.apimap. 124e5c31af7Sopenharmony_ci 125e5c31af7Sopenharmony_ci - feature - name of the feature being generated""" 126e5c31af7Sopenharmony_ci 127e5c31af7Sopenharmony_ci # Map each category of interface 128e5c31af7Sopenharmony_ci self.mapInterfaceKeys(feature, 'basetype') 129e5c31af7Sopenharmony_ci self.mapInterfaceKeys(feature, 'bitmask') 130e5c31af7Sopenharmony_ci self.mapInterfaceKeys(feature, 'command') 131e5c31af7Sopenharmony_ci self.mapInterfaceKeys(feature, 'define') 132e5c31af7Sopenharmony_ci self.mapInterfaceKeys(feature, 'enum') 133e5c31af7Sopenharmony_ci self.mapInterfaceKeys(feature, 'enumconstant') 134e5c31af7Sopenharmony_ci self.mapInterfaceKeys(feature, 'funcpointer') 135e5c31af7Sopenharmony_ci self.mapInterfaceKeys(feature, 'handle') 136e5c31af7Sopenharmony_ci self.mapInterfaceKeys(feature, 'include') 137e5c31af7Sopenharmony_ci self.mapInterfaceKeys(feature, 'struct') 138e5c31af7Sopenharmony_ci self.mapInterfaceKeys(feature, 'union') 139e5c31af7Sopenharmony_ci 140e5c31af7Sopenharmony_ci def endFile(self): 141e5c31af7Sopenharmony_ci super().endFile() 142e5c31af7Sopenharmony_ci 143e5c31af7Sopenharmony_ci def beginFeature(self, interface, emit): 144e5c31af7Sopenharmony_ci # Start processing in superclass 145e5c31af7Sopenharmony_ci OutputGenerator.beginFeature(self, interface, emit) 146e5c31af7Sopenharmony_ci 147e5c31af7Sopenharmony_ci # Add this feature to the list being tracked 148e5c31af7Sopenharmony_ci self.features.append( self.featureName ) 149e5c31af7Sopenharmony_ci 150e5c31af7Sopenharmony_ci def endFeature(self): 151e5c31af7Sopenharmony_ci # Finish processing in superclass 152e5c31af7Sopenharmony_ci OutputGenerator.endFeature(self) 153e5c31af7Sopenharmony_ci 154e5c31af7Sopenharmony_ci def addName(self, dict, name, value): 155e5c31af7Sopenharmony_ci """Add a string entry to the dictionary, quoting it so it gets 156e5c31af7Sopenharmony_ci printed out correctly in self.endFile().""" 157e5c31af7Sopenharmony_ci dict[name] = value 158e5c31af7Sopenharmony_ci 159e5c31af7Sopenharmony_ci def addMapping(self, baseType, refType): 160e5c31af7Sopenharmony_ci """Add a mapping between types to mapDict. 161e5c31af7Sopenharmony_ci 162e5c31af7Sopenharmony_ci Only include API types, so we do not end up with a lot of useless 163e5c31af7Sopenharmony_ci uint32_t and void types.""" 164e5c31af7Sopenharmony_ci if not self.apiName(baseType) or not self.apiName(refType): 165e5c31af7Sopenharmony_ci self.logMsg('diag', 'ScriptOutputGenerator::addMapping: IGNORE map from', baseType, '<->', refType) 166e5c31af7Sopenharmony_ci return 167e5c31af7Sopenharmony_ci 168e5c31af7Sopenharmony_ci self.logMsg('diag', 'ScriptOutputGenerator::addMapping: map from', 169e5c31af7Sopenharmony_ci baseType, '<->', refType) 170e5c31af7Sopenharmony_ci 171e5c31af7Sopenharmony_ci if baseType not in self.mapDict: 172e5c31af7Sopenharmony_ci baseDict = {} 173e5c31af7Sopenharmony_ci self.mapDict[baseType] = baseDict 174e5c31af7Sopenharmony_ci else: 175e5c31af7Sopenharmony_ci baseDict = self.mapDict[baseType] 176e5c31af7Sopenharmony_ci if refType not in self.mapDict: 177e5c31af7Sopenharmony_ci refDict = {} 178e5c31af7Sopenharmony_ci self.mapDict[refType] = refDict 179e5c31af7Sopenharmony_ci else: 180e5c31af7Sopenharmony_ci refDict = self.mapDict[refType] 181e5c31af7Sopenharmony_ci 182e5c31af7Sopenharmony_ci baseDict[refType] = None 183e5c31af7Sopenharmony_ci refDict[baseType] = None 184e5c31af7Sopenharmony_ci 185e5c31af7Sopenharmony_ci def breakCheck(self, procname, name): 186e5c31af7Sopenharmony_ci """Debugging aid - call from procname to break on API 'name' if it 187e5c31af7Sopenharmony_ci matches logic in this call.""" 188e5c31af7Sopenharmony_ci 189e5c31af7Sopenharmony_ci pat = 'VkExternalFenceFeatureFlagBits' 190e5c31af7Sopenharmony_ci if name[0:len(pat)] == pat: 191e5c31af7Sopenharmony_ci print('{}(name = {}) matches {}'.format(procname, name, pat)) 192e5c31af7Sopenharmony_ci import pdb 193e5c31af7Sopenharmony_ci pdb.set_trace() 194e5c31af7Sopenharmony_ci 195e5c31af7Sopenharmony_ci def genType(self, typeinfo, name, alias): 196e5c31af7Sopenharmony_ci """Generate type. 197e5c31af7Sopenharmony_ci 198e5c31af7Sopenharmony_ci - For 'struct' or 'union' types, defer to genStruct() to 199e5c31af7Sopenharmony_ci add to the dictionary. 200e5c31af7Sopenharmony_ci - For 'bitmask' types, add the type name to the 'flags' dictionary, 201e5c31af7Sopenharmony_ci with the value being the corresponding 'enums' name defining 202e5c31af7Sopenharmony_ci the acceptable flag bits. 203e5c31af7Sopenharmony_ci - For 'enum' types, add the type name to the 'enums' dictionary, 204e5c31af7Sopenharmony_ci with the value being '@STOPHERE@' (because this case seems 205e5c31af7Sopenharmony_ci never to happen). 206e5c31af7Sopenharmony_ci - For 'funcpointer' types, add the type name to the 'funcpointers' 207e5c31af7Sopenharmony_ci dictionary. 208e5c31af7Sopenharmony_ci - For 'handle' and 'define' types, add the handle or #define name 209e5c31af7Sopenharmony_ci to the 'struct' dictionary, because that is how the spec sources 210e5c31af7Sopenharmony_ci tag these types even though they are not structs.""" 211e5c31af7Sopenharmony_ci OutputGenerator.genType(self, typeinfo, name, alias) 212e5c31af7Sopenharmony_ci 213e5c31af7Sopenharmony_ci typeElem = typeinfo.elem 214e5c31af7Sopenharmony_ci # If the type is a struct type, traverse the embedded <member> tags 215e5c31af7Sopenharmony_ci # generating a structure. Otherwise, emit the tag text. 216e5c31af7Sopenharmony_ci category = typeElem.get('category') 217e5c31af7Sopenharmony_ci 218e5c31af7Sopenharmony_ci # Add a typeCategory{} entry for the category of this type. 219e5c31af7Sopenharmony_ci self.addName(self.typeCategory, name, category) 220e5c31af7Sopenharmony_ci 221e5c31af7Sopenharmony_ci if category in ('struct', 'union'): 222e5c31af7Sopenharmony_ci self.genStruct(typeinfo, name, alias) 223e5c31af7Sopenharmony_ci else: 224e5c31af7Sopenharmony_ci if alias: 225e5c31af7Sopenharmony_ci # Add name -> alias mapping 226e5c31af7Sopenharmony_ci self.addName(self.alias, name, alias) 227e5c31af7Sopenharmony_ci 228e5c31af7Sopenharmony_ci # Always emit an alias (?!) 229e5c31af7Sopenharmony_ci count = 1 230e5c31af7Sopenharmony_ci 231e5c31af7Sopenharmony_ci # May want to only emit full type definition when not an alias? 232e5c31af7Sopenharmony_ci else: 233e5c31af7Sopenharmony_ci # Extract the type name 234e5c31af7Sopenharmony_ci # (from self.genOpts). Copy other text through unchanged. 235e5c31af7Sopenharmony_ci # If the resulting text is an empty string, do not emit it. 236e5c31af7Sopenharmony_ci count = len(noneStr(typeElem.text)) 237e5c31af7Sopenharmony_ci for elem in typeElem: 238e5c31af7Sopenharmony_ci count += len(noneStr(elem.text)) + len(noneStr(elem.tail)) 239e5c31af7Sopenharmony_ci 240e5c31af7Sopenharmony_ci if count > 0: 241e5c31af7Sopenharmony_ci if category == 'bitmask': 242e5c31af7Sopenharmony_ci requiredEnum = typeElem.get('requires') 243e5c31af7Sopenharmony_ci self.addName(self.flags, name, requiredEnum) 244e5c31af7Sopenharmony_ci 245e5c31af7Sopenharmony_ci # This happens when the Flags type is defined, but no 246e5c31af7Sopenharmony_ci # FlagBits are defined yet. 247e5c31af7Sopenharmony_ci if requiredEnum is not None: 248e5c31af7Sopenharmony_ci self.addMapping(name, requiredEnum) 249e5c31af7Sopenharmony_ci elif category == 'enum': 250e5c31af7Sopenharmony_ci # This case does not seem to come up. It nominally would 251e5c31af7Sopenharmony_ci # result from 252e5c31af7Sopenharmony_ci # <type name="Something" category="enum"/>, 253e5c31af7Sopenharmony_ci # but the output generator does not emit them directly. 254e5c31af7Sopenharmony_ci self.logMsg('warn', 'ScriptOutputGenerator::genType: invalid \'enum\' category for name:', name) 255e5c31af7Sopenharmony_ci elif category == 'funcpointer': 256e5c31af7Sopenharmony_ci self.funcpointers[name] = None 257e5c31af7Sopenharmony_ci elif category == 'handle': 258e5c31af7Sopenharmony_ci self.handles[name] = None 259e5c31af7Sopenharmony_ci elif category == 'define': 260e5c31af7Sopenharmony_ci self.defines[name] = None 261e5c31af7Sopenharmony_ci elif category == 'basetype': 262e5c31af7Sopenharmony_ci self.basetypes[name] = None 263e5c31af7Sopenharmony_ci self.addName(self.typeCategory, name, 'basetype') 264e5c31af7Sopenharmony_ci else: 265e5c31af7Sopenharmony_ci self.logMsg('diag', 'ScriptOutputGenerator::genType: unprocessed type:', name) 266e5c31af7Sopenharmony_ci 267e5c31af7Sopenharmony_ci def genStruct(self, typeinfo, typeName, alias): 268e5c31af7Sopenharmony_ci """Generate struct (e.g. C "struct" type). 269e5c31af7Sopenharmony_ci 270e5c31af7Sopenharmony_ci Add the struct name to the 'structs' dictionary, with the 271e5c31af7Sopenharmony_ci value being an ordered list of the struct member names.""" 272e5c31af7Sopenharmony_ci OutputGenerator.genStruct(self, typeinfo, typeName, alias) 273e5c31af7Sopenharmony_ci 274e5c31af7Sopenharmony_ci if alias: 275e5c31af7Sopenharmony_ci # Add name -> alias mapping 276e5c31af7Sopenharmony_ci self.addName(self.alias, typeName, alias) 277e5c31af7Sopenharmony_ci else: 278e5c31af7Sopenharmony_ci # May want to only emit definition on this branch 279e5c31af7Sopenharmony_ci True 280e5c31af7Sopenharmony_ci 281e5c31af7Sopenharmony_ci members = [member.text for member in typeinfo.elem.findall('.//member/name')] 282e5c31af7Sopenharmony_ci self.structs[typeName] = members 283e5c31af7Sopenharmony_ci memberTypes = [member.text for member in typeinfo.elem.findall('.//member/type')] 284e5c31af7Sopenharmony_ci for member_type in memberTypes: 285e5c31af7Sopenharmony_ci self.addMapping(typeName, member_type) 286e5c31af7Sopenharmony_ci 287e5c31af7Sopenharmony_ci def genGroup(self, groupinfo, groupName, alias): 288e5c31af7Sopenharmony_ci """Generate group (e.g. C "enum" type). 289e5c31af7Sopenharmony_ci 290e5c31af7Sopenharmony_ci These are concatenated together with other types. 291e5c31af7Sopenharmony_ci 292e5c31af7Sopenharmony_ci - Add the enum type name to the 'enums' dictionary, with 293e5c31af7Sopenharmony_ci the value being an ordered list of the enumerant names. 294e5c31af7Sopenharmony_ci - Add each enumerant name to the 'consts' dictionary, with 295e5c31af7Sopenharmony_ci the value being the enum type the enumerant is part of.""" 296e5c31af7Sopenharmony_ci OutputGenerator.genGroup(self, groupinfo, groupName, alias) 297e5c31af7Sopenharmony_ci groupElem = groupinfo.elem 298e5c31af7Sopenharmony_ci 299e5c31af7Sopenharmony_ci # Add a typeCategory{} entry for the category of this type. 300e5c31af7Sopenharmony_ci self.addName(self.typeCategory, groupName, 'group') 301e5c31af7Sopenharmony_ci 302e5c31af7Sopenharmony_ci if alias: 303e5c31af7Sopenharmony_ci # Add name -> alias mapping 304e5c31af7Sopenharmony_ci self.addName(self.alias, groupName, alias) 305e5c31af7Sopenharmony_ci else: 306e5c31af7Sopenharmony_ci # May want to only emit definition on this branch 307e5c31af7Sopenharmony_ci True 308e5c31af7Sopenharmony_ci 309e5c31af7Sopenharmony_ci # Add each nested 'enum' tag 310e5c31af7Sopenharmony_ci enumerants = [elem.get('name') for elem in groupElem.findall('enum')] 311e5c31af7Sopenharmony_ci for name in enumerants: 312e5c31af7Sopenharmony_ci self.addName(self.consts, name, groupName) 313e5c31af7Sopenharmony_ci 314e5c31af7Sopenharmony_ci # Sort enums for output stability, since their order is irrelevant 315e5c31af7Sopenharmony_ci self.enums[groupName] = sorted(enumerants) 316e5c31af7Sopenharmony_ci 317e5c31af7Sopenharmony_ci def genEnum(self, enuminfo, name, alias): 318e5c31af7Sopenharmony_ci """Generate enumerant (compile time constant). 319e5c31af7Sopenharmony_ci 320e5c31af7Sopenharmony_ci - Add the constant name to the 'consts' dictionary, with the 321e5c31af7Sopenharmony_ci value being None to indicate that the constant is not 322e5c31af7Sopenharmony_ci an enumeration value.""" 323e5c31af7Sopenharmony_ci OutputGenerator.genEnum(self, enuminfo, name, alias) 324e5c31af7Sopenharmony_ci 325e5c31af7Sopenharmony_ci if name not in self.consts: 326e5c31af7Sopenharmony_ci # Add a typeCategory{} entry for the category of this type. 327e5c31af7Sopenharmony_ci self.addName(self.typeCategory, name, 'consts') 328e5c31af7Sopenharmony_ci self.consts[name] = None 329e5c31af7Sopenharmony_ci 330e5c31af7Sopenharmony_ci if alias: 331e5c31af7Sopenharmony_ci # Add name -> alias mapping 332e5c31af7Sopenharmony_ci self.addName(self.alias, name, alias) 333e5c31af7Sopenharmony_ci else: 334e5c31af7Sopenharmony_ci # May want to only emit definition on this branch 335e5c31af7Sopenharmony_ci True 336e5c31af7Sopenharmony_ci 337e5c31af7Sopenharmony_ci # Otherwise, do not add it to the consts dictionary because it is 338e5c31af7Sopenharmony_ci # already present. This happens due to the generator 'reparentEnums' 339e5c31af7Sopenharmony_ci # parameter being False, so each extension enum appears in both the 340e5c31af7Sopenharmony_ci # <enums> type and in the <extension> or <feature> it originally 341e5c31af7Sopenharmony_ci # came from. 342e5c31af7Sopenharmony_ci 343e5c31af7Sopenharmony_ci def genCmd(self, cmdinfo, name, alias): 344e5c31af7Sopenharmony_ci """Generate command. 345e5c31af7Sopenharmony_ci 346e5c31af7Sopenharmony_ci - Add the command name to the 'protos' dictionary, with the 347e5c31af7Sopenharmony_ci value being an ordered list of the parameter names.""" 348e5c31af7Sopenharmony_ci OutputGenerator.genCmd(self, cmdinfo, name, alias) 349e5c31af7Sopenharmony_ci 350e5c31af7Sopenharmony_ci # Add a typeCategory{} entry for the category of this type. 351e5c31af7Sopenharmony_ci self.addName(self.typeCategory, name, 'protos') 352e5c31af7Sopenharmony_ci 353e5c31af7Sopenharmony_ci if alias: 354e5c31af7Sopenharmony_ci # Add name -> alias mapping 355e5c31af7Sopenharmony_ci self.addName(self.alias, name, alias) 356e5c31af7Sopenharmony_ci else: 357e5c31af7Sopenharmony_ci # May want to only emit definition on this branch 358e5c31af7Sopenharmony_ci True 359e5c31af7Sopenharmony_ci 360e5c31af7Sopenharmony_ci params = [param.text for param in cmdinfo.elem.findall('param/name')] 361e5c31af7Sopenharmony_ci self.protos[name] = params 362e5c31af7Sopenharmony_ci paramTypes = [param.text for param in cmdinfo.elem.findall('param/type')] 363e5c31af7Sopenharmony_ci for param_type in paramTypes: 364e5c31af7Sopenharmony_ci self.addMapping(name, param_type) 365e5c31af7Sopenharmony_ci 366e5c31af7Sopenharmony_ci def createInverseMap(self): 367e5c31af7Sopenharmony_ci """This creates the inverse mapping of nonexistent APIs in this 368e5c31af7Sopenharmony_ci build to their aliases which are supported. Must be called by 369e5c31af7Sopenharmony_ci language-specific subclasses before emitting that mapping.""" 370e5c31af7Sopenharmony_ci 371e5c31af7Sopenharmony_ci # Map from APIs not supported in this build to aliases that are. 372e5c31af7Sopenharmony_ci # When there are multiple valid choices for remapping, choose the 373e5c31af7Sopenharmony_ci # most-official suffixed one (KHR > EXT > vendor). 374e5c31af7Sopenharmony_ci for key in self.alias: 375e5c31af7Sopenharmony_ci # If the API key is aliased to something which does not exist, 376e5c31af7Sopenharmony_ci # then add the thing that does not exist to the nonexistent map. 377e5c31af7Sopenharmony_ci # This is used in spec macros to make promoted extension links 378e5c31af7Sopenharmony_ci # in specs built without the promoted interface refer to the 379e5c31af7Sopenharmony_ci # older interface instead. 380e5c31af7Sopenharmony_ci 381e5c31af7Sopenharmony_ci invkey = self.alias[key] 382e5c31af7Sopenharmony_ci 383e5c31af7Sopenharmony_ci if invkey not in self.typeCategory: 384e5c31af7Sopenharmony_ci if invkey in self.nonexistent: 385e5c31af7Sopenharmony_ci # Potentially remap existing mapping to a more official 386e5c31af7Sopenharmony_ci # alias. 387e5c31af7Sopenharmony_ci self.nonexistent[invkey] = mostOfficial(self.nonexistent[invkey], key) 388e5c31af7Sopenharmony_ci else: 389e5c31af7Sopenharmony_ci # Create remapping to an alias 390e5c31af7Sopenharmony_ci self.nonexistent[invkey] = key 391