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