1a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos# -*- coding: utf-8 -*- 2a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos 33c77ed4e119083afaec64a173bfdcf024c271635Jarkko Pöyry#------------------------------------------------------------------------- 43c77ed4e119083afaec64a173bfdcf024c271635Jarkko Pöyry# drawElements Quality Program utilities 53c77ed4e119083afaec64a173bfdcf024c271635Jarkko Pöyry# -------------------------------------- 63c77ed4e119083afaec64a173bfdcf024c271635Jarkko Pöyry# 73c77ed4e119083afaec64a173bfdcf024c271635Jarkko Pöyry# Copyright 2015 The Android Open Source Project 83c77ed4e119083afaec64a173bfdcf024c271635Jarkko Pöyry# 93c77ed4e119083afaec64a173bfdcf024c271635Jarkko Pöyry# Licensed under the Apache License, Version 2.0 (the "License"); 103c77ed4e119083afaec64a173bfdcf024c271635Jarkko Pöyry# you may not use this file except in compliance with the License. 113c77ed4e119083afaec64a173bfdcf024c271635Jarkko Pöyry# You may obtain a copy of the License at 123c77ed4e119083afaec64a173bfdcf024c271635Jarkko Pöyry# 133c77ed4e119083afaec64a173bfdcf024c271635Jarkko Pöyry# http://www.apache.org/licenses/LICENSE-2.0 143c77ed4e119083afaec64a173bfdcf024c271635Jarkko Pöyry# 153c77ed4e119083afaec64a173bfdcf024c271635Jarkko Pöyry# Unless required by applicable law or agreed to in writing, software 163c77ed4e119083afaec64a173bfdcf024c271635Jarkko Pöyry# distributed under the License is distributed on an "AS IS" BASIS, 173c77ed4e119083afaec64a173bfdcf024c271635Jarkko Pöyry# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 183c77ed4e119083afaec64a173bfdcf024c271635Jarkko Pöyry# See the License for the specific language governing permissions and 193c77ed4e119083afaec64a173bfdcf024c271635Jarkko Pöyry# limitations under the License. 203c77ed4e119083afaec64a173bfdcf024c271635Jarkko Pöyry# 213c77ed4e119083afaec64a173bfdcf024c271635Jarkko Pöyry#------------------------------------------------------------------------- 223c77ed4e119083afaec64a173bfdcf024c271635Jarkko Pöyry 23a017863963f9194666b813f6ef88130288a5fc50Pyry Haulosimport sys, logging, re 24a017863963f9194666b813f6ef88130288a5fc50Pyry Haulosfrom lxml import etree 25a017863963f9194666b813f6ef88130288a5fc50Pyry Haulosfrom collections import OrderedDict 26a017863963f9194666b813f6ef88130288a5fc50Pyry Haulosfrom functools import wraps, partial 27a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos 28a017863963f9194666b813f6ef88130288a5fc50Pyry Hauloslog = logging.getLogger(__name__) 29a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos 30a017863963f9194666b813f6ef88130288a5fc50Pyry Haulosdebug = log.debug 31a017863963f9194666b813f6ef88130288a5fc50Pyry Haulosinfo = log.info 32a017863963f9194666b813f6ef88130288a5fc50Pyry Hauloswarning = log.warning 33a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos 34a017863963f9194666b813f6ef88130288a5fc50Pyry Haulosdef warnElem(elem, fmt, *args): 35a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos warning('%s:%d, %s %s: ' + fmt, elem.base, elem.sourceline, elem.tag, elem.get('name') or '', *args) 36a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos 37a017863963f9194666b813f6ef88130288a5fc50Pyry Haulosclass Object(object): 38a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos def __init__(self, **kwargs): 39a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos self.__dict__.update(kwargs) 40a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos 41a017863963f9194666b813f6ef88130288a5fc50Pyry Haulosclass Located(Object): 42a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos location = None 43a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos 44a017863963f9194666b813f6ef88130288a5fc50Pyry Haulosclass Group(Located): pass 45a017863963f9194666b813f6ef88130288a5fc50Pyry Haulosclass Enum(Located): pass 46a017863963f9194666b813f6ef88130288a5fc50Pyry Haulosclass Enums(Located): 47a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos name = None 48a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos comment = None 49a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos enums = None 50a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos 51a017863963f9194666b813f6ef88130288a5fc50Pyry Haulosclass Type(Located): 52a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos location = None 53a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos name=None 54a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos definition=None 55a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos api=None 56a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos requires=None 57a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos 58a017863963f9194666b813f6ef88130288a5fc50Pyry Haulosdef makeObject(cls, elem, **kwargs): 59a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos kwargs.setdefault('name', elem.get('name')) 60a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos kwargs.setdefault('comment', elem.get('comment')) 61a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos kwargs['location'] = (elem.base, elem.sourceline) 62a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos return cls(**kwargs) 63a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos 64a017863963f9194666b813f6ef88130288a5fc50Pyry Haulosdef parseEnum(eEnum): 65a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos return makeObject( 66a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos Enum, eEnum, 67a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos value=eEnum.get('value'), 68a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos type=eEnum.get('type'), 69a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos alias=eEnum.get('alias')) 70a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos 71a017863963f9194666b813f6ef88130288a5fc50Pyry Haulosclass Param(Located): pass 72a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos 73a017863963f9194666b813f6ef88130288a5fc50Pyry Haulosclass Command(Located): 74a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos name=None 75a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos declaration=None 76a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos type=None 77a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos ptype=None 78a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos group=None 79a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos params=None 80a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos alias=None 81a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos 82a017863963f9194666b813f6ef88130288a5fc50Pyry Haulosclass Interface(Object): pass 83a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos 84a017863963f9194666b813f6ef88130288a5fc50Pyry Haulosclass Index: 85a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos def __init__(self, items=[], **kwargs): 86a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos self.index = {} 87a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos self.items = [] 88a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos self.__dict__.update(kwargs) 89a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos self.update(items) 90a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos 91a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos def append(self, item): 92a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos keys = self.getkeys(item) 93a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos for key in keys: 94a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos self[key] = item 95a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos self.items.append(item) 96a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos 97a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos def update(self, items): 98a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos for item in items: 99a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos self.append(item) 100a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos 101a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos def __iter__(self): 102a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos return iter(self.items) 103a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos 104a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos def nextkey(self, key): 105a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos raise KeyError 106a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos 107a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos def getkeys(self, item): 108a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos return [] 109a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos 110a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos def __contains__(self, key): 111a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos return key in self.index 112a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos 113a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos def __setitem__(self, key, item): 114a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos if key in self.index: 115a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos self.duplicateKey(key, item) 116a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos else: 117a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos self.index[key] = item 118a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos 119a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos def duplicateKey(self, key, item): 120a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos warning("Duplicate %s: %r", type(item).__name__.lower(), key) 121a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos 122a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos def __getitem__(self, key): 123a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos try: 124a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos while True: 125a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos try: 126a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos return self.index[key] 127a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos except KeyError: 128a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos pass 129a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos key = self.nextkey(key) 130a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos except KeyError: 131a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos item = self.missingKey(key) 132a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos self.append(item) 133a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos return item 134a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos 135a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos def missingKey(self, key): 136a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos raise KeyError(key) 137a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos 138a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos def __len__(self): 139a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos return len(self.items) 140a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos 141a017863963f9194666b813f6ef88130288a5fc50Pyry Haulosclass ElemNameIndex(Index): 142a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos def getkeys(self, item): 143a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos return [item.get('name')] 144a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos 145a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos def duplicateKey(self, key, item): 146a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos warnElem(item, "Duplicate key: %s", key) 147a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos 148a017863963f9194666b813f6ef88130288a5fc50Pyry Haulosclass CommandIndex(Index): 149a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos def getkeys(self, item): 150a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos return [item.findtext('proto/name'), item.findtext('alias')] 151a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos 152a017863963f9194666b813f6ef88130288a5fc50Pyry Haulosclass NameApiIndex(Index): 153a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos def getkeys(self, item): 154a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos return [(item.get('name'), item.get('api'))] 155a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos 156a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos def nextkey(self, key): 157a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos if len(key) == 2 and key[1] is not None: 158a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos return key[0], None 159a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos raise KeyError 160a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos 161a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos def duplicateKey(self, key, item): 162a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos warnElem(item, "Duplicate key: %s", key) 163a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos 164a017863963f9194666b813f6ef88130288a5fc50Pyry Haulosclass TypeIndex(NameApiIndex): 165a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos def getkeys(self, item): 166a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos return [(item.get('name') or item.findtext('name'), item.get('api'))] 167a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos 168a017863963f9194666b813f6ef88130288a5fc50Pyry Haulosclass EnumIndex(NameApiIndex): 169a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos def getkeys(self, item): 170a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos name, api, alias = (item.get(attrib) for attrib in ['name', 'api', 'alias']) 171a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos return [(name, api)] + ([(alias, api)] if alias is not None else []) 172a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos 173a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos def duplicateKey(self, (name, api), item): 174a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos if name == item.get('alias'): 175a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos warnElem(item, "Alias already present: %s", name) 176a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos else: 177a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos warnElem(item, "Already present") 178a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos 179a017863963f9194666b813f6ef88130288a5fc50Pyry Haulosclass Registry: 180a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos def __init__(self, eRegistry): 181a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos self.types = TypeIndex(eRegistry.findall('types/type')) 182a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos self.groups = ElemNameIndex(eRegistry.findall('groups/group')) 183a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos self.enums = EnumIndex(eRegistry.findall('enums/enum')) 184a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos for eEnum in self.enums: 185a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos groupName = eEnum.get('group') 186a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos if groupName is not None: 187a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos self.groups[groupName] = eEnum 188a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos self.commands = CommandIndex(eRegistry.findall('commands/command')) 189a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos self.features = ElemNameIndex(eRegistry.findall('feature')) 190a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos self.apis = {} 191a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos for eFeature in self.features: 192a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos self.apis.setdefault(eFeature.get('api'), []).append(eFeature) 193a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos for apiFeatures in self.apis.itervalues(): 194a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos apiFeatures.sort(key=lambda eFeature: eFeature.get('number')) 195a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos self.extensions = ElemNameIndex(eRegistry.findall('extensions/extension')) 196a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos self.element = eRegistry 197a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos 198a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos def getFeatures(self, api, checkVersion=None): 199a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos return [eFeature for eFeature in self.apis[api] 200a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos if checkVersion is None or checkVersion(eFeature.get('number'))] 201a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos 202a017863963f9194666b813f6ef88130288a5fc50Pyry Haulosclass NameIndex(Index): 203a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos createMissing = None 204a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos kind = "item" 205a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos 206a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos def getkeys(self, item): 207a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos return [item.name] 208a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos 209a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos def missingKey(self, key): 210a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos if self.createMissing: 211a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos warning("Reference to implicit %s: %r", self.kind, key) 212a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos return self.createMissing(name=key) 213a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos else: 214a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos raise KeyError 215a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos 216a017863963f9194666b813f6ef88130288a5fc50Pyry Haulosdef matchApi(api1, api2): 217a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos return api1 is None or api2 is None or api1 == api2 218a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos 219a017863963f9194666b813f6ef88130288a5fc50Pyry Haulosclass Interface(Object): 220a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos pass 221a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos 222a017863963f9194666b813f6ef88130288a5fc50Pyry Haulosdef extractAlias(eCommand): 223a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos aliases = eCommand.xpath('alias/@name') 224a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos return aliases[0] if aliases else None 225a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos 226a017863963f9194666b813f6ef88130288a5fc50Pyry Haulosdef getExtensionName(eExtension): 227a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos return eExtension.get('name') 228a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos 229a017863963f9194666b813f6ef88130288a5fc50Pyry Haulosdef extensionSupports(eExtension, api, profile=None): 230a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos if api == 'gl' and profile == 'core': 231a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos needSupport = 'glcore' 232a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos else: 233a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos needSupport = api 234a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos supporteds = eExtension.get('supported').split('|') 235a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos return needSupport in supporteds 236a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos 237a017863963f9194666b813f6ef88130288a5fc50Pyry Haulosclass InterfaceSpec(Object): 238a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos def __init__(self): 239a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos self.enums = set() 240a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos self.types = set() 241a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos self.commands = set() 242091a7c799f05f94bfdb61423a934d2d9427e9f06Daniel Koch self.versions = set() 243a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos 244a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos def addComponent(self, eComponent): 245a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos if eComponent.tag == 'require': 246a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos def modify(items, item): items.add(item) 247a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos else: 248a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos assert eComponent.tag == 'remove' 249a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos def modify(items, item): 250a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos try: 251a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos items.remove(item) 252a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos except KeyError: 253a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos warning("Tried to remove absent item: %s", item) 254a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos for typeName in eComponent.xpath('type/@name'): 255a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos modify(self.types, typeName) 256a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos for enumName in eComponent.xpath('enum/@name'): 257a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos modify(self.enums, enumName) 258a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos for commandName in eComponent.xpath('command/@name'): 259a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos modify(self.commands, commandName) 260a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos 261a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos def addComponents(self, elem, api, profile=None): 262a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos for eComponent in elem.xpath('require|remove'): 263a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos cApi = eComponent.get('api') 264a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos cProfile = eComponent.get('profile') 265a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos if (matchApi(api, eComponent.get('api')) and 266a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos matchApi(profile, eComponent.get('profile'))): 267a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos self.addComponent(eComponent) 268a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos 269a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos def addFeature(self, eFeature, api=None, profile=None, force=False): 270a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos info('Feature %s', eFeature.get('name')) 271a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos if not matchApi(api, eFeature.get('api')): 272a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos if not force: return 273a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos warnElem(eFeature, 'API %s is not supported', api) 274a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos self.addComponents(eFeature, api, profile) 275091a7c799f05f94bfdb61423a934d2d9427e9f06Daniel Koch self.versions.add(eFeature.get('name')) 276a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos 277a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos def addExtension(self, eExtension, api=None, profile=None, force=False): 278a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos if not extensionSupports(eExtension, api, profile): 279a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos if not force: return 280a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos warnElem(eExtension, '%s is not supported in API %s' % (getExtensionName(eExtension), api)) 281a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos self.addComponents(eExtension, api, profile) 282a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos 283a017863963f9194666b813f6ef88130288a5fc50Pyry Haulosdef createInterface(registry, spec, api=None): 284a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos def parseType(eType): 285a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos # todo: apientry 286a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos #requires = eType.get('requires') 287a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos #if requires is not None: 288a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos # types[requires] 289a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos return makeObject( 290a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos Type, eType, 291a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos name=eType.get('name') or eType.findtext('name'), 292a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos definition=''.join(eType.xpath('.//text()')), 293a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos api=eType.get('api'), 294a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos requires=eType.get('requires')) 295a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos 296a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos def createType(name): 297a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos info('Add type %s', name) 298a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos try: 299a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos return parseType(registry.types[name, api]) 300a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos except KeyError: 301a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos return Type(name=name) 302a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos 303a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos def createEnum(enumName): 304a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos info('Add enum %s', enumName) 305a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos return parseEnum(registry.enums[enumName, api]) 306a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos 307a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos def extractPtype(elem): 308a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos ePtype = elem.find('ptype') 309a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos if ePtype is None: 310a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos return None 311a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos return types[ePtype.text] 312a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos 313a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos def extractGroup(elem): 314a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos groupName = elem.get('group') 315a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos if groupName is None: 316a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos return None 317a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos return groups[groupName] 318a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos 319a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos def parseParam(eParam): 320a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos return makeObject( 321a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos Param, eParam, 322a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos name=eParam.get('name') or eParam.findtext('name'), 323a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos declaration=''.join(eParam.xpath('.//text()')).strip(), 324a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos type=''.join(eParam.xpath('(.|ptype)/text()')).strip(), 325a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos ptype=extractPtype(eParam), 326a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos group=extractGroup(eParam)) 327a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos 328a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos def createCommand(commandName): 329a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos info('Add command %s', commandName) 330a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos eCmd = registry.commands[commandName] 331a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos eProto = eCmd.find('proto') 332a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos return makeObject( 333a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos Command, eCmd, 334a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos name=eCmd.findtext('proto/name'), 335a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos declaration=''.join(eProto.xpath('.//text()')).strip(), 336a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos type=''.join(eProto.xpath('(.|ptype)/text()')).strip(), 337a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos ptype=extractPtype(eProto), 338a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos group=extractGroup(eProto), 339a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos alias=extractAlias(eCmd), 340a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos params=NameIndex(map(parseParam, eCmd.findall('param')))) 341a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos 342a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos def createGroup(name): 343a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos info('Add group %s', name) 344a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos try: 345a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos eGroup = registry.groups[name] 346a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos except KeyError: 347a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos return Group(name=name) 348a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos return makeObject( 349a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos Group, eGroup, 350a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos # Missing enums are often from exotic extensions. Don't create dummy entries, 351a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos # just filter them out. 352a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos enums=NameIndex(enums[name] for name in eGroup.xpath('enum/@name') 353a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos if name in enums)) 354a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos 355a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos def sortedIndex(items): 356a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos return NameIndex(sorted(items, key=lambda item: item.location)) 357a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos 358a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos groups = NameIndex(createMissing=createGroup, kind="group") 359a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos types = NameIndex(map(createType, spec.types), 360a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos createMissing=createType, kind="type") 361a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos enums = NameIndex(map(createEnum, spec.enums), 362a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos createMissing=Enum, kind="enum") 363a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos commands = NameIndex(map(createCommand, spec.commands), 364091a7c799f05f94bfdb61423a934d2d9427e9f06Daniel Koch createMissing=Command, kind="command") 365091a7c799f05f94bfdb61423a934d2d9427e9f06Daniel Koch versions = sorted(spec.versions) 366a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos 367a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos # This is a mess because the registry contains alias chains whose 368a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos # midpoints might not be included in the interface even though 369a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos # endpoints are. 370a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos for command in commands: 371a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos alias = command.alias 372a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos aliasCommand = None 373a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos while alias is not None: 374a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos aliasCommand = registry.commands[alias] 375a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos alias = extractAlias(aliasCommand) 376a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos command.alias = None 377a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos if aliasCommand is not None: 378a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos name = aliasCommand.findtext('proto/name') 379a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos if name in commands: 380a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos command.alias = commands[name] 381a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos 382a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos return Interface( 383a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos types=sortedIndex(types), 384a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos enums=sortedIndex(enums), 385a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos groups=sortedIndex(groups), 386091a7c799f05f94bfdb61423a934d2d9427e9f06Daniel Koch commands=sortedIndex(commands), 387091a7c799f05f94bfdb61423a934d2d9427e9f06Daniel Koch versions=versions) 388a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos 389a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos 390a017863963f9194666b813f6ef88130288a5fc50Pyry Haulosdef spec(registry, api, version=None, profile=None, extensionNames=[], protects=[], force=False): 391a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos available = set(protects) 392a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos spec = InterfaceSpec() 393a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos 394a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos if version is None or version is False: 395a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos def check(v): return False 396a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos elif version is True: 397a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos def check(v): return True 398a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos else: 399a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos def check(v): return v <= version 400a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos 401a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos for eFeature in registry.getFeatures(api, check): 402a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos spec.addFeature(eFeature, api, profile, force) 403a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos 404a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos for extName in extensionNames: 405a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos eExtension = registry.extensions[extName] 406a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos protect = eExtension.get('protect') 407a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos if protect is not None and protect not in available: 408a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos warnElem(eExtension, "Unavailable dependency %s", protect) 409a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos if not force: 410a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos continue 411a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos spec.addExtension(eExtension, api, profile, force) 412a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos available.add(extName) 413a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos 414a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos return spec 415a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos 416a017863963f9194666b813f6ef88130288a5fc50Pyry Haulosdef interface(registry, api, **kwargs): 417a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos s = spec(registry, api, **kwargs) 418a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos return createInterface(registry, s, api) 419a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos 420a017863963f9194666b813f6ef88130288a5fc50Pyry Haulosdef parse(path): 421a017863963f9194666b813f6ef88130288a5fc50Pyry Haulos return Registry(etree.parse(path)) 422