| #!/usr/bin/env python3 |
| ########################################################################## |
| # |
| # Copyright 2014 VMware, Inc |
| # All Rights Reserved. |
| # |
| # Permission is hereby granted, free of charge, to any person obtaining a copy |
| # of this software and associated documentation files (the "Software"), to deal |
| # in the Software without restriction, including without limitation the rights |
| # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
| # copies of the Software, and to permit persons to whom the Software is |
| # furnished to do so, subject to the following conditions: |
| # |
| # The above copyright notice and this permission notice shall be included in |
| # all copies or substantial portions of the Software. |
| # |
| # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
| # THE SOFTWARE. |
| # |
| ##########################################################################/ |
| |
| |
| # |
| # Script to half-generate *api.py based on Khronos' *.xml |
| # |
| |
| |
| import optparse |
| import sys |
| import xml.etree.ElementTree as ET |
| |
| import c2api |
| |
| |
| def appendToken(tokens, text): |
| for token in text.split(): |
| if token.startswith('*'): |
| for c in token: |
| tokens.append(c) |
| else: |
| tokens.append(token) |
| |
| |
| def getType(node): |
| tokens = [] |
| |
| if node.text is not None: |
| appendToken(tokens, node.text) |
| |
| ptype = node.find('ptype') |
| if ptype is not None: |
| appendToken(tokens, ptype.text) |
| appendToken(tokens, ptype.tail) |
| |
| # Array |
| lenExpr = node.get('len') |
| if lenExpr is not None: |
| assert tokens[-1] == '*' |
| tokens = tokens[:-1] |
| if lenExpr == "COMPSIZE(pname)": |
| lenExpr = "_gl_param_size(pname)" |
| |
| typeText = ' '.join(tokens) |
| parser = c2api.DeclParser() |
| parser.tokenize(typeText + ';') |
| typeExpr = parser.parse_type() |
| |
| if lenExpr is not None: |
| if lenExpr == "1": |
| typeExpr = 'Pointer(%s)' % (typeExpr) |
| else: |
| if not lenExpr.isdigit(): |
| lenExpr = '"' + lenExpr + '"' |
| typeExpr = 'Array(%s, %s)' % (typeExpr, lenExpr) |
| |
| return typeExpr |
| |
| |
| def processCommand(prototypes, command): |
| proto = command.find('proto') |
| |
| functionName = proto.find('name').text |
| |
| retType = getType(proto) |
| |
| args = [] |
| for param in command.findall('param'): |
| argName = param.find('name').text |
| #print argName, param.text |
| argType = getType(param) |
| if argName.lower() == 'hdc': |
| argName = 'hDC' |
| arg = '(%s, "%s")' % (argType, argName) |
| args.append(arg) |
| |
| if namespace == 'WGL': |
| constructor = 'StdFunction' |
| else: |
| constructor = 'GlFunction' |
| |
| prototype = '%s(%s, "%s", [%s])' % (constructor, retType, functionName, ', '.join(args)) |
| |
| prototypes[functionName] = prototype |
| |
| |
| def processRequire(node, filterName): |
| nodeName = node.get('name') |
| if filterName is not None and nodeName != filterName: |
| return |
| |
| commands = [] |
| for requireNode in node.findall('require'): |
| commands.extend(requireNode.findall('command')) |
| if not commands: |
| return |
| |
| functionNames = [command.get('name') for command in commands] |
| |
| return nodeName, functionNames |
| |
| |
| |
| def printPrototypes(prototypes, extensionName, functionNames, skip=set()): |
| print(' # %s' % extensionName) |
| |
| if extensionName == 'GL_EXT_direct_state_access': |
| functionNames.sort() |
| |
| for functionName in functionNames: |
| if functionName not in skip: |
| prototype = prototypes[functionName] |
| print(' %s,' % prototype) |
| |
| print() |
| |
| |
| def main(): |
| optparser = optparse.OptionParser( |
| usage='\n\t%prog [options] <xml> ...', |
| version='%%prog') |
| optparser.add_option( |
| '--filter', metavar='NAME', |
| type='string', dest='filter', |
| help='filter feature/extension') |
| (options, args) = optparser.parse_args(sys.argv[1:]) |
| |
| global prototypes |
| global namespace |
| |
| for arg in args: |
| tree = ET.parse(arg) |
| root = tree.getroot() |
| |
| prototypes = {} |
| |
| for commands in root.findall('commands'): |
| namespace = commands.get('namespace') |
| for command in commands.findall('command'): |
| processCommand(prototypes, command) |
| |
| # Extract features |
| features = [] |
| for feature in root.findall('feature'): |
| ret = processRequire(feature, options.filter) |
| if ret is not None: |
| features.append(ret) |
| |
| # Extract extensions |
| extensions = [] |
| for extension in root.find('extensions').findall('extension'): |
| ret = processRequire(extension, options.filter) |
| if ret is not None: |
| extensions.append(ret) |
| |
| # Eliminate the functions from features that are in extensions |
| for extensionName, extensionFunctionNames in extensions: |
| for featureName, featureFunctionNames in features: |
| for functionName in extensionFunctionNames: |
| try: |
| featureFunctionNames.remove(functionName) |
| except ValueError: |
| pass |
| |
| # Print all |
| skip = set() |
| for extensionName, functionNames in features + extensions: |
| printPrototypes(prototypes, extensionName, functionNames, skip) |
| skip.update(functionNames) |
| |
| |
| if __name__ == '__main__': |
| main() |