blob: 6b4ec3b7c4a24e3c20b614b56a42cad2753e1e92 [file] [log] [blame]
Jose Fonseca5b3c68c2019-04-28 14:13:01 +01001#!/usr/bin/env python3
José Fonseca8e0d1042014-05-27 20:02:34 +01002##########################################################################
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
Jose Fonseca5c6ca062015-01-24 09:39:55 +0000128def printPrototypes(prototypes, extensionName, functionNames, skip=set()):
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100129 print(' # %s' % extensionName)
José Fonseca251aa362014-12-31 19:37:44 +0000130
131 if extensionName == 'GL_EXT_direct_state_access':
José Fonsecafb195262014-12-25 16:23:19 +0000132 functionNames.sort()
133
134 for functionName in functionNames:
Jose Fonseca5c6ca062015-01-24 09:39:55 +0000135 if functionName not in skip:
136 prototype = prototypes[functionName]
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100137 print(' %s,' % prototype)
José Fonsecafb195262014-12-25 16:23:19 +0000138
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100139 print()
José Fonseca8e0d1042014-05-27 20:02:34 +0100140
141
José Fonseca0296e3a2014-08-13 19:00:31 +0100142def main():
143 optparser = optparse.OptionParser(
144 usage='\n\t%prog [options] <xml> ...',
145 version='%%prog')
146 optparser.add_option(
147 '--filter', metavar='NAME',
148 type='string', dest='filter',
149 help='filter feature/extension')
150 (options, args) = optparser.parse_args(sys.argv[1:])
José Fonseca8e0d1042014-05-27 20:02:34 +0100151
José Fonseca0296e3a2014-08-13 19:00:31 +0100152 global prototypes
153 global namespace
José Fonseca8e0d1042014-05-27 20:02:34 +0100154
José Fonseca0296e3a2014-08-13 19:00:31 +0100155 for arg in args:
156 tree = ET.parse(arg)
157 root = tree.getroot()
José Fonseca8e0d1042014-05-27 20:02:34 +0100158
José Fonseca0296e3a2014-08-13 19:00:31 +0100159 prototypes = {}
José Fonseca8e0d1042014-05-27 20:02:34 +0100160
José Fonseca0296e3a2014-08-13 19:00:31 +0100161 for commands in root.findall('commands'):
162 namespace = commands.get('namespace')
163 for command in commands.findall('command'):
164 processCommand(prototypes, command)
José Fonseca8e0d1042014-05-27 20:02:34 +0100165
José Fonseca251aa362014-12-31 19:37:44 +0000166 # Extract features
167 features = []
José Fonseca0296e3a2014-08-13 19:00:31 +0100168 for feature in root.findall('feature'):
José Fonseca251aa362014-12-31 19:37:44 +0000169 ret = processRequire(feature, options.filter)
170 if ret is not None:
171 features.append(ret)
José Fonseca0296e3a2014-08-13 19:00:31 +0100172
José Fonseca251aa362014-12-31 19:37:44 +0000173 # Extract extensions
174 extensions = []
175 for extension in root.find('extensions').findall('extension'):
176 ret = processRequire(extension, options.filter)
177 if ret is not None:
178 extensions.append(ret)
179
180 # Eliminate the functions from features that are in extensions
181 for extensionName, extensionFunctionNames in extensions:
182 for featureName, featureFunctionNames in features:
183 for functionName in extensionFunctionNames:
184 try:
185 featureFunctionNames.remove(functionName)
186 except ValueError:
187 pass
188
189 # Print all
Jose Fonseca5c6ca062015-01-24 09:39:55 +0000190 skip = set()
José Fonseca251aa362014-12-31 19:37:44 +0000191 for extensionName, functionNames in features + extensions:
Jose Fonseca5c6ca062015-01-24 09:39:55 +0000192 printPrototypes(prototypes, extensionName, functionNames, skip)
193 skip.update(functionNames)
José Fonseca0296e3a2014-08-13 19:00:31 +0100194
195
196if __name__ == '__main__':
197 main()