diff options
Diffstat (limited to 'registry/cgenerator.py')
-rw-r--r-- | registry/cgenerator.py | 121 |
1 files changed, 101 insertions, 20 deletions
diff --git a/registry/cgenerator.py b/registry/cgenerator.py index 2efa081..65302bc 100644 --- a/registry/cgenerator.py +++ b/registry/cgenerator.py @@ -6,9 +6,11 @@ import os import re -from generator import (GeneratorOptions, OutputGenerator, noneStr, - regSortFeatures, write) +from generator import (GeneratorOptions, + MissingGeneratorOptionsConventionsError, + MissingGeneratorOptionsError, MissingRegistryError, + OutputGenerator, noneStr, regSortFeatures, write) class CGeneratorOptions(GeneratorOptions): """CGeneratorOptions - subclass of GeneratorOptions. @@ -17,12 +19,14 @@ class CGeneratorOptions(GeneratorOptions): generation.""" def __init__(self, - prefixText="", + prefixText='', genFuncPointers=True, protectFile=True, protectFeature=True, protectProto=None, protectProtoStr=None, + protectExtensionProto=None, + protectExtensionProtoStr=None, apicall='', apientry='', apientryp='', @@ -31,6 +35,7 @@ class CGeneratorOptions(GeneratorOptions): alignFuncParam=0, genEnumBeginEndRange=False, genAliasMacro=False, + genStructExtendsComment=False, aliasMacro='', misracstyle=False, misracppstyle=False, @@ -40,11 +45,11 @@ class CGeneratorOptions(GeneratorOptions): Additional parameters beyond parent class: - prefixText - list of strings to prefix generated header with - (usually a copyright statement + calling convention macros). + (usually a copyright statement + calling convention macros) - protectFile - True if multiple inclusion protection should be - generated (based on the filename) around the entire header. + generated (based on the filename) around the entire header - protectFeature - True if #ifndef..#endif protection should be - generated around a feature interface in the header file. + generated around a feature interface in the header file - genFuncPointers - True if function pointer typedefs should be generated - protectProto - If conditional protection should be generated @@ -54,12 +59,19 @@ class CGeneratorOptions(GeneratorOptions): set to None. - protectProtoStr - #ifdef/#ifndef symbol to use around prototype declarations, if protectProto is set + - protectExtensionProto - 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 + - protectExtensionProtoStr - #ifdef/#ifndef symbol to use around + extension prototype declarations, if protectExtensionProto is set - apicall - string to use for the function declaration prefix, - such as APICALL on Windows. + such as APICALL on Windows - apientry - string to use for the calling convention macro, - in typedefs, such as APIENTRY. + in typedefs, such as APIENTRY - apientryp - string to use for the calling convention macro - in function pointer typedefs, such as APIENTRYP. + in function pointer typedefs, such as APIENTRYP - indentFuncProto - True if prototype declarations should put each parameter on a separate line - indentFuncPointer - True if typedefed function pointers should put each @@ -70,6 +82,9 @@ class CGeneratorOptions(GeneratorOptions): be generated for enumerated types - genAliasMacro - True if the OpenXR alias macro should be generated for aliased types (unclear what other circumstances this is useful) + - genStructExtendsComment - True if comments showing the structures + whose pNext chain a structure extends are included before its + definition - aliasMacro - alias macro to inject when genAliasMacro is True - misracstyle - generate MISRA C-friendly headers - misracppstyle - generate MISRA C++-friendly headers""" @@ -94,6 +109,12 @@ class CGeneratorOptions(GeneratorOptions): self.protectProtoStr = protectProtoStr """#ifdef/#ifndef symbol to use around prototype declarations, if protectProto is set""" + self.protectExtensionProto = protectExtensionProto + """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.""" + + self.protectExtensionProtoStr = protectExtensionProtoStr + """#ifdef/#ifndef symbol to use around extension prototype declarations, if protectExtensionProto is set""" + self.apicall = apicall """string to use for the function declaration prefix, such as APICALL on Windows.""" @@ -118,6 +139,9 @@ class CGeneratorOptions(GeneratorOptions): self.genAliasMacro = genAliasMacro """True if the OpenXR alias macro should be generated for aliased types (unclear what other circumstances this is useful)""" + self.genStructExtendsComment = genStructExtendsComment + """True if comments showing the structures whose pNext chain a structure extends are included before its definition""" + self.aliasMacro = aliasMacro """alias macro to inject when genAliasMacro is True""" @@ -148,10 +172,12 @@ class COutputGenerator(OutputGenerator): def beginFile(self, genOpts): OutputGenerator.beginFile(self, genOpts) + if self.genOpts is None: + raise MissingGeneratorOptionsError() # C-specific # # Multiple inclusion protection & C++ wrappers. - if genOpts.protectFile and self.genOpts.filename: + if self.genOpts.protectFile and self.genOpts.filename: headerSym = re.sub(r'\.h', '_h_', os.path.basename(self.genOpts.filename)).upper() write('#ifndef', headerSym, file=self.outFile) @@ -173,6 +199,8 @@ class COutputGenerator(OutputGenerator): def endFile(self): # C-specific # Finish C++ wrapper and multiple inclusion protection + if self.genOpts is None: + raise MissingGeneratorOptionsError() self.newline() write('#ifdef __cplusplus', file=self.outFile) write('}', file=self.outFile) @@ -193,42 +221,76 @@ class COutputGenerator(OutputGenerator): self.sections = {section: [] for section in self.ALL_SECTIONS} self.feature_not_empty = False + def _endProtectComment(self, protect_str, protect_directive='#ifdef'): + if protect_directive is None or protect_str is None: + raise RuntimeError('Should not call in here without something to protect') + + # Do not put comments after #endif closing blocks if this is not set + if not self.genOpts.conventions.protectProtoComment: + return '#endif' + elif 'ifdef' in protect_directive: + return '#endif /* ' + protect_str + ' */' + else: + return '#endif /* !' + protect_str + ' */' + def endFeature(self): "Actually write the interface to the output file." # C-specific if self.emit: if self.feature_not_empty: + if self.genOpts is None: + raise MissingGeneratorOptionsError() + if self.genOpts.conventions is None: + raise MissingGeneratorOptionsConventionsError() + is_core = self.featureName and self.featureName.startswith(self.conventions.api_prefix + 'VERSION_') if self.genOpts.conventions.writeFeature(self.featureExtraProtect, self.genOpts.filename): self.newline() if self.genOpts.protectFeature: write('#ifndef', self.featureName, file=self.outFile) + # If type declarations are needed by other features based on # this one, it may be necessary to suppress the ExtraProtect, # or move it below the 'for section...' loop. if self.featureExtraProtect is not None: write('#ifdef', self.featureExtraProtect, file=self.outFile) self.newline() + write('#define', self.featureName, '1', file=self.outFile) for section in self.TYPE_SECTIONS: contents = self.sections[section] if contents: write('\n'.join(contents), file=self.outFile) + if self.genOpts.genFuncPointers and self.sections['commandPointer']: write('\n'.join(self.sections['commandPointer']), file=self.outFile) self.newline() + if self.sections['command']: if self.genOpts.protectProto: write(self.genOpts.protectProto, self.genOpts.protectProtoStr, file=self.outFile) + if self.genOpts.protectExtensionProto and not is_core: + write(self.genOpts.protectExtensionProto, + self.genOpts.protectExtensionProtoStr, file=self.outFile) write('\n'.join(self.sections['command']), end='', file=self.outFile) + if self.genOpts.protectExtensionProto and not is_core: + write(self._endProtectComment(protect_directive=self.genOpts.protectExtensionProto, + protect_str=self.genOpts.protectExtensionProtoStr), + file=self.outFile) if self.genOpts.protectProto: - write('#endif', file=self.outFile) + write(self._endProtectComment(protect_directive=self.genOpts.protectProto, + protect_str=self.genOpts.protectProtoStr), + file=self.outFile) else: self.newline() + if self.featureExtraProtect is not None: - write('#endif /*', self.featureExtraProtect, '*/', file=self.outFile) + write(self._endProtectComment(protect_str=self.featureExtraProtect), + file=self.outFile) + if self.genOpts.protectFeature: - write('#endif /*', self.featureName, '*/', file=self.outFile) + write(self._endProtectComment(protect_str=self.featureName), + file=self.outFile) # Finish processing in superclass OutputGenerator.endFeature(self) @@ -264,6 +326,8 @@ class COutputGenerator(OutputGenerator): # special-purpose generator. self.genStruct(typeinfo, name, alias) else: + if self.genOpts is None: + raise MissingGeneratorOptionsError() # OpenXR: this section was not under 'else:' previously, just fell through if alias: # If the type is an alias, just emit a typedef declaration @@ -288,7 +352,7 @@ class COutputGenerator(OutputGenerator): """Generate protection string. Protection strings are the strings defining the OS/Platform/Graphics - requirements for a given OpenXR command. When generating the + requirements for a given API command. When generating the language header files, we need to make sure the items specific to a graphics API or OS platform are properly wrapped in #ifs.""" protect_if_str = '' @@ -297,7 +361,7 @@ class COutputGenerator(OutputGenerator): return (protect_if_str, protect_end_str) if ',' in protect_str: - protect_list = protect_str.split(",") + protect_list = protect_str.split(',') protect_defs = ('defined(%s)' % d for d in protect_list) protect_def_str = ' && '.join(protect_defs) protect_if_str = '#if %s\n' % protect_def_str @@ -310,6 +374,8 @@ class COutputGenerator(OutputGenerator): def typeMayAlias(self, typeName): if not self.may_alias: + if self.registry is None: + raise MissingRegistryError() # First time we have asked if a type may alias. # So, populate the set of all names of types that may. @@ -319,9 +385,9 @@ class COutputGenerator(OutputGenerator): if data.elem.get('mayalias') == 'true') # Every type mentioned in some other type's parentstruct attribute. - parent_structs = (otherType.elem.get('parentstruct') - for otherType in self.registry.typedict.values()) - self.may_alias.update(set(x for x in parent_structs + polymorphic_bases = (otherType.elem.get('parentstruct') + for otherType in self.registry.typedict.values()) + self.may_alias.update(set(x for x in polymorphic_bases if x is not None)) return typeName in self.may_alias @@ -339,6 +405,9 @@ class COutputGenerator(OutputGenerator): generate a typedef of that alias.""" OutputGenerator.genStruct(self, typeinfo, typeName, alias) + if self.genOpts is None: + raise MissingGeneratorOptionsError() + typeElem = typeinfo.elem if alias: @@ -348,6 +417,11 @@ class COutputGenerator(OutputGenerator): (protect_begin, protect_end) = self.genProtectString(typeElem.get('protect')) if protect_begin: body += protect_begin + + if self.genOpts.genStructExtendsComment: + structextends = typeElem.get('structextends') + body += '// ' + typeName + ' extends ' + structextends + '\n' if structextends else '' + body += 'typedef ' + typeElem.get('category') # This is an OpenXR-specific alternative where aliasing refers @@ -391,11 +465,16 @@ class COutputGenerator(OutputGenerator): body = 'typedef ' + alias + ' ' + groupName + ';\n' self.appendSection(section, body) else: + if self.genOpts is None: + raise MissingGeneratorOptionsError() (section, body) = self.buildEnumCDecl(self.genOpts.genEnumBeginEndRange, groupinfo, groupName) - self.appendSection(section, "\n" + body) + self.appendSection(section, '\n' + body) def genEnum(self, enuminfo, name, alias): - """Generate the C declaration for a constant (a single <enum> value).""" + """Generate the C declaration for a constant (a single <enum> value). + + <enum> tags may specify their values in several ways, but are usually + just integers.""" OutputGenerator.genEnum(self, enuminfo, name, alias) @@ -410,6 +489,8 @@ class COutputGenerator(OutputGenerator): # prefix = '// ' + name + ' is an alias of command ' + alias + '\n' # else: # prefix = '' + if self.genOpts is None: + raise MissingGeneratorOptionsError() prefix = '' decls = self.makeCDecls(cmdinfo.elem) |