1e5c31af7Sopenharmony_ci#!/usr/bin/python3 2e5c31af7Sopenharmony_ci# 3e5c31af7Sopenharmony_ci# Copyright (c) 2018-2019 Collabora, Ltd. 4e5c31af7Sopenharmony_ci# 5e5c31af7Sopenharmony_ci# SPDX-License-Identifier: Apache-2.0 6e5c31af7Sopenharmony_ci# 7e5c31af7Sopenharmony_ci# Author(s): Ryan Pavlik <ryan.pavlik@collabora.com> 8e5c31af7Sopenharmony_ci# 9e5c31af7Sopenharmony_ci# Purpose: This file performs some basic checks of the custom macros 10e5c31af7Sopenharmony_ci# used in the AsciiDoctor source for the spec, especially 11e5c31af7Sopenharmony_ci# related to the validity of the entities linked-to. 12e5c31af7Sopenharmony_ci 13e5c31af7Sopenharmony_cifrom pathlib import Path 14e5c31af7Sopenharmony_ci 15e5c31af7Sopenharmony_cifrom reg import Registry 16e5c31af7Sopenharmony_cifrom spec_tools.entity_db import EntityDatabase 17e5c31af7Sopenharmony_cifrom spec_tools.macro_checker import MacroChecker 18e5c31af7Sopenharmony_cifrom spec_tools.macro_checker_file import MacroCheckerFile 19e5c31af7Sopenharmony_cifrom spec_tools.main import checkerMain 20e5c31af7Sopenharmony_cifrom spec_tools.shared import (AUTO_FIX_STRING, EXTENSION_CATEGORY, MessageId, 21e5c31af7Sopenharmony_ci MessageType) 22e5c31af7Sopenharmony_ci 23e5c31af7Sopenharmony_ci### 24e5c31af7Sopenharmony_ci# "Configuration" constants 25e5c31af7Sopenharmony_ci 26e5c31af7Sopenharmony_ciFREEFORM_CATEGORY = 'freeform' 27e5c31af7Sopenharmony_ci 28e5c31af7Sopenharmony_ci# defines mentioned in spec but not needed in registry 29e5c31af7Sopenharmony_ciEXTRA_DEFINES = ( 30e5c31af7Sopenharmony_ci 'VKAPI_ATTR', 31e5c31af7Sopenharmony_ci 'VKAPI_CALL', 32e5c31af7Sopenharmony_ci 'VKAPI_PTR', 33e5c31af7Sopenharmony_ci 'VK_NO_STDDEF_H', 34e5c31af7Sopenharmony_ci 'VK_NO_STDINT_H', 35e5c31af7Sopenharmony_ci ) 36e5c31af7Sopenharmony_ci 37e5c31af7Sopenharmony_ci# Extra freeform refpages in addition to EXTRA_DEFINES 38e5c31af7Sopenharmony_ciEXTRA_REFPAGES = ( 39e5c31af7Sopenharmony_ci 'VK_VERSION_1_0', 40e5c31af7Sopenharmony_ci 'VK_VERSION_1_1', 41e5c31af7Sopenharmony_ci 'VK_VERSION_1_2', 42e5c31af7Sopenharmony_ci 'VK_VERSION_1_3', 43e5c31af7Sopenharmony_ci 'WSIheaders', 44e5c31af7Sopenharmony_ci 'provisional-headers', 45e5c31af7Sopenharmony_ci ) 46e5c31af7Sopenharmony_ci 47e5c31af7Sopenharmony_ci# These are marked with the code: macro 48e5c31af7Sopenharmony_ciSYSTEM_TYPES = set(('void', 'char', 'float', 'size_t', 'uintptr_t', 49e5c31af7Sopenharmony_ci 'int8_t', 'uint8_t', 50e5c31af7Sopenharmony_ci 'int32_t', 'uint32_t', 51e5c31af7Sopenharmony_ci 'int64_t', 'uint64_t')) 52e5c31af7Sopenharmony_ci 53e5c31af7Sopenharmony_ciROOT = Path(__file__).resolve().parent.parent 54e5c31af7Sopenharmony_ciDEFAULT_DISABLED_MESSAGES = set(( 55e5c31af7Sopenharmony_ci MessageId.LEGACY, 56e5c31af7Sopenharmony_ci MessageId.REFPAGE_MISSING, 57e5c31af7Sopenharmony_ci MessageId.MISSING_MACRO, 58e5c31af7Sopenharmony_ci MessageId.EXTENSION, 59e5c31af7Sopenharmony_ci # TODO *text macro checking actually needs fixing for Vulkan 60e5c31af7Sopenharmony_ci MessageId.MISUSED_TEXT, 61e5c31af7Sopenharmony_ci MessageId.MISSING_TEXT 62e5c31af7Sopenharmony_ci)) 63e5c31af7Sopenharmony_ci 64e5c31af7Sopenharmony_ciCWD = Path('.').resolve() 65e5c31af7Sopenharmony_ci 66e5c31af7Sopenharmony_ci 67e5c31af7Sopenharmony_ciclass VulkanEntityDatabase(EntityDatabase): 68e5c31af7Sopenharmony_ci """Vulkan-specific subclass of EntityDatabase.""" 69e5c31af7Sopenharmony_ci 70e5c31af7Sopenharmony_ci def __init__(self, *args, **kwargs): 71e5c31af7Sopenharmony_ci super().__init__(*args, **kwargs) 72e5c31af7Sopenharmony_ci self._conditionally_recognized = set(('fname', 'sname')) 73e5c31af7Sopenharmony_ci 74e5c31af7Sopenharmony_ci def makeRegistry(self): 75e5c31af7Sopenharmony_ci registryFile = str(ROOT / 'xml/vk.xml') 76e5c31af7Sopenharmony_ci registry = Registry() 77e5c31af7Sopenharmony_ci registry.loadFile(registryFile) 78e5c31af7Sopenharmony_ci return registry 79e5c31af7Sopenharmony_ci 80e5c31af7Sopenharmony_ci def getNamePrefix(self): 81e5c31af7Sopenharmony_ci return "vk" 82e5c31af7Sopenharmony_ci 83e5c31af7Sopenharmony_ci def getPlatformRequires(self): 84e5c31af7Sopenharmony_ci return 'vk_platform' 85e5c31af7Sopenharmony_ci 86e5c31af7Sopenharmony_ci def getSystemTypes(self): 87e5c31af7Sopenharmony_ci return SYSTEM_TYPES 88e5c31af7Sopenharmony_ci 89e5c31af7Sopenharmony_ci def populateMacros(self): 90e5c31af7Sopenharmony_ci self.addMacros('t', ['link', 'name'], ['funcpointers', 'flags']) 91e5c31af7Sopenharmony_ci 92e5c31af7Sopenharmony_ci def populateEntities(self): 93e5c31af7Sopenharmony_ci # These are not mentioned in the XML 94e5c31af7Sopenharmony_ci for name in EXTRA_DEFINES: 95e5c31af7Sopenharmony_ci self.addEntity(name, 'dlink', 96e5c31af7Sopenharmony_ci category=FREEFORM_CATEGORY, generates=False) 97e5c31af7Sopenharmony_ci for name in EXTRA_REFPAGES: 98e5c31af7Sopenharmony_ci self.addEntity(name, 'code', 99e5c31af7Sopenharmony_ci category=FREEFORM_CATEGORY, generates=False) 100e5c31af7Sopenharmony_ci 101e5c31af7Sopenharmony_ci def shouldBeRecognized(self, macro, entity_name): 102e5c31af7Sopenharmony_ci """Determine, based on the macro and the name provided, if we should expect to recognize the entity.""" 103e5c31af7Sopenharmony_ci if super().shouldBeRecognized(macro, entity_name): 104e5c31af7Sopenharmony_ci return True 105e5c31af7Sopenharmony_ci 106e5c31af7Sopenharmony_ci # The *name: macros in Vulkan should also be recognized if the entity name matches the pattern. 107e5c31af7Sopenharmony_ci if macro in self._conditionally_recognized and self.likelyRecognizedEntity(entity_name): 108e5c31af7Sopenharmony_ci return True 109e5c31af7Sopenharmony_ci return False 110e5c31af7Sopenharmony_ci 111e5c31af7Sopenharmony_ci 112e5c31af7Sopenharmony_ciclass VulkanMacroCheckerFile(MacroCheckerFile): 113e5c31af7Sopenharmony_ci """Vulkan-specific subclass of MacroCheckerFile.""" 114e5c31af7Sopenharmony_ci 115e5c31af7Sopenharmony_ci def perform_entity_check(self, type): 116e5c31af7Sopenharmony_ci """Returns True if an entity check should be performed on this 117e5c31af7Sopenharmony_ci refpage type. 118e5c31af7Sopenharmony_ci 119e5c31af7Sopenharmony_ci Overrides base class definition for Vulkan, since we have refpage 120e5c31af7Sopenharmony_ci types which do not correspond to entities in the API.""" 121e5c31af7Sopenharmony_ci 122e5c31af7Sopenharmony_ci return type != 'builtins' and type != 'spirv' 123e5c31af7Sopenharmony_ci 124e5c31af7Sopenharmony_ci def handleWrongMacro(self, msg, data): 125e5c31af7Sopenharmony_ci """Report an appropriate message when we found that the macro used is incorrect. 126e5c31af7Sopenharmony_ci 127e5c31af7Sopenharmony_ci May be overridden depending on each API's behavior regarding macro misuse: 128e5c31af7Sopenharmony_ci e.g. in some cases, it may be considered a MessageId.LEGACY warning rather than 129e5c31af7Sopenharmony_ci a MessageId.WRONG_MACRO or MessageId.EXTENSION. 130e5c31af7Sopenharmony_ci """ 131e5c31af7Sopenharmony_ci message_type = MessageType.WARNING 132e5c31af7Sopenharmony_ci message_id = MessageId.WRONG_MACRO 133e5c31af7Sopenharmony_ci group = 'macro' 134e5c31af7Sopenharmony_ci 135e5c31af7Sopenharmony_ci if data.category == EXTENSION_CATEGORY: 136e5c31af7Sopenharmony_ci # Ah, this is an extension 137e5c31af7Sopenharmony_ci msg.append( 138e5c31af7Sopenharmony_ci 'This is apparently an extension name, which should be marked up as a link.') 139e5c31af7Sopenharmony_ci message_id = MessageId.EXTENSION 140e5c31af7Sopenharmony_ci group = None # replace the whole thing 141e5c31af7Sopenharmony_ci else: 142e5c31af7Sopenharmony_ci # Non-extension, we found the macro though. 143e5c31af7Sopenharmony_ci if data.macro[0] == self.macro[0] and data.macro[1:] == 'link' and self.macro[1:] == 'name': 144e5c31af7Sopenharmony_ci # First letter matches, old is 'name', new is 'link': 145e5c31af7Sopenharmony_ci # This is legacy markup 146e5c31af7Sopenharmony_ci msg.append( 147e5c31af7Sopenharmony_ci 'This is legacy markup that has not been updated yet.') 148e5c31af7Sopenharmony_ci message_id = MessageId.LEGACY 149e5c31af7Sopenharmony_ci else: 150e5c31af7Sopenharmony_ci # Not legacy, just wrong. 151e5c31af7Sopenharmony_ci message_type = MessageType.ERROR 152e5c31af7Sopenharmony_ci 153e5c31af7Sopenharmony_ci msg.append(AUTO_FIX_STRING) 154e5c31af7Sopenharmony_ci self.diag(message_type, message_id, msg, 155e5c31af7Sopenharmony_ci group=group, replacement=self.makeMacroMarkup(data=data), fix=self.makeFix(data=data)) 156e5c31af7Sopenharmony_ci 157e5c31af7Sopenharmony_ci def allowEnumXrefs(self): 158e5c31af7Sopenharmony_ci """Returns True if enums can be specified in the 'xrefs' attribute 159e5c31af7Sopenharmony_ci of a refpage. 160e5c31af7Sopenharmony_ci 161e5c31af7Sopenharmony_ci Overrides base class behavior. OpenXR does not allow this. 162e5c31af7Sopenharmony_ci """ 163e5c31af7Sopenharmony_ci return True 164e5c31af7Sopenharmony_ci 165e5c31af7Sopenharmony_cidef makeMacroChecker(enabled_messages): 166e5c31af7Sopenharmony_ci """Create a correctly-configured MacroChecker instance.""" 167e5c31af7Sopenharmony_ci entity_db = VulkanEntityDatabase() 168e5c31af7Sopenharmony_ci return MacroChecker(enabled_messages, entity_db, VulkanMacroCheckerFile, ROOT) 169e5c31af7Sopenharmony_ci 170e5c31af7Sopenharmony_ci 171e5c31af7Sopenharmony_ciif __name__ == '__main__': 172e5c31af7Sopenharmony_ci default_enabled_messages = set(MessageId).difference( 173e5c31af7Sopenharmony_ci DEFAULT_DISABLED_MESSAGES) 174e5c31af7Sopenharmony_ci 175e5c31af7Sopenharmony_ci all_docs = [str(fn) 176e5c31af7Sopenharmony_ci for fn in sorted((ROOT / 'chapters/').glob('**/[A-Za-z]*.adoc'))] 177e5c31af7Sopenharmony_ci all_docs.extend([str(fn) 178e5c31af7Sopenharmony_ci for fn in sorted((ROOT / 'appendices/').glob('**/[A-Za-z]*.adoc'))]) 179e5c31af7Sopenharmony_ci all_docs.append(str(ROOT / 'vkspec.adoc')) 180e5c31af7Sopenharmony_ci 181e5c31af7Sopenharmony_ci checkerMain(default_enabled_messages, makeMacroChecker, 182e5c31af7Sopenharmony_ci all_docs) 183