blob: 3dbd8ee07bbac6b311b0ffa569ee9190354eb760 [file] [log] [blame]
José Fonseca8e0d1042014-05-27 20:02:34 +01001#!/usr/bin/env python
2##########################################################################
3#
4# Copyright 2014 VMware, Inc
5# All Rights Reserved.
6#
7# Permission is hereby granted, free of charge, to any person obtaining a copy
8# of this software and associated documentation files (the "Software"), to deal
9# in the Software without restriction, including without limitation the rights
10# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11# copies of the Software, and to permit persons to whom the Software is
12# furnished to do so, subject to the following conditions:
13#
14# The above copyright notice and this permission notice shall be included in
15# all copies or substantial portions of the Software.
16#
17# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23# THE SOFTWARE.
24#
25##########################################################################/
26
27
28#
29# Script to half-generate *api.py based on Khronos' *.xml
30#
31
32
José Fonseca0296e3a2014-08-13 19:00:31 +010033import optparse
José Fonseca8e0d1042014-05-27 20:02:34 +010034import sys
35import xml.etree.ElementTree as ET
36
37import c2api
38
39
José Fonseca4563c462014-05-30 15:57:36 +010040def appendToken(tokens, text):
41 for token in text.split():
42 if token.startswith('*'):
43 for c in token:
44 tokens.append(c)
45 else:
46 tokens.append(token)
47
José Fonseca8e0d1042014-05-27 20:02:34 +010048
49def getType(node):
José Fonseca4563c462014-05-30 15:57:36 +010050 tokens = []
José Fonseca8e0d1042014-05-27 20:02:34 +010051
José Fonseca4563c462014-05-30 15:57:36 +010052 if node.text is not None:
53 appendToken(tokens, node.text)
54
55 ptype = node.find('ptype')
56 if ptype is not None:
57 appendToken(tokens, ptype.text)
58 appendToken(tokens, ptype.tail)
59
60 # Array
61 lenExpr = node.get('len')
62 if lenExpr is not None:
63 assert tokens[-1] == '*'
64 tokens = tokens[:-1]
65 if lenExpr == "COMPSIZE(pname)":
66 lenExpr = "_gl_param_size(pname)"
67
68 typeText = ' '.join(tokens)
José Fonseca8e0d1042014-05-27 20:02:34 +010069 parser = c2api.DeclParser()
70 parser.tokenize(typeText + ';')
José Fonseca4563c462014-05-30 15:57:36 +010071 typeExpr = parser.parse_type()
José Fonseca8e0d1042014-05-27 20:02:34 +010072
José Fonseca4563c462014-05-30 15:57:36 +010073 if lenExpr is not None:
José Fonseca9b1b9422014-12-25 16:21:43 +000074 if lenExpr == "1":
75 typeExpr = 'Pointer(%s)' % (typeExpr)
76 else:
77 if not lenExpr.isdigit():
78 lenExpr = '"' + lenExpr + '"'
79 typeExpr = 'Array(%s, %s)' % (typeExpr, lenExpr)
José Fonseca4563c462014-05-30 15:57:36 +010080
81 return typeExpr
82
83
84def processCommand(prototypes, command):
85 proto = command.find('proto')
86
87 functionName = proto.find('name').text
88
89 retType = getType(proto)
90
91 args = []
92 for param in command.findall('param'):
93 argName = param.find('name').text
94 #print argName, param.text
95 argType = getType(param)
96 if argName.lower() == 'hdc':
97 argName = 'hDC'
98 arg = '(%s, "%s")' % (argType, argName)
99 args.append(arg)
100
101 if namespace == 'WGL':
102 constructor = 'StdFunction'
103 else:
104 constructor = 'GlFunction'
105
106 prototype = '%s(%s, "%s", [%s])' % (constructor, retType, functionName, ', '.join(args))
107
108 prototypes[functionName] = prototype
109
110
José Fonseca251aa362014-12-31 19:37:44 +0000111def processRequire(node, filterName):
José Fonseca0296e3a2014-08-13 19:00:31 +0100112 nodeName = node.get('name')
113 if filterName is not None and nodeName != filterName:
114 return
115
José Fonseca14490752014-08-13 18:41:14 +0100116 commands = []
117 for requireNode in node.findall('require'):
118 commands.extend(requireNode.findall('command'))
José Fonseca4563c462014-05-30 15:57:36 +0100119 if not commands:
120 return
José Fonsecafb195262014-12-25 16:23:19 +0000121
122 functionNames = [command.get('name') for command in commands]
123
José Fonseca251aa362014-12-31 19:37:44 +0000124 return nodeName, functionNames
125
126
127
128def printPrototypes(prototypes, extensionName, functionNames):
129 print ' # %s' % extensionName
130
131 if extensionName == 'GL_EXT_direct_state_access':
José Fonsecafb195262014-12-25 16:23:19 +0000132 functionNames.sort()
133
134 for functionName in functionNames:
José Fonseca4563c462014-05-30 15:57:36 +0100135 prototype = prototypes[functionName]
136 print ' %s,' % prototype
José Fonsecafb195262014-12-25 16:23:19 +0000137
José Fonseca4563c462014-05-30 15:57:36 +0100138 print
José Fonseca8e0d1042014-05-27 20:02:34 +0100139
140
José Fonseca0296e3a2014-08-13 19:00:31 +0100141def main():
142 optparser = optparse.OptionParser(
143 usage='\n\t%prog [options] <xml> ...',
144 version='%%prog')
145 optparser.add_option(
146 '--filter', metavar='NAME',
147 type='string', dest='filter',
148 help='filter feature/extension')
149 (options, args) = optparser.parse_args(sys.argv[1:])
José Fonseca8e0d1042014-05-27 20:02:34 +0100150
José Fonseca0296e3a2014-08-13 19:00:31 +0100151 global prototypes
152 global namespace
José Fonseca8e0d1042014-05-27 20:02:34 +0100153
José Fonseca0296e3a2014-08-13 19:00:31 +0100154 for arg in args:
155 tree = ET.parse(arg)
156 root = tree.getroot()
José Fonseca8e0d1042014-05-27 20:02:34 +0100157
José Fonseca0296e3a2014-08-13 19:00:31 +0100158 prototypes = {}
José Fonseca8e0d1042014-05-27 20:02:34 +0100159
José Fonseca0296e3a2014-08-13 19:00:31 +0100160 for commands in root.findall('commands'):
161 namespace = commands.get('namespace')
162 for command in commands.findall('command'):
163 processCommand(prototypes, command)
José Fonseca8e0d1042014-05-27 20:02:34 +0100164
José Fonseca251aa362014-12-31 19:37:44 +0000165 # Extract features
166 features = []
José Fonseca0296e3a2014-08-13 19:00:31 +0100167 for feature in root.findall('feature'):
José Fonseca251aa362014-12-31 19:37:44 +0000168 ret = processRequire(feature, options.filter)
169 if ret is not None:
170 features.append(ret)
José Fonseca0296e3a2014-08-13 19:00:31 +0100171
José Fonseca251aa362014-12-31 19:37:44 +0000172 # Extract extensions
173 extensions = []
174 for extension in root.find('extensions').findall('extension'):
175 ret = processRequire(extension, options.filter)
176 if ret is not None:
177 extensions.append(ret)
178
179 # Eliminate the functions from features that are in extensions
180 for extensionName, extensionFunctionNames in extensions:
181 for featureName, featureFunctionNames in features:
182 for functionName in extensionFunctionNames:
183 try:
184 featureFunctionNames.remove(functionName)
185 except ValueError:
186 pass
187
188 # Print all
189 for extensionName, functionNames in features + extensions:
190 printPrototypes(prototypes, extensionName, functionNames)
José Fonseca0296e3a2014-08-13 19:00:31 +0100191
192
193if __name__ == '__main__':
194 main()