aboutsummaryrefslogtreecommitdiffhomepage
path: root/registry/cgenerator.py
diff options
context:
space:
mode:
Diffstat (limited to 'registry/cgenerator.py')
-rw-r--r--registry/cgenerator.py121
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)