1e8556ba3Sopenharmony_ci#!/usr/bin/python3 -i
2e8556ba3Sopenharmony_ci#
3e8556ba3Sopenharmony_ci# Copyright 2013-2024 The Khronos Group Inc.
4e8556ba3Sopenharmony_ci#
5e8556ba3Sopenharmony_ci# SPDX-License-Identifier: Apache-2.0
6e8556ba3Sopenharmony_ci
7e8556ba3Sopenharmony_ci# Base class for working-group-specific style conventions,
8e8556ba3Sopenharmony_ci# used in generation.
9e8556ba3Sopenharmony_ci
10e8556ba3Sopenharmony_cifrom enum import Enum
11e8556ba3Sopenharmony_ciimport abc
12e8556ba3Sopenharmony_ciimport re
13e8556ba3Sopenharmony_ci
14e8556ba3Sopenharmony_ci# Type categories that respond "False" to isStructAlwaysValid
15e8556ba3Sopenharmony_ci# basetype is home to typedefs like ..Bool32
16e8556ba3Sopenharmony_ciCATEGORIES_REQUIRING_VALIDATION = set(('handle',
17e8556ba3Sopenharmony_ci                                       'enum',
18e8556ba3Sopenharmony_ci                                       'bitmask',
19e8556ba3Sopenharmony_ci                                       'basetype',
20e8556ba3Sopenharmony_ci                                       None))
21e8556ba3Sopenharmony_ci
22e8556ba3Sopenharmony_ci# These are basic C types pulled in via openxr_platform_defines.h
23e8556ba3Sopenharmony_ciTYPES_KNOWN_ALWAYS_VALID = set(('char',
24e8556ba3Sopenharmony_ci                                'float',
25e8556ba3Sopenharmony_ci                                'int8_t', 'uint8_t',
26e8556ba3Sopenharmony_ci                                'int16_t', 'uint16_t',
27e8556ba3Sopenharmony_ci                                'int32_t', 'uint32_t',
28e8556ba3Sopenharmony_ci                                'int64_t', 'uint64_t',
29e8556ba3Sopenharmony_ci                                'size_t',
30e8556ba3Sopenharmony_ci                                'intptr_t', 'uintptr_t',
31e8556ba3Sopenharmony_ci                                'int',
32e8556ba3Sopenharmony_ci                                ))
33e8556ba3Sopenharmony_ci
34e8556ba3Sopenharmony_ci# Split an extension name into vendor ID and name portions
35e8556ba3Sopenharmony_ciEXT_NAME_DECOMPOSE_RE = re.compile(r'(?P<prefix>[A-Za-z]+)_(?P<vendor>[A-Za-z]+)_(?P<name>[\w_]+)')
36e8556ba3Sopenharmony_ci
37e8556ba3Sopenharmony_ci# Match an API version name.
38e8556ba3Sopenharmony_ci# Match object includes API prefix, major, and minor version numbers.
39e8556ba3Sopenharmony_ci# This could be refined further for specific APIs.
40e8556ba3Sopenharmony_ciAPI_VERSION_NAME_RE = re.compile(r'(?P<apivariant>[A-Za-z]+)_VERSION_(?P<major>[0-9]+)_(?P<minor>[0-9]+)')
41e8556ba3Sopenharmony_ci
42e8556ba3Sopenharmony_ciclass ProseListFormats(Enum):
43e8556ba3Sopenharmony_ci    """A connective, possibly with a quantifier."""
44e8556ba3Sopenharmony_ci    AND = 0
45e8556ba3Sopenharmony_ci    EACH_AND = 1
46e8556ba3Sopenharmony_ci    OR = 2
47e8556ba3Sopenharmony_ci    ANY_OR = 3
48e8556ba3Sopenharmony_ci
49e8556ba3Sopenharmony_ci    @classmethod
50e8556ba3Sopenharmony_ci    def from_string(cls, s):
51e8556ba3Sopenharmony_ci        if s == 'or':
52e8556ba3Sopenharmony_ci            return cls.OR
53e8556ba3Sopenharmony_ci        if s == 'and':
54e8556ba3Sopenharmony_ci            return cls.AND
55e8556ba3Sopenharmony_ci        raise RuntimeError("Unrecognized string connective: " + s)
56e8556ba3Sopenharmony_ci
57e8556ba3Sopenharmony_ci    @property
58e8556ba3Sopenharmony_ci    def connective(self):
59e8556ba3Sopenharmony_ci        if self in (ProseListFormats.OR, ProseListFormats.ANY_OR):
60e8556ba3Sopenharmony_ci            return 'or'
61e8556ba3Sopenharmony_ci        return 'and'
62e8556ba3Sopenharmony_ci
63e8556ba3Sopenharmony_ci    def quantifier(self, n):
64e8556ba3Sopenharmony_ci        """Return the desired quantifier for a list of a given length."""
65e8556ba3Sopenharmony_ci        if self == ProseListFormats.ANY_OR:
66e8556ba3Sopenharmony_ci            if n > 1:
67e8556ba3Sopenharmony_ci                return 'any of '
68e8556ba3Sopenharmony_ci        elif self == ProseListFormats.EACH_AND:
69e8556ba3Sopenharmony_ci            if n > 2:
70e8556ba3Sopenharmony_ci                return 'each of '
71e8556ba3Sopenharmony_ci            if n == 2:
72e8556ba3Sopenharmony_ci                return 'both of '
73e8556ba3Sopenharmony_ci        return ''
74e8556ba3Sopenharmony_ci
75e8556ba3Sopenharmony_ci
76e8556ba3Sopenharmony_ciclass ConventionsBase(abc.ABC):
77e8556ba3Sopenharmony_ci    """WG-specific conventions."""
78e8556ba3Sopenharmony_ci
79e8556ba3Sopenharmony_ci    def __init__(self):
80e8556ba3Sopenharmony_ci        self._command_prefix = None
81e8556ba3Sopenharmony_ci        self._type_prefix = None
82e8556ba3Sopenharmony_ci
83e8556ba3Sopenharmony_ci    def formatVersionOrExtension(self, name):
84e8556ba3Sopenharmony_ci        """Mark up an API version or extension name as a link in the spec."""
85e8556ba3Sopenharmony_ci
86e8556ba3Sopenharmony_ci        # Is this a version name?
87e8556ba3Sopenharmony_ci        match = API_VERSION_NAME_RE.match(name)
88e8556ba3Sopenharmony_ci        if match is not None:
89e8556ba3Sopenharmony_ci            return self.formatVersion(name,
90e8556ba3Sopenharmony_ci                match.group('apivariant'),
91e8556ba3Sopenharmony_ci                match.group('major'),
92e8556ba3Sopenharmony_ci                match.group('minor'))
93e8556ba3Sopenharmony_ci        else:
94e8556ba3Sopenharmony_ci            # If not, assumed to be an extension name. Might be worth checking.
95e8556ba3Sopenharmony_ci            return self.formatExtension(name)
96e8556ba3Sopenharmony_ci
97e8556ba3Sopenharmony_ci    def formatVersion(self, name, apivariant, major, minor):
98e8556ba3Sopenharmony_ci        """Mark up an API version name as a link in the spec."""
99e8556ba3Sopenharmony_ci        return '`<<{}>>`'.format(name)
100e8556ba3Sopenharmony_ci
101e8556ba3Sopenharmony_ci    def formatExtension(self, name):
102e8556ba3Sopenharmony_ci        """Mark up an extension name as a link in the spec."""
103e8556ba3Sopenharmony_ci        return '`<<{}>>`'.format(name)
104e8556ba3Sopenharmony_ci
105e8556ba3Sopenharmony_ci    def formatSPIRVlink(self, name):
106e8556ba3Sopenharmony_ci        """Mark up a SPIR-V extension name as an external link in the spec.
107e8556ba3Sopenharmony_ci           Since these are external links, the formatting probably will be
108e8556ba3Sopenharmony_ci           the same for all APIs creating such links, so long as they use
109e8556ba3Sopenharmony_ci           the asciidoctor {spirv} attribute for the base path to the SPIR-V
110e8556ba3Sopenharmony_ci           extensions."""
111e8556ba3Sopenharmony_ci
112e8556ba3Sopenharmony_ci        (vendor, _) = self.extension_name_split(name)
113e8556ba3Sopenharmony_ci
114e8556ba3Sopenharmony_ci        return f'{{spirv}}/{vendor}/{name}.html[{name}]'
115e8556ba3Sopenharmony_ci
116e8556ba3Sopenharmony_ci    @property
117e8556ba3Sopenharmony_ci    @abc.abstractmethod
118e8556ba3Sopenharmony_ci    def null(self):
119e8556ba3Sopenharmony_ci        """Preferred spelling of NULL."""
120e8556ba3Sopenharmony_ci        raise NotImplementedError
121e8556ba3Sopenharmony_ci
122e8556ba3Sopenharmony_ci    def makeProseList(self, elements, fmt=ProseListFormats.AND, with_verb=False, *args, **kwargs):
123e8556ba3Sopenharmony_ci        """Make a (comma-separated) list for use in prose.
124e8556ba3Sopenharmony_ci
125e8556ba3Sopenharmony_ci        Adds a connective (by default, 'and')
126e8556ba3Sopenharmony_ci        before the last element if there are more than 1.
127e8556ba3Sopenharmony_ci
128e8556ba3Sopenharmony_ci        Adds the right one of "is" or "are" to the end if with_verb is true.
129e8556ba3Sopenharmony_ci
130e8556ba3Sopenharmony_ci        Optionally adds a quantifier (like 'any') before a list of 2 or more,
131e8556ba3Sopenharmony_ci        if specified by fmt.
132e8556ba3Sopenharmony_ci
133e8556ba3Sopenharmony_ci        Override with a different method or different call to
134e8556ba3Sopenharmony_ci        _implMakeProseList if you want to add a comma for two elements,
135e8556ba3Sopenharmony_ci        or not use a serial comma.
136e8556ba3Sopenharmony_ci        """
137e8556ba3Sopenharmony_ci        return self._implMakeProseList(elements, fmt, with_verb, *args, **kwargs)
138e8556ba3Sopenharmony_ci
139e8556ba3Sopenharmony_ci    @property
140e8556ba3Sopenharmony_ci    def struct_macro(self):
141e8556ba3Sopenharmony_ci        """Get the appropriate format macro for a structure.
142e8556ba3Sopenharmony_ci
143e8556ba3Sopenharmony_ci        May override.
144e8556ba3Sopenharmony_ci        """
145e8556ba3Sopenharmony_ci        return 'slink:'
146e8556ba3Sopenharmony_ci
147e8556ba3Sopenharmony_ci    @property
148e8556ba3Sopenharmony_ci    def external_macro(self):
149e8556ba3Sopenharmony_ci        """Get the appropriate format macro for an external type like uint32_t.
150e8556ba3Sopenharmony_ci
151e8556ba3Sopenharmony_ci        May override.
152e8556ba3Sopenharmony_ci        """
153e8556ba3Sopenharmony_ci        return 'code:'
154e8556ba3Sopenharmony_ci
155e8556ba3Sopenharmony_ci    @property
156e8556ba3Sopenharmony_ci    @abc.abstractmethod
157e8556ba3Sopenharmony_ci    def structtype_member_name(self):
158e8556ba3Sopenharmony_ci        """Return name of the structure type member.
159e8556ba3Sopenharmony_ci
160e8556ba3Sopenharmony_ci        Must implement.
161e8556ba3Sopenharmony_ci        """
162e8556ba3Sopenharmony_ci        raise NotImplementedError()
163e8556ba3Sopenharmony_ci
164e8556ba3Sopenharmony_ci    @property
165e8556ba3Sopenharmony_ci    @abc.abstractmethod
166e8556ba3Sopenharmony_ci    def nextpointer_member_name(self):
167e8556ba3Sopenharmony_ci        """Return name of the structure pointer chain member.
168e8556ba3Sopenharmony_ci
169e8556ba3Sopenharmony_ci        Must implement.
170e8556ba3Sopenharmony_ci        """
171e8556ba3Sopenharmony_ci        raise NotImplementedError()
172e8556ba3Sopenharmony_ci
173e8556ba3Sopenharmony_ci    @property
174e8556ba3Sopenharmony_ci    @abc.abstractmethod
175e8556ba3Sopenharmony_ci    def xml_api_name(self):
176e8556ba3Sopenharmony_ci        """Return the name used in the default API XML registry for the default API"""
177e8556ba3Sopenharmony_ci        raise NotImplementedError()
178e8556ba3Sopenharmony_ci
179e8556ba3Sopenharmony_ci    @abc.abstractmethod
180e8556ba3Sopenharmony_ci    def generate_structure_type_from_name(self, structname):
181e8556ba3Sopenharmony_ci        """Generate a structure type name, like XR_TYPE_CREATE_INSTANCE_INFO.
182e8556ba3Sopenharmony_ci
183e8556ba3Sopenharmony_ci        Must implement.
184e8556ba3Sopenharmony_ci        """
185e8556ba3Sopenharmony_ci        raise NotImplementedError()
186e8556ba3Sopenharmony_ci
187e8556ba3Sopenharmony_ci    def makeStructName(self, name):
188e8556ba3Sopenharmony_ci        """Prepend the appropriate format macro for a structure to a structure type name.
189e8556ba3Sopenharmony_ci
190e8556ba3Sopenharmony_ci        Uses struct_macro, so just override that if you want to change behavior.
191e8556ba3Sopenharmony_ci        """
192e8556ba3Sopenharmony_ci        return self.struct_macro + name
193e8556ba3Sopenharmony_ci
194e8556ba3Sopenharmony_ci    def makeExternalTypeName(self, name):
195e8556ba3Sopenharmony_ci        """Prepend the appropriate format macro for an external type like uint32_t to a type name.
196e8556ba3Sopenharmony_ci
197e8556ba3Sopenharmony_ci        Uses external_macro, so just override that if you want to change behavior.
198e8556ba3Sopenharmony_ci        """
199e8556ba3Sopenharmony_ci        return self.external_macro + name
200e8556ba3Sopenharmony_ci
201e8556ba3Sopenharmony_ci    def _implMakeProseList(self, elements, fmt, with_verb, comma_for_two_elts=False, serial_comma=True):
202e8556ba3Sopenharmony_ci        """Internal-use implementation to make a (comma-separated) list for use in prose.
203e8556ba3Sopenharmony_ci
204e8556ba3Sopenharmony_ci        Adds a connective (by default, 'and')
205e8556ba3Sopenharmony_ci        before the last element if there are more than 1,
206e8556ba3Sopenharmony_ci        and only includes commas if there are more than 2
207e8556ba3Sopenharmony_ci        (if comma_for_two_elts is False).
208e8556ba3Sopenharmony_ci
209e8556ba3Sopenharmony_ci        Adds the right one of "is" or "are" to the end if with_verb is true.
210e8556ba3Sopenharmony_ci
211e8556ba3Sopenharmony_ci        Optionally adds a quantifier (like 'any') before a list of 2 or more,
212e8556ba3Sopenharmony_ci        if specified by fmt.
213e8556ba3Sopenharmony_ci
214e8556ba3Sopenharmony_ci        Do not edit these defaults, override self.makeProseList().
215e8556ba3Sopenharmony_ci        """
216e8556ba3Sopenharmony_ci        assert(serial_comma)  # did not implement what we did not need
217e8556ba3Sopenharmony_ci        if isinstance(fmt, str):
218e8556ba3Sopenharmony_ci            fmt = ProseListFormats.from_string(fmt)
219e8556ba3Sopenharmony_ci
220e8556ba3Sopenharmony_ci        my_elts = list(elements)
221e8556ba3Sopenharmony_ci        if len(my_elts) > 1:
222e8556ba3Sopenharmony_ci            my_elts[-1] = '{} {}'.format(fmt.connective, my_elts[-1])
223e8556ba3Sopenharmony_ci
224e8556ba3Sopenharmony_ci        if not comma_for_two_elts and len(my_elts) <= 2:
225e8556ba3Sopenharmony_ci            prose = ' '.join(my_elts)
226e8556ba3Sopenharmony_ci        else:
227e8556ba3Sopenharmony_ci            prose = ', '.join(my_elts)
228e8556ba3Sopenharmony_ci
229e8556ba3Sopenharmony_ci        quantifier = fmt.quantifier(len(my_elts))
230e8556ba3Sopenharmony_ci
231e8556ba3Sopenharmony_ci        parts = [quantifier, prose]
232e8556ba3Sopenharmony_ci
233e8556ba3Sopenharmony_ci        if with_verb:
234e8556ba3Sopenharmony_ci            if len(my_elts) > 1:
235e8556ba3Sopenharmony_ci                parts.append(' are')
236e8556ba3Sopenharmony_ci            else:
237e8556ba3Sopenharmony_ci                parts.append(' is')
238e8556ba3Sopenharmony_ci        return ''.join(parts)
239e8556ba3Sopenharmony_ci
240e8556ba3Sopenharmony_ci    @property
241e8556ba3Sopenharmony_ci    @abc.abstractmethod
242e8556ba3Sopenharmony_ci    def file_suffix(self):
243e8556ba3Sopenharmony_ci        """Return suffix of generated Asciidoctor files"""
244e8556ba3Sopenharmony_ci        raise NotImplementedError
245e8556ba3Sopenharmony_ci
246e8556ba3Sopenharmony_ci    @abc.abstractmethod
247e8556ba3Sopenharmony_ci    def api_name(self, spectype=None):
248e8556ba3Sopenharmony_ci        """Return API or specification name for citations in ref pages.
249e8556ba3Sopenharmony_ci
250e8556ba3Sopenharmony_ci        spectype is the spec this refpage is for.
251e8556ba3Sopenharmony_ci        'api' (the default value) is the main API Specification.
252e8556ba3Sopenharmony_ci        If an unrecognized spectype is given, returns None.
253e8556ba3Sopenharmony_ci
254e8556ba3Sopenharmony_ci        Must implement."""
255e8556ba3Sopenharmony_ci        raise NotImplementedError
256e8556ba3Sopenharmony_ci
257e8556ba3Sopenharmony_ci    def should_insert_may_alias_macro(self, genOpts):
258e8556ba3Sopenharmony_ci        """Return true if we should insert a "may alias" macro in this file.
259e8556ba3Sopenharmony_ci
260e8556ba3Sopenharmony_ci        Only used by OpenXR right now."""
261e8556ba3Sopenharmony_ci        return False
262e8556ba3Sopenharmony_ci
263e8556ba3Sopenharmony_ci    @property
264e8556ba3Sopenharmony_ci    def command_prefix(self):
265e8556ba3Sopenharmony_ci        """Return the expected prefix of commands/functions.
266e8556ba3Sopenharmony_ci
267e8556ba3Sopenharmony_ci        Implemented in terms of api_prefix."""
268e8556ba3Sopenharmony_ci        if not self._command_prefix:
269e8556ba3Sopenharmony_ci            self._command_prefix = self.api_prefix[:].replace('_', '').lower()
270e8556ba3Sopenharmony_ci        return self._command_prefix
271e8556ba3Sopenharmony_ci
272e8556ba3Sopenharmony_ci    @property
273e8556ba3Sopenharmony_ci    def type_prefix(self):
274e8556ba3Sopenharmony_ci        """Return the expected prefix of type names.
275e8556ba3Sopenharmony_ci
276e8556ba3Sopenharmony_ci        Implemented in terms of command_prefix (and in turn, api_prefix)."""
277e8556ba3Sopenharmony_ci        if not self._type_prefix:
278e8556ba3Sopenharmony_ci            self._type_prefix = ''.join(
279e8556ba3Sopenharmony_ci                (self.command_prefix[0:1].upper(), self.command_prefix[1:]))
280e8556ba3Sopenharmony_ci        return self._type_prefix
281e8556ba3Sopenharmony_ci
282e8556ba3Sopenharmony_ci    @property
283e8556ba3Sopenharmony_ci    @abc.abstractmethod
284e8556ba3Sopenharmony_ci    def api_prefix(self):
285e8556ba3Sopenharmony_ci        """Return API token prefix.
286e8556ba3Sopenharmony_ci
287e8556ba3Sopenharmony_ci        Typically two uppercase letters followed by an underscore.
288e8556ba3Sopenharmony_ci
289e8556ba3Sopenharmony_ci        Must implement."""
290e8556ba3Sopenharmony_ci        raise NotImplementedError
291e8556ba3Sopenharmony_ci
292e8556ba3Sopenharmony_ci    @property
293e8556ba3Sopenharmony_ci    def extension_name_prefix(self):
294e8556ba3Sopenharmony_ci        """Return extension name prefix.
295e8556ba3Sopenharmony_ci
296e8556ba3Sopenharmony_ci        Typically two uppercase letters followed by an underscore.
297e8556ba3Sopenharmony_ci
298e8556ba3Sopenharmony_ci        Assumed to be the same as api_prefix, but some APIs use different
299e8556ba3Sopenharmony_ci        case conventions."""
300e8556ba3Sopenharmony_ci
301e8556ba3Sopenharmony_ci        return self.api_prefix
302e8556ba3Sopenharmony_ci
303e8556ba3Sopenharmony_ci    @property
304e8556ba3Sopenharmony_ci    def write_contacts(self):
305e8556ba3Sopenharmony_ci        """Return whether contact list should be written to extension appendices"""
306e8556ba3Sopenharmony_ci        return False
307e8556ba3Sopenharmony_ci
308e8556ba3Sopenharmony_ci    @property
309e8556ba3Sopenharmony_ci    def write_extension_type(self):
310e8556ba3Sopenharmony_ci        """Return whether extension type should be written to extension appendices"""
311e8556ba3Sopenharmony_ci        return True
312e8556ba3Sopenharmony_ci
313e8556ba3Sopenharmony_ci    @property
314e8556ba3Sopenharmony_ci    def write_extension_number(self):
315e8556ba3Sopenharmony_ci        """Return whether extension number should be written to extension appendices"""
316e8556ba3Sopenharmony_ci        return True
317e8556ba3Sopenharmony_ci
318e8556ba3Sopenharmony_ci    @property
319e8556ba3Sopenharmony_ci    def write_extension_revision(self):
320e8556ba3Sopenharmony_ci        """Return whether extension revision number should be written to extension appendices"""
321e8556ba3Sopenharmony_ci        return True
322e8556ba3Sopenharmony_ci
323e8556ba3Sopenharmony_ci    @property
324e8556ba3Sopenharmony_ci    def write_refpage_include(self):
325e8556ba3Sopenharmony_ci        """Return whether refpage include should be written to extension appendices"""
326e8556ba3Sopenharmony_ci        return True
327e8556ba3Sopenharmony_ci
328e8556ba3Sopenharmony_ci    @property
329e8556ba3Sopenharmony_ci    def api_version_prefix(self):
330e8556ba3Sopenharmony_ci        """Return API core version token prefix.
331e8556ba3Sopenharmony_ci
332e8556ba3Sopenharmony_ci        Implemented in terms of api_prefix.
333e8556ba3Sopenharmony_ci
334e8556ba3Sopenharmony_ci        May override."""
335e8556ba3Sopenharmony_ci        return self.api_prefix + 'VERSION_'
336e8556ba3Sopenharmony_ci
337e8556ba3Sopenharmony_ci    @property
338e8556ba3Sopenharmony_ci    def KHR_prefix(self):
339e8556ba3Sopenharmony_ci        """Return extension name prefix for KHR extensions.
340e8556ba3Sopenharmony_ci
341e8556ba3Sopenharmony_ci        Implemented in terms of api_prefix.
342e8556ba3Sopenharmony_ci
343e8556ba3Sopenharmony_ci        May override."""
344e8556ba3Sopenharmony_ci        return self.api_prefix + 'KHR_'
345e8556ba3Sopenharmony_ci
346e8556ba3Sopenharmony_ci    @property
347e8556ba3Sopenharmony_ci    def EXT_prefix(self):
348e8556ba3Sopenharmony_ci        """Return extension name prefix for EXT extensions.
349e8556ba3Sopenharmony_ci
350e8556ba3Sopenharmony_ci        Implemented in terms of api_prefix.
351e8556ba3Sopenharmony_ci
352e8556ba3Sopenharmony_ci        May override."""
353e8556ba3Sopenharmony_ci        return self.api_prefix + 'EXT_'
354e8556ba3Sopenharmony_ci
355e8556ba3Sopenharmony_ci    def writeFeature(self, featureExtraProtect, filename):
356e8556ba3Sopenharmony_ci        """Return True if OutputGenerator.endFeature should write this feature.
357e8556ba3Sopenharmony_ci
358e8556ba3Sopenharmony_ci        Defaults to always True.
359e8556ba3Sopenharmony_ci        Used in COutputGenerator.
360e8556ba3Sopenharmony_ci
361e8556ba3Sopenharmony_ci        May override."""
362e8556ba3Sopenharmony_ci        return True
363e8556ba3Sopenharmony_ci
364e8556ba3Sopenharmony_ci    def requires_error_validation(self, return_type):
365e8556ba3Sopenharmony_ci        """Return True if the return_type element is an API result code
366e8556ba3Sopenharmony_ci        requiring error validation.
367e8556ba3Sopenharmony_ci
368e8556ba3Sopenharmony_ci        Defaults to always False.
369e8556ba3Sopenharmony_ci
370e8556ba3Sopenharmony_ci        May override."""
371e8556ba3Sopenharmony_ci        return False
372e8556ba3Sopenharmony_ci
373e8556ba3Sopenharmony_ci    @property
374e8556ba3Sopenharmony_ci    def required_errors(self):
375e8556ba3Sopenharmony_ci        """Return a list of required error codes for validation.
376e8556ba3Sopenharmony_ci
377e8556ba3Sopenharmony_ci        Defaults to an empty list.
378e8556ba3Sopenharmony_ci
379e8556ba3Sopenharmony_ci        May override."""
380e8556ba3Sopenharmony_ci        return []
381e8556ba3Sopenharmony_ci
382e8556ba3Sopenharmony_ci    def is_voidpointer_alias(self, tag, text, tail):
383e8556ba3Sopenharmony_ci        """Return True if the declaration components (tag,text,tail) of an
384e8556ba3Sopenharmony_ci        element represents a void * type.
385e8556ba3Sopenharmony_ci
386e8556ba3Sopenharmony_ci        Defaults to a reasonable implementation.
387e8556ba3Sopenharmony_ci
388e8556ba3Sopenharmony_ci        May override."""
389e8556ba3Sopenharmony_ci        return tag == 'type' and text == 'void' and tail.startswith('*')
390e8556ba3Sopenharmony_ci
391e8556ba3Sopenharmony_ci    def make_voidpointer_alias(self, tail):
392e8556ba3Sopenharmony_ci        """Reformat a void * declaration to include the API alias macro.
393e8556ba3Sopenharmony_ci
394e8556ba3Sopenharmony_ci        Defaults to a no-op.
395e8556ba3Sopenharmony_ci
396e8556ba3Sopenharmony_ci        Must override if you actually want to use this feature in your project."""
397e8556ba3Sopenharmony_ci        return tail
398e8556ba3Sopenharmony_ci
399e8556ba3Sopenharmony_ci    def category_requires_validation(self, category):
400e8556ba3Sopenharmony_ci        """Return True if the given type 'category' always requires validation.
401e8556ba3Sopenharmony_ci
402e8556ba3Sopenharmony_ci        Defaults to a reasonable implementation.
403e8556ba3Sopenharmony_ci
404e8556ba3Sopenharmony_ci        May override."""
405e8556ba3Sopenharmony_ci        return category in CATEGORIES_REQUIRING_VALIDATION
406e8556ba3Sopenharmony_ci
407e8556ba3Sopenharmony_ci    def type_always_valid(self, typename):
408e8556ba3Sopenharmony_ci        """Return True if the given type name is always valid (never requires validation).
409e8556ba3Sopenharmony_ci
410e8556ba3Sopenharmony_ci        This is for things like integers.
411e8556ba3Sopenharmony_ci
412e8556ba3Sopenharmony_ci        Defaults to a reasonable implementation.
413e8556ba3Sopenharmony_ci
414e8556ba3Sopenharmony_ci        May override."""
415e8556ba3Sopenharmony_ci        return typename in TYPES_KNOWN_ALWAYS_VALID
416e8556ba3Sopenharmony_ci
417e8556ba3Sopenharmony_ci    @property
418e8556ba3Sopenharmony_ci    def should_skip_checking_codes(self):
419e8556ba3Sopenharmony_ci        """Return True if more than the basic validation of return codes should
420e8556ba3Sopenharmony_ci        be skipped for a command."""
421e8556ba3Sopenharmony_ci
422e8556ba3Sopenharmony_ci        return False
423e8556ba3Sopenharmony_ci
424e8556ba3Sopenharmony_ci    @property
425e8556ba3Sopenharmony_ci    def generate_index_terms(self):
426e8556ba3Sopenharmony_ci        """Return True if asiidoctor index terms should be generated as part
427e8556ba3Sopenharmony_ci           of an API interface from the docgenerator."""
428e8556ba3Sopenharmony_ci
429e8556ba3Sopenharmony_ci        return False
430e8556ba3Sopenharmony_ci
431e8556ba3Sopenharmony_ci    @property
432e8556ba3Sopenharmony_ci    def generate_enum_table(self):
433e8556ba3Sopenharmony_ci        """Return True if asciidoctor tables describing enumerants in a
434e8556ba3Sopenharmony_ci           group should be generated as part of group generation."""
435e8556ba3Sopenharmony_ci        return False
436e8556ba3Sopenharmony_ci
437e8556ba3Sopenharmony_ci    @property
438e8556ba3Sopenharmony_ci    def generate_max_enum_in_docs(self):
439e8556ba3Sopenharmony_ci        """Return True if MAX_ENUM tokens should be generated in
440e8556ba3Sopenharmony_ci           documentation includes."""
441e8556ba3Sopenharmony_ci        return False
442e8556ba3Sopenharmony_ci
443e8556ba3Sopenharmony_ci    def extension_name_split(self, name):
444e8556ba3Sopenharmony_ci        """Split an extension name, returning (vendor, rest of name).
445e8556ba3Sopenharmony_ci           The API prefix of the name is ignored."""
446e8556ba3Sopenharmony_ci
447e8556ba3Sopenharmony_ci        match = EXT_NAME_DECOMPOSE_RE.match(name)
448e8556ba3Sopenharmony_ci        vendor = match.group('vendor')
449e8556ba3Sopenharmony_ci        bare_name = match.group('name')
450e8556ba3Sopenharmony_ci
451e8556ba3Sopenharmony_ci        return (vendor, bare_name)
452e8556ba3Sopenharmony_ci
453e8556ba3Sopenharmony_ci    @abc.abstractmethod
454e8556ba3Sopenharmony_ci    def extension_file_path(self, name):
455e8556ba3Sopenharmony_ci        """Return file path to an extension appendix relative to a directory
456e8556ba3Sopenharmony_ci           containing all such appendices.
457e8556ba3Sopenharmony_ci           - name - extension name
458e8556ba3Sopenharmony_ci
459e8556ba3Sopenharmony_ci           Must implement."""
460e8556ba3Sopenharmony_ci        raise NotImplementedError
461e8556ba3Sopenharmony_ci
462e8556ba3Sopenharmony_ci    def extension_include_string(self, name):
463e8556ba3Sopenharmony_ci        """Return format string for include:: line for an extension appendix
464e8556ba3Sopenharmony_ci           file.
465e8556ba3Sopenharmony_ci            - name - extension name"""
466e8556ba3Sopenharmony_ci
467e8556ba3Sopenharmony_ci        return 'include::{{appendices}}/{}[]'.format(
468e8556ba3Sopenharmony_ci                self.extension_file_path(name))
469e8556ba3Sopenharmony_ci
470e8556ba3Sopenharmony_ci    @property
471e8556ba3Sopenharmony_ci    def provisional_extension_warning(self):
472e8556ba3Sopenharmony_ci        """Return True if a warning should be included in extension
473e8556ba3Sopenharmony_ci           appendices for provisional extensions."""
474e8556ba3Sopenharmony_ci        return True
475e8556ba3Sopenharmony_ci
476e8556ba3Sopenharmony_ci    @property
477e8556ba3Sopenharmony_ci    def generated_include_path(self):
478e8556ba3Sopenharmony_ci        """Return path relative to the generated reference pages, to the
479e8556ba3Sopenharmony_ci           generated API include files."""
480e8556ba3Sopenharmony_ci
481e8556ba3Sopenharmony_ci        return '{generated}'
482e8556ba3Sopenharmony_ci
483e8556ba3Sopenharmony_ci    @property
484e8556ba3Sopenharmony_ci    def include_extension_appendix_in_refpage(self):
485e8556ba3Sopenharmony_ci        """Return True if generating extension refpages by embedding
486e8556ba3Sopenharmony_ci           extension appendix content (default), False otherwise
487e8556ba3Sopenharmony_ci           (OpenXR)."""
488e8556ba3Sopenharmony_ci
489e8556ba3Sopenharmony_ci        return True
490e8556ba3Sopenharmony_ci
491e8556ba3Sopenharmony_ci    def valid_flag_bit(self, bitpos):
492e8556ba3Sopenharmony_ci        """Return True if bitpos is an allowed numeric bit position for
493e8556ba3Sopenharmony_ci           an API flag.
494e8556ba3Sopenharmony_ci
495e8556ba3Sopenharmony_ci           Behavior depends on the data type used for flags (which may be 32
496e8556ba3Sopenharmony_ci           or 64 bits), and may depend on assumptions about compiler
497e8556ba3Sopenharmony_ci           handling of sign bits in enumerated types, as well."""
498e8556ba3Sopenharmony_ci        return True
499e8556ba3Sopenharmony_ci
500e8556ba3Sopenharmony_ci    @property
501e8556ba3Sopenharmony_ci    def duplicate_aliased_structs(self):
502e8556ba3Sopenharmony_ci        """
503e8556ba3Sopenharmony_ci        Should aliased structs have the original struct definition listed in the
504e8556ba3Sopenharmony_ci        generated docs snippet?
505e8556ba3Sopenharmony_ci        """
506e8556ba3Sopenharmony_ci        return False
507e8556ba3Sopenharmony_ci
508e8556ba3Sopenharmony_ci    @property
509e8556ba3Sopenharmony_ci    def protectProtoComment(self):
510e8556ba3Sopenharmony_ci        """Return True if generated #endif should have a comment matching
511e8556ba3Sopenharmony_ci           the protection symbol used in the opening #ifdef/#ifndef."""
512e8556ba3Sopenharmony_ci        return False
513e8556ba3Sopenharmony_ci
514e8556ba3Sopenharmony_ci    @property
515e8556ba3Sopenharmony_ci    def extra_refpage_headers(self):
516e8556ba3Sopenharmony_ci        """Return any extra headers (preceding the title) for generated
517e8556ba3Sopenharmony_ci           reference pages."""
518e8556ba3Sopenharmony_ci        return ''
519e8556ba3Sopenharmony_ci
520e8556ba3Sopenharmony_ci    @property
521e8556ba3Sopenharmony_ci    def extra_refpage_body(self):
522e8556ba3Sopenharmony_ci        """Return any extra text (following the title) for generated
523e8556ba3Sopenharmony_ci           reference pages."""
524e8556ba3Sopenharmony_ci        return ''
525e8556ba3Sopenharmony_ci
526e8556ba3Sopenharmony_ci    def is_api_version_name(self, name):
527e8556ba3Sopenharmony_ci        """Return True if name is an API version name."""
528e8556ba3Sopenharmony_ci
529e8556ba3Sopenharmony_ci        return API_VERSION_NAME_RE.match(name) is not None
530e8556ba3Sopenharmony_ci
531e8556ba3Sopenharmony_ci    @property
532e8556ba3Sopenharmony_ci    def docgen_language(self):
533e8556ba3Sopenharmony_ci        """Return the language to be used in docgenerator [source]
534e8556ba3Sopenharmony_ci           blocks."""
535e8556ba3Sopenharmony_ci
536e8556ba3Sopenharmony_ci        return 'c++'
537