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