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