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_ciimport os 8e5c31af7Sopenharmony_ciimport re 9e5c31af7Sopenharmony_ci 10e5c31af7Sopenharmony_cifrom generator import (GeneratorOptions, 11e5c31af7Sopenharmony_ci MissingGeneratorOptionsConventionsError, 12e5c31af7Sopenharmony_ci MissingGeneratorOptionsError, MissingRegistryError, 13e5c31af7Sopenharmony_ci OutputGenerator, noneStr, regSortFeatures, write) 14e5c31af7Sopenharmony_ci 15e5c31af7Sopenharmony_ciclass CGeneratorOptions(GeneratorOptions): 16e5c31af7Sopenharmony_ci """CGeneratorOptions - subclass of GeneratorOptions. 17e5c31af7Sopenharmony_ci 18e5c31af7Sopenharmony_ci Adds options used by COutputGenerator objects during C language header 19e5c31af7Sopenharmony_ci generation.""" 20e5c31af7Sopenharmony_ci 21e5c31af7Sopenharmony_ci def __init__(self, 22e5c31af7Sopenharmony_ci prefixText='', 23e5c31af7Sopenharmony_ci genFuncPointers=True, 24e5c31af7Sopenharmony_ci protectFile=True, 25e5c31af7Sopenharmony_ci protectFeature=True, 26e5c31af7Sopenharmony_ci protectProto=None, 27e5c31af7Sopenharmony_ci protectProtoStr=None, 28e5c31af7Sopenharmony_ci protectExtensionProto=None, 29e5c31af7Sopenharmony_ci protectExtensionProtoStr=None, 30e5c31af7Sopenharmony_ci apicall='', 31e5c31af7Sopenharmony_ci apientry='', 32e5c31af7Sopenharmony_ci apientryp='', 33e5c31af7Sopenharmony_ci indentFuncProto=True, 34e5c31af7Sopenharmony_ci indentFuncPointer=False, 35e5c31af7Sopenharmony_ci alignFuncParam=0, 36e5c31af7Sopenharmony_ci genEnumBeginEndRange=False, 37e5c31af7Sopenharmony_ci genAliasMacro=False, 38e5c31af7Sopenharmony_ci genStructExtendsComment=False, 39e5c31af7Sopenharmony_ci aliasMacro='', 40e5c31af7Sopenharmony_ci misracstyle=False, 41e5c31af7Sopenharmony_ci misracppstyle=False, 42e5c31af7Sopenharmony_ci **kwargs 43e5c31af7Sopenharmony_ci ): 44e5c31af7Sopenharmony_ci """Constructor. 45e5c31af7Sopenharmony_ci Additional parameters beyond parent class: 46e5c31af7Sopenharmony_ci 47e5c31af7Sopenharmony_ci - prefixText - list of strings to prefix generated header with 48e5c31af7Sopenharmony_ci (usually a copyright statement + calling convention macros) 49e5c31af7Sopenharmony_ci - protectFile - True if multiple inclusion protection should be 50e5c31af7Sopenharmony_ci generated (based on the filename) around the entire header 51e5c31af7Sopenharmony_ci - protectFeature - True if #ifndef..#endif protection should be 52e5c31af7Sopenharmony_ci generated around a feature interface in the header file 53e5c31af7Sopenharmony_ci - genFuncPointers - True if function pointer typedefs should be 54e5c31af7Sopenharmony_ci generated 55e5c31af7Sopenharmony_ci - protectProto - If conditional protection should be generated 56e5c31af7Sopenharmony_ci around prototype declarations, set to either '#ifdef' 57e5c31af7Sopenharmony_ci to require opt-in (#ifdef protectProtoStr) or '#ifndef' 58e5c31af7Sopenharmony_ci to require opt-out (#ifndef protectProtoStr). Otherwise 59e5c31af7Sopenharmony_ci set to None. 60e5c31af7Sopenharmony_ci - protectProtoStr - #ifdef/#ifndef symbol to use around prototype 61e5c31af7Sopenharmony_ci declarations, if protectProto is set 62e5c31af7Sopenharmony_ci - protectExtensionProto - If conditional protection should be generated 63e5c31af7Sopenharmony_ci around extension prototype declarations, set to either '#ifdef' 64e5c31af7Sopenharmony_ci to require opt-in (#ifdef protectExtensionProtoStr) or '#ifndef' 65e5c31af7Sopenharmony_ci to require opt-out (#ifndef protectExtensionProtoStr). Otherwise 66e5c31af7Sopenharmony_ci set to None 67e5c31af7Sopenharmony_ci - protectExtensionProtoStr - #ifdef/#ifndef symbol to use around 68e5c31af7Sopenharmony_ci extension prototype declarations, if protectExtensionProto is set 69e5c31af7Sopenharmony_ci - apicall - string to use for the function declaration prefix, 70e5c31af7Sopenharmony_ci such as APICALL on Windows 71e5c31af7Sopenharmony_ci - apientry - string to use for the calling convention macro, 72e5c31af7Sopenharmony_ci in typedefs, such as APIENTRY 73e5c31af7Sopenharmony_ci - apientryp - string to use for the calling convention macro 74e5c31af7Sopenharmony_ci in function pointer typedefs, such as APIENTRYP 75e5c31af7Sopenharmony_ci - indentFuncProto - True if prototype declarations should put each 76e5c31af7Sopenharmony_ci parameter on a separate line 77e5c31af7Sopenharmony_ci - indentFuncPointer - True if typedefed function pointers should put each 78e5c31af7Sopenharmony_ci parameter on a separate line 79e5c31af7Sopenharmony_ci - alignFuncParam - if nonzero and parameters are being put on a 80e5c31af7Sopenharmony_ci separate line, align parameter names at the specified column 81e5c31af7Sopenharmony_ci - genEnumBeginEndRange - True if BEGIN_RANGE / END_RANGE macros should 82e5c31af7Sopenharmony_ci be generated for enumerated types 83e5c31af7Sopenharmony_ci - genAliasMacro - True if the OpenXR alias macro should be generated 84e5c31af7Sopenharmony_ci for aliased types (unclear what other circumstances this is useful) 85e5c31af7Sopenharmony_ci - genStructExtendsComment - True if comments showing the structures 86e5c31af7Sopenharmony_ci whose pNext chain a structure extends are included before its 87e5c31af7Sopenharmony_ci definition 88e5c31af7Sopenharmony_ci - aliasMacro - alias macro to inject when genAliasMacro is True 89e5c31af7Sopenharmony_ci - misracstyle - generate MISRA C-friendly headers 90e5c31af7Sopenharmony_ci - misracppstyle - generate MISRA C++-friendly headers""" 91e5c31af7Sopenharmony_ci 92e5c31af7Sopenharmony_ci GeneratorOptions.__init__(self, **kwargs) 93e5c31af7Sopenharmony_ci 94e5c31af7Sopenharmony_ci self.prefixText = prefixText 95e5c31af7Sopenharmony_ci """list of strings to prefix generated header with (usually a copyright statement + calling convention macros).""" 96e5c31af7Sopenharmony_ci 97e5c31af7Sopenharmony_ci self.genFuncPointers = genFuncPointers 98e5c31af7Sopenharmony_ci """True if function pointer typedefs should be generated""" 99e5c31af7Sopenharmony_ci 100e5c31af7Sopenharmony_ci self.protectFile = protectFile 101e5c31af7Sopenharmony_ci """True if multiple inclusion protection should be generated (based on the filename) around the entire header.""" 102e5c31af7Sopenharmony_ci 103e5c31af7Sopenharmony_ci self.protectFeature = protectFeature 104e5c31af7Sopenharmony_ci """True if #ifndef..#endif protection should be generated around a feature interface in the header file.""" 105e5c31af7Sopenharmony_ci 106e5c31af7Sopenharmony_ci self.protectProto = protectProto 107e5c31af7Sopenharmony_ci """If conditional protection should be generated around prototype declarations, set to either '#ifdef' to require opt-in (#ifdef protectProtoStr) or '#ifndef' to require opt-out (#ifndef protectProtoStr). Otherwise set to None.""" 108e5c31af7Sopenharmony_ci 109e5c31af7Sopenharmony_ci self.protectProtoStr = protectProtoStr 110e5c31af7Sopenharmony_ci """#ifdef/#ifndef symbol to use around prototype declarations, if protectProto is set""" 111e5c31af7Sopenharmony_ci 112e5c31af7Sopenharmony_ci self.protectExtensionProto = protectExtensionProto 113e5c31af7Sopenharmony_ci """If conditional protection should be generated around extension prototype declarations, set to either '#ifdef' to require opt-in (#ifdef protectExtensionProtoStr) or '#ifndef' to require opt-out (#ifndef protectExtensionProtoStr). Otherwise set to None.""" 114e5c31af7Sopenharmony_ci 115e5c31af7Sopenharmony_ci self.protectExtensionProtoStr = protectExtensionProtoStr 116e5c31af7Sopenharmony_ci """#ifdef/#ifndef symbol to use around extension prototype declarations, if protectExtensionProto is set""" 117e5c31af7Sopenharmony_ci 118e5c31af7Sopenharmony_ci self.apicall = apicall 119e5c31af7Sopenharmony_ci """string to use for the function declaration prefix, such as APICALL on Windows.""" 120e5c31af7Sopenharmony_ci 121e5c31af7Sopenharmony_ci self.apientry = apientry 122e5c31af7Sopenharmony_ci """string to use for the calling convention macro, in typedefs, such as APIENTRY.""" 123e5c31af7Sopenharmony_ci 124e5c31af7Sopenharmony_ci self.apientryp = apientryp 125e5c31af7Sopenharmony_ci """string to use for the calling convention macro in function pointer typedefs, such as APIENTRYP.""" 126e5c31af7Sopenharmony_ci 127e5c31af7Sopenharmony_ci self.indentFuncProto = indentFuncProto 128e5c31af7Sopenharmony_ci """True if prototype declarations should put each parameter on a separate line""" 129e5c31af7Sopenharmony_ci 130e5c31af7Sopenharmony_ci self.indentFuncPointer = indentFuncPointer 131e5c31af7Sopenharmony_ci """True if typedefed function pointers should put each parameter on a separate line""" 132e5c31af7Sopenharmony_ci 133e5c31af7Sopenharmony_ci self.alignFuncParam = alignFuncParam 134e5c31af7Sopenharmony_ci """if nonzero and parameters are being put on a separate line, align parameter names at the specified column""" 135e5c31af7Sopenharmony_ci 136e5c31af7Sopenharmony_ci self.genEnumBeginEndRange = genEnumBeginEndRange 137e5c31af7Sopenharmony_ci """True if BEGIN_RANGE / END_RANGE macros should be generated for enumerated types""" 138e5c31af7Sopenharmony_ci 139e5c31af7Sopenharmony_ci self.genAliasMacro = genAliasMacro 140e5c31af7Sopenharmony_ci """True if the OpenXR alias macro should be generated for aliased types (unclear what other circumstances this is useful)""" 141e5c31af7Sopenharmony_ci 142e5c31af7Sopenharmony_ci self.genStructExtendsComment = genStructExtendsComment 143e5c31af7Sopenharmony_ci """True if comments showing the structures whose pNext chain a structure extends are included before its definition""" 144e5c31af7Sopenharmony_ci 145e5c31af7Sopenharmony_ci self.aliasMacro = aliasMacro 146e5c31af7Sopenharmony_ci """alias macro to inject when genAliasMacro is True""" 147e5c31af7Sopenharmony_ci 148e5c31af7Sopenharmony_ci self.misracstyle = misracstyle 149e5c31af7Sopenharmony_ci """generate MISRA C-friendly headers""" 150e5c31af7Sopenharmony_ci 151e5c31af7Sopenharmony_ci self.misracppstyle = misracppstyle 152e5c31af7Sopenharmony_ci """generate MISRA C++-friendly headers""" 153e5c31af7Sopenharmony_ci 154e5c31af7Sopenharmony_ci self.codeGenerator = True 155e5c31af7Sopenharmony_ci """True if this generator makes compilable code""" 156e5c31af7Sopenharmony_ci 157e5c31af7Sopenharmony_ci 158e5c31af7Sopenharmony_ciclass COutputGenerator(OutputGenerator): 159e5c31af7Sopenharmony_ci """Generates C-language API interfaces.""" 160e5c31af7Sopenharmony_ci 161e5c31af7Sopenharmony_ci # This is an ordered list of sections in the header file. 162e5c31af7Sopenharmony_ci TYPE_SECTIONS = ['include', 'define', 'basetype', 'handle', 'enum', 163e5c31af7Sopenharmony_ci 'group', 'bitmask', 'funcpointer', 'struct'] 164e5c31af7Sopenharmony_ci ALL_SECTIONS = TYPE_SECTIONS + ['commandPointer', 'command'] 165e5c31af7Sopenharmony_ci 166e5c31af7Sopenharmony_ci def __init__(self, *args, **kwargs): 167e5c31af7Sopenharmony_ci super().__init__(*args, **kwargs) 168e5c31af7Sopenharmony_ci # Internal state - accumulators for different inner block text 169e5c31af7Sopenharmony_ci self.sections = {section: [] for section in self.ALL_SECTIONS} 170e5c31af7Sopenharmony_ci self.feature_not_empty = False 171e5c31af7Sopenharmony_ci self.may_alias = None 172e5c31af7Sopenharmony_ci 173e5c31af7Sopenharmony_ci def beginFile(self, genOpts): 174e5c31af7Sopenharmony_ci OutputGenerator.beginFile(self, genOpts) 175e5c31af7Sopenharmony_ci if self.genOpts is None: 176e5c31af7Sopenharmony_ci raise MissingGeneratorOptionsError() 177e5c31af7Sopenharmony_ci # C-specific 178e5c31af7Sopenharmony_ci # 179e5c31af7Sopenharmony_ci # Multiple inclusion protection & C++ wrappers. 180e5c31af7Sopenharmony_ci if self.genOpts.protectFile and self.genOpts.filename: 181e5c31af7Sopenharmony_ci headerSym = re.sub(r'\.h', '_h_', 182e5c31af7Sopenharmony_ci os.path.basename(self.genOpts.filename)).upper() 183e5c31af7Sopenharmony_ci write('#ifndef', headerSym, file=self.outFile) 184e5c31af7Sopenharmony_ci write('#define', headerSym, '1', file=self.outFile) 185e5c31af7Sopenharmony_ci self.newline() 186e5c31af7Sopenharmony_ci 187e5c31af7Sopenharmony_ci # User-supplied prefix text, if any (list of strings) 188e5c31af7Sopenharmony_ci if genOpts.prefixText: 189e5c31af7Sopenharmony_ci for s in genOpts.prefixText: 190e5c31af7Sopenharmony_ci write(s, file=self.outFile) 191e5c31af7Sopenharmony_ci 192e5c31af7Sopenharmony_ci # C++ extern wrapper - after prefix lines so they can add includes. 193e5c31af7Sopenharmony_ci self.newline() 194e5c31af7Sopenharmony_ci write('#ifdef __cplusplus', file=self.outFile) 195e5c31af7Sopenharmony_ci write('extern "C" {', file=self.outFile) 196e5c31af7Sopenharmony_ci write('#endif', file=self.outFile) 197e5c31af7Sopenharmony_ci self.newline() 198e5c31af7Sopenharmony_ci 199e5c31af7Sopenharmony_ci def endFile(self): 200e5c31af7Sopenharmony_ci # C-specific 201e5c31af7Sopenharmony_ci # Finish C++ wrapper and multiple inclusion protection 202e5c31af7Sopenharmony_ci if self.genOpts is None: 203e5c31af7Sopenharmony_ci raise MissingGeneratorOptionsError() 204e5c31af7Sopenharmony_ci self.newline() 205e5c31af7Sopenharmony_ci write('#ifdef __cplusplus', file=self.outFile) 206e5c31af7Sopenharmony_ci write('}', file=self.outFile) 207e5c31af7Sopenharmony_ci write('#endif', file=self.outFile) 208e5c31af7Sopenharmony_ci if self.genOpts.protectFile and self.genOpts.filename: 209e5c31af7Sopenharmony_ci self.newline() 210e5c31af7Sopenharmony_ci write('#endif', file=self.outFile) 211e5c31af7Sopenharmony_ci # Finish processing in superclass 212e5c31af7Sopenharmony_ci OutputGenerator.endFile(self) 213e5c31af7Sopenharmony_ci 214e5c31af7Sopenharmony_ci def beginFeature(self, interface, emit): 215e5c31af7Sopenharmony_ci # Start processing in superclass 216e5c31af7Sopenharmony_ci OutputGenerator.beginFeature(self, interface, emit) 217e5c31af7Sopenharmony_ci # C-specific 218e5c31af7Sopenharmony_ci # Accumulate includes, defines, types, enums, function pointer typedefs, 219e5c31af7Sopenharmony_ci # end function prototypes separately for this feature. They are only 220e5c31af7Sopenharmony_ci # printed in endFeature(). 221e5c31af7Sopenharmony_ci self.sections = {section: [] for section in self.ALL_SECTIONS} 222e5c31af7Sopenharmony_ci self.feature_not_empty = False 223e5c31af7Sopenharmony_ci 224e5c31af7Sopenharmony_ci def _endProtectComment(self, protect_str, protect_directive='#ifdef'): 225e5c31af7Sopenharmony_ci if protect_directive is None or protect_str is None: 226e5c31af7Sopenharmony_ci raise RuntimeError('Should not call in here without something to protect') 227e5c31af7Sopenharmony_ci 228e5c31af7Sopenharmony_ci # Do not put comments after #endif closing blocks if this is not set 229e5c31af7Sopenharmony_ci if not self.genOpts.conventions.protectProtoComment: 230e5c31af7Sopenharmony_ci return '' 231e5c31af7Sopenharmony_ci elif 'ifdef' in protect_directive: 232e5c31af7Sopenharmony_ci return f' /* {protect_str} */' 233e5c31af7Sopenharmony_ci else: 234e5c31af7Sopenharmony_ci return f' /* !{protect_str} */' 235e5c31af7Sopenharmony_ci 236e5c31af7Sopenharmony_ci def endFeature(self): 237e5c31af7Sopenharmony_ci "Actually write the interface to the output file." 238e5c31af7Sopenharmony_ci # C-specific 239e5c31af7Sopenharmony_ci if self.emit: 240e5c31af7Sopenharmony_ci if self.feature_not_empty: 241e5c31af7Sopenharmony_ci if self.genOpts is None: 242e5c31af7Sopenharmony_ci raise MissingGeneratorOptionsError() 243e5c31af7Sopenharmony_ci if self.genOpts.conventions is None: 244e5c31af7Sopenharmony_ci raise MissingGeneratorOptionsConventionsError() 245e5c31af7Sopenharmony_ci is_core = self.featureName and self.featureName.startswith(self.conventions.api_prefix + 'VERSION_') 246e5c31af7Sopenharmony_ci if self.genOpts.conventions.writeFeature(self.featureExtraProtect, self.genOpts.filename): 247e5c31af7Sopenharmony_ci self.newline() 248e5c31af7Sopenharmony_ci if self.genOpts.protectFeature: 249e5c31af7Sopenharmony_ci write('#ifndef', self.featureName, file=self.outFile) 250e5c31af7Sopenharmony_ci 251e5c31af7Sopenharmony_ci # If type declarations are needed by other features based on 252e5c31af7Sopenharmony_ci # this one, it may be necessary to suppress the ExtraProtect, 253e5c31af7Sopenharmony_ci # or move it below the 'for section...' loop. 254e5c31af7Sopenharmony_ci if self.featureExtraProtect is not None: 255e5c31af7Sopenharmony_ci write('#ifdef', self.featureExtraProtect, file=self.outFile) 256e5c31af7Sopenharmony_ci self.newline() 257e5c31af7Sopenharmony_ci 258e5c31af7Sopenharmony_ci # Generate warning of possible use in IDEs 259e5c31af7Sopenharmony_ci write(f'// {self.featureName} is a preprocessor guard. Do not pass it to API calls.', file=self.outFile) 260e5c31af7Sopenharmony_ci write('#define', self.featureName, '1', file=self.outFile) 261e5c31af7Sopenharmony_ci for section in self.TYPE_SECTIONS: 262e5c31af7Sopenharmony_ci contents = self.sections[section] 263e5c31af7Sopenharmony_ci if contents: 264e5c31af7Sopenharmony_ci write('\n'.join(contents), file=self.outFile) 265e5c31af7Sopenharmony_ci 266e5c31af7Sopenharmony_ci if self.genOpts.genFuncPointers and self.sections['commandPointer']: 267e5c31af7Sopenharmony_ci write('\n'.join(self.sections['commandPointer']), file=self.outFile) 268e5c31af7Sopenharmony_ci self.newline() 269e5c31af7Sopenharmony_ci 270e5c31af7Sopenharmony_ci if self.sections['command']: 271e5c31af7Sopenharmony_ci if self.genOpts.protectProto: 272e5c31af7Sopenharmony_ci write(self.genOpts.protectProto, 273e5c31af7Sopenharmony_ci self.genOpts.protectProtoStr, file=self.outFile) 274e5c31af7Sopenharmony_ci if self.genOpts.protectExtensionProto and not is_core: 275e5c31af7Sopenharmony_ci write(self.genOpts.protectExtensionProto, 276e5c31af7Sopenharmony_ci self.genOpts.protectExtensionProtoStr, file=self.outFile) 277e5c31af7Sopenharmony_ci write('\n'.join(self.sections['command']), end='', file=self.outFile) 278e5c31af7Sopenharmony_ci if self.genOpts.protectExtensionProto and not is_core: 279e5c31af7Sopenharmony_ci write('#endif' + 280e5c31af7Sopenharmony_ci self._endProtectComment(protect_directive=self.genOpts.protectExtensionProto, 281e5c31af7Sopenharmony_ci protect_str=self.genOpts.protectExtensionProtoStr), 282e5c31af7Sopenharmony_ci file=self.outFile) 283e5c31af7Sopenharmony_ci if self.genOpts.protectProto: 284e5c31af7Sopenharmony_ci write('#endif' + 285e5c31af7Sopenharmony_ci self._endProtectComment(protect_directive=self.genOpts.protectProto, 286e5c31af7Sopenharmony_ci protect_str=self.genOpts.protectProtoStr), 287e5c31af7Sopenharmony_ci file=self.outFile) 288e5c31af7Sopenharmony_ci else: 289e5c31af7Sopenharmony_ci self.newline() 290e5c31af7Sopenharmony_ci 291e5c31af7Sopenharmony_ci if self.featureExtraProtect is not None: 292e5c31af7Sopenharmony_ci write('#endif' + 293e5c31af7Sopenharmony_ci self._endProtectComment(protect_str=self.featureExtraProtect), 294e5c31af7Sopenharmony_ci file=self.outFile) 295e5c31af7Sopenharmony_ci 296e5c31af7Sopenharmony_ci if self.genOpts.protectFeature: 297e5c31af7Sopenharmony_ci write('#endif' + 298e5c31af7Sopenharmony_ci self._endProtectComment(protect_str=self.featureName), 299e5c31af7Sopenharmony_ci file=self.outFile) 300e5c31af7Sopenharmony_ci # Finish processing in superclass 301e5c31af7Sopenharmony_ci OutputGenerator.endFeature(self) 302e5c31af7Sopenharmony_ci 303e5c31af7Sopenharmony_ci def appendSection(self, section, text): 304e5c31af7Sopenharmony_ci "Append a definition to the specified section" 305e5c31af7Sopenharmony_ci 306e5c31af7Sopenharmony_ci if section is None: 307e5c31af7Sopenharmony_ci self.logMsg('error', 'Missing section in appendSection (probably a <type> element missing its \'category\' attribute. Text:', text) 308e5c31af7Sopenharmony_ci exit(1) 309e5c31af7Sopenharmony_ci 310e5c31af7Sopenharmony_ci self.sections[section].append(text) 311e5c31af7Sopenharmony_ci self.feature_not_empty = True 312e5c31af7Sopenharmony_ci 313e5c31af7Sopenharmony_ci def genType(self, typeinfo, name, alias): 314e5c31af7Sopenharmony_ci "Generate type." 315e5c31af7Sopenharmony_ci OutputGenerator.genType(self, typeinfo, name, alias) 316e5c31af7Sopenharmony_ci typeElem = typeinfo.elem 317e5c31af7Sopenharmony_ci 318e5c31af7Sopenharmony_ci # Vulkan: 319e5c31af7Sopenharmony_ci # Determine the category of the type, and the type section to add 320e5c31af7Sopenharmony_ci # its definition to. 321e5c31af7Sopenharmony_ci # 'funcpointer' is added to the 'struct' section as a workaround for 322e5c31af7Sopenharmony_ci # internal issue #877, since structures and function pointer types 323e5c31af7Sopenharmony_ci # can have cross-dependencies. 324e5c31af7Sopenharmony_ci category = typeElem.get('category') 325e5c31af7Sopenharmony_ci if category == 'funcpointer': 326e5c31af7Sopenharmony_ci section = 'struct' 327e5c31af7Sopenharmony_ci else: 328e5c31af7Sopenharmony_ci section = category 329e5c31af7Sopenharmony_ci 330e5c31af7Sopenharmony_ci if category in ('struct', 'union'): 331e5c31af7Sopenharmony_ci # If the type is a struct type, generate it using the 332e5c31af7Sopenharmony_ci # special-purpose generator. 333e5c31af7Sopenharmony_ci self.genStruct(typeinfo, name, alias) 334e5c31af7Sopenharmony_ci else: 335e5c31af7Sopenharmony_ci if self.genOpts is None: 336e5c31af7Sopenharmony_ci raise MissingGeneratorOptionsError() 337e5c31af7Sopenharmony_ci # OpenXR: this section was not under 'else:' previously, just fell through 338e5c31af7Sopenharmony_ci if alias: 339e5c31af7Sopenharmony_ci # If the type is an alias, just emit a typedef declaration 340e5c31af7Sopenharmony_ci body = 'typedef ' + alias + ' ' + name + ';\n' 341e5c31af7Sopenharmony_ci else: 342e5c31af7Sopenharmony_ci # Replace <apientry /> tags with an APIENTRY-style string 343e5c31af7Sopenharmony_ci # (from self.genOpts). Copy other text through unchanged. 344e5c31af7Sopenharmony_ci # If the resulting text is an empty string, do not emit it. 345e5c31af7Sopenharmony_ci body = noneStr(typeElem.text) 346e5c31af7Sopenharmony_ci for elem in typeElem: 347e5c31af7Sopenharmony_ci if elem.tag == 'apientry': 348e5c31af7Sopenharmony_ci body += self.genOpts.apientry + noneStr(elem.tail) 349e5c31af7Sopenharmony_ci else: 350e5c31af7Sopenharmony_ci body += noneStr(elem.text) + noneStr(elem.tail) 351e5c31af7Sopenharmony_ci if category == 'define' and self.misracppstyle(): 352e5c31af7Sopenharmony_ci body = body.replace("(uint32_t)", "static_cast<uint32_t>") 353e5c31af7Sopenharmony_ci if body: 354e5c31af7Sopenharmony_ci # Add extra newline after multi-line entries. 355e5c31af7Sopenharmony_ci if '\n' in body[0:-1]: 356e5c31af7Sopenharmony_ci body += '\n' 357e5c31af7Sopenharmony_ci self.appendSection(section, body) 358e5c31af7Sopenharmony_ci 359e5c31af7Sopenharmony_ci def genProtectString(self, protect_str): 360e5c31af7Sopenharmony_ci """Generate protection string. 361e5c31af7Sopenharmony_ci 362e5c31af7Sopenharmony_ci Protection strings are the strings defining the OS/Platform/Graphics 363e5c31af7Sopenharmony_ci requirements for a given API command. When generating the 364e5c31af7Sopenharmony_ci language header files, we need to make sure the items specific to a 365e5c31af7Sopenharmony_ci graphics API or OS platform are properly wrapped in #ifs.""" 366e5c31af7Sopenharmony_ci protect_if_str = '' 367e5c31af7Sopenharmony_ci protect_end_str = '' 368e5c31af7Sopenharmony_ci if not protect_str: 369e5c31af7Sopenharmony_ci return (protect_if_str, protect_end_str) 370e5c31af7Sopenharmony_ci 371e5c31af7Sopenharmony_ci if ',' in protect_str: 372e5c31af7Sopenharmony_ci protect_list = protect_str.split(',') 373e5c31af7Sopenharmony_ci protect_defs = ('defined(%s)' % d for d in protect_list) 374e5c31af7Sopenharmony_ci protect_def_str = ' && '.join(protect_defs) 375e5c31af7Sopenharmony_ci protect_if_str = '#if %s\n' % protect_def_str 376e5c31af7Sopenharmony_ci protect_end_str = '#endif // %s\n' % protect_def_str 377e5c31af7Sopenharmony_ci else: 378e5c31af7Sopenharmony_ci protect_if_str = '#ifdef %s\n' % protect_str 379e5c31af7Sopenharmony_ci protect_end_str = '#endif // %s\n' % protect_str 380e5c31af7Sopenharmony_ci 381e5c31af7Sopenharmony_ci return (protect_if_str, protect_end_str) 382e5c31af7Sopenharmony_ci 383e5c31af7Sopenharmony_ci def typeMayAlias(self, typeName): 384e5c31af7Sopenharmony_ci if not self.may_alias: 385e5c31af7Sopenharmony_ci if self.registry is None: 386e5c31af7Sopenharmony_ci raise MissingRegistryError() 387e5c31af7Sopenharmony_ci # First time we have asked if a type may alias. 388e5c31af7Sopenharmony_ci # So, populate the set of all names of types that may. 389e5c31af7Sopenharmony_ci 390e5c31af7Sopenharmony_ci # Everyone with an explicit mayalias="true" 391e5c31af7Sopenharmony_ci self.may_alias = set(typeName 392e5c31af7Sopenharmony_ci for typeName, data in self.registry.typedict.items() 393e5c31af7Sopenharmony_ci if data.elem.get('mayalias') == 'true') 394e5c31af7Sopenharmony_ci 395e5c31af7Sopenharmony_ci # Every type mentioned in some other type's parentstruct attribute. 396e5c31af7Sopenharmony_ci polymorphic_bases = (otherType.elem.get('parentstruct') 397e5c31af7Sopenharmony_ci for otherType in self.registry.typedict.values()) 398e5c31af7Sopenharmony_ci self.may_alias.update(set(x for x in polymorphic_bases 399e5c31af7Sopenharmony_ci if x is not None)) 400e5c31af7Sopenharmony_ci return typeName in self.may_alias 401e5c31af7Sopenharmony_ci 402e5c31af7Sopenharmony_ci def genStruct(self, typeinfo, typeName, alias): 403e5c31af7Sopenharmony_ci """Generate struct (e.g. C "struct" type). 404e5c31af7Sopenharmony_ci 405e5c31af7Sopenharmony_ci This is a special case of the <type> tag where the contents are 406e5c31af7Sopenharmony_ci interpreted as a set of <member> tags instead of freeform C 407e5c31af7Sopenharmony_ci C type declarations. The <member> tags are just like <param> 408e5c31af7Sopenharmony_ci tags - they are a declaration of a struct or union member. 409e5c31af7Sopenharmony_ci Only simple member declarations are supported (no nested 410e5c31af7Sopenharmony_ci structs etc.) 411e5c31af7Sopenharmony_ci 412e5c31af7Sopenharmony_ci If alias is not None, then this struct aliases another; just 413e5c31af7Sopenharmony_ci generate a typedef of that alias.""" 414e5c31af7Sopenharmony_ci OutputGenerator.genStruct(self, typeinfo, typeName, alias) 415e5c31af7Sopenharmony_ci 416e5c31af7Sopenharmony_ci if self.genOpts is None: 417e5c31af7Sopenharmony_ci raise MissingGeneratorOptionsError() 418e5c31af7Sopenharmony_ci 419e5c31af7Sopenharmony_ci typeElem = typeinfo.elem 420e5c31af7Sopenharmony_ci 421e5c31af7Sopenharmony_ci if alias: 422e5c31af7Sopenharmony_ci body = 'typedef ' + alias + ' ' + typeName + ';\n' 423e5c31af7Sopenharmony_ci else: 424e5c31af7Sopenharmony_ci body = '' 425e5c31af7Sopenharmony_ci (protect_begin, protect_end) = self.genProtectString(typeElem.get('protect')) 426e5c31af7Sopenharmony_ci if protect_begin: 427e5c31af7Sopenharmony_ci body += protect_begin 428e5c31af7Sopenharmony_ci 429e5c31af7Sopenharmony_ci if self.genOpts.genStructExtendsComment: 430e5c31af7Sopenharmony_ci structextends = typeElem.get('structextends') 431e5c31af7Sopenharmony_ci body += '// ' + typeName + ' extends ' + structextends + '\n' if structextends else '' 432e5c31af7Sopenharmony_ci 433e5c31af7Sopenharmony_ci body += 'typedef ' + typeElem.get('category') 434e5c31af7Sopenharmony_ci 435e5c31af7Sopenharmony_ci # This is an OpenXR-specific alternative where aliasing refers 436e5c31af7Sopenharmony_ci # to an inheritance hierarchy of types rather than C-level type 437e5c31af7Sopenharmony_ci # aliases. 438e5c31af7Sopenharmony_ci if self.genOpts.genAliasMacro and self.typeMayAlias(typeName): 439e5c31af7Sopenharmony_ci body += ' ' + self.genOpts.aliasMacro 440e5c31af7Sopenharmony_ci 441e5c31af7Sopenharmony_ci body += ' ' + typeName + ' {\n' 442e5c31af7Sopenharmony_ci 443e5c31af7Sopenharmony_ci targetLen = self.getMaxCParamTypeLength(typeinfo) 444e5c31af7Sopenharmony_ci for member in typeElem.findall('.//member'): 445e5c31af7Sopenharmony_ci body += self.makeCParamDecl(member, targetLen + 4) 446e5c31af7Sopenharmony_ci body += ';\n' 447e5c31af7Sopenharmony_ci body += '} ' + typeName + ';\n' 448e5c31af7Sopenharmony_ci if protect_end: 449e5c31af7Sopenharmony_ci body += protect_end 450e5c31af7Sopenharmony_ci 451e5c31af7Sopenharmony_ci self.appendSection('struct', body) 452e5c31af7Sopenharmony_ci 453e5c31af7Sopenharmony_ci def genGroup(self, groupinfo, groupName, alias=None): 454e5c31af7Sopenharmony_ci """Generate groups (e.g. C "enum" type). 455e5c31af7Sopenharmony_ci 456e5c31af7Sopenharmony_ci These are concatenated together with other types. 457e5c31af7Sopenharmony_ci 458e5c31af7Sopenharmony_ci If alias is not None, it is the name of another group type 459e5c31af7Sopenharmony_ci which aliases this type; just generate that alias.""" 460e5c31af7Sopenharmony_ci OutputGenerator.genGroup(self, groupinfo, groupName, alias) 461e5c31af7Sopenharmony_ci groupElem = groupinfo.elem 462e5c31af7Sopenharmony_ci 463e5c31af7Sopenharmony_ci # After either enumerated type or alias paths, add the declaration 464e5c31af7Sopenharmony_ci # to the appropriate section for the group being defined. 465e5c31af7Sopenharmony_ci if groupElem.get('type') == 'bitmask': 466e5c31af7Sopenharmony_ci section = 'bitmask' 467e5c31af7Sopenharmony_ci else: 468e5c31af7Sopenharmony_ci section = 'group' 469e5c31af7Sopenharmony_ci 470e5c31af7Sopenharmony_ci if alias: 471e5c31af7Sopenharmony_ci # If the group name is aliased, just emit a typedef declaration 472e5c31af7Sopenharmony_ci # for the alias. 473e5c31af7Sopenharmony_ci body = 'typedef ' + alias + ' ' + groupName + ';\n' 474e5c31af7Sopenharmony_ci self.appendSection(section, body) 475e5c31af7Sopenharmony_ci else: 476e5c31af7Sopenharmony_ci if self.genOpts is None: 477e5c31af7Sopenharmony_ci raise MissingGeneratorOptionsError() 478e5c31af7Sopenharmony_ci (section, body) = self.buildEnumCDecl(self.genOpts.genEnumBeginEndRange, groupinfo, groupName) 479e5c31af7Sopenharmony_ci self.appendSection(section, '\n' + body) 480e5c31af7Sopenharmony_ci 481e5c31af7Sopenharmony_ci def genEnum(self, enuminfo, name, alias): 482e5c31af7Sopenharmony_ci """Generate the C declaration for a constant (a single <enum> value). 483e5c31af7Sopenharmony_ci 484e5c31af7Sopenharmony_ci <enum> tags may specify their values in several ways, but are usually 485e5c31af7Sopenharmony_ci just integers.""" 486e5c31af7Sopenharmony_ci 487e5c31af7Sopenharmony_ci OutputGenerator.genEnum(self, enuminfo, name, alias) 488e5c31af7Sopenharmony_ci 489e5c31af7Sopenharmony_ci body = self.buildConstantCDecl(enuminfo, name, alias) 490e5c31af7Sopenharmony_ci self.appendSection('enum', body) 491e5c31af7Sopenharmony_ci 492e5c31af7Sopenharmony_ci def genCmd(self, cmdinfo, name, alias): 493e5c31af7Sopenharmony_ci "Command generation" 494e5c31af7Sopenharmony_ci OutputGenerator.genCmd(self, cmdinfo, name, alias) 495e5c31af7Sopenharmony_ci 496e5c31af7Sopenharmony_ci # if alias: 497e5c31af7Sopenharmony_ci # prefix = '// ' + name + ' is an alias of command ' + alias + '\n' 498e5c31af7Sopenharmony_ci # else: 499e5c31af7Sopenharmony_ci # prefix = '' 500e5c31af7Sopenharmony_ci if self.genOpts is None: 501e5c31af7Sopenharmony_ci raise MissingGeneratorOptionsError() 502e5c31af7Sopenharmony_ci 503e5c31af7Sopenharmony_ci prefix = '' 504e5c31af7Sopenharmony_ci decls = self.makeCDecls(cmdinfo.elem) 505e5c31af7Sopenharmony_ci self.appendSection('command', prefix + decls[0] + '\n') 506e5c31af7Sopenharmony_ci if self.genOpts.genFuncPointers: 507e5c31af7Sopenharmony_ci self.appendSection('commandPointer', decls[1]) 508e5c31af7Sopenharmony_ci 509e5c31af7Sopenharmony_ci def misracstyle(self): 510e5c31af7Sopenharmony_ci return self.genOpts.misracstyle; 511e5c31af7Sopenharmony_ci 512e5c31af7Sopenharmony_ci def misracppstyle(self): 513e5c31af7Sopenharmony_ci return self.genOpts.misracppstyle; 514