1*1cddb830SAndroid Build Coastguard Worker# Copyright (c) 2020 The Khronos Group Inc. 2*1cddb830SAndroid Build Coastguard Worker# 3*1cddb830SAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License"); 4*1cddb830SAndroid Build Coastguard Worker# you may not use this file except in compliance with the License. 5*1cddb830SAndroid Build Coastguard Worker# You may obtain a copy of the License at 6*1cddb830SAndroid Build Coastguard Worker# 7*1cddb830SAndroid Build Coastguard Worker# http://www.apache.org/licenses/LICENSE-2.0 8*1cddb830SAndroid Build Coastguard Worker# 9*1cddb830SAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software 10*1cddb830SAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS, 11*1cddb830SAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*1cddb830SAndroid Build Coastguard Worker# See the License for the specific language governing permissions and 13*1cddb830SAndroid Build Coastguard Worker# limitations under the License. 14*1cddb830SAndroid Build Coastguard Worker 15*1cddb830SAndroid Build Coastguard Workerfrom collections import OrderedDict 16*1cddb830SAndroid Build Coastguard Workerfrom collections import namedtuple 17*1cddb830SAndroid Build Coastguard Worker 18*1cddb830SAndroid Build Coastguard Workerimport argparse 19*1cddb830SAndroid Build Coastguard Workerimport sys 20*1cddb830SAndroid Build Coastguard Workerimport urllib 21*1cddb830SAndroid Build Coastguard Workerimport xml.etree.ElementTree as etree 22*1cddb830SAndroid Build Coastguard Workerimport urllib.request 23*1cddb830SAndroid Build Coastguard Worker 24*1cddb830SAndroid Build Coastguard Worker# parse_xml - Helper function to parse the XML file from a URL or local file. 25*1cddb830SAndroid Build Coastguard Workerdef parse_xml(path): 26*1cddb830SAndroid Build Coastguard Worker file = urllib.request.urlopen(path) if path.startswith("http") else open(path, 'r') 27*1cddb830SAndroid Build Coastguard Worker with file: 28*1cddb830SAndroid Build Coastguard Worker tree = etree.parse(file) 29*1cddb830SAndroid Build Coastguard Worker return tree 30*1cddb830SAndroid Build Coastguard Worker 31*1cddb830SAndroid Build Coastguard Worker# noneStr - returns string argument, or "" if argument is None. 32*1cddb830SAndroid Build Coastguard Workerdef noneStr(s): 33*1cddb830SAndroid Build Coastguard Worker if s: 34*1cddb830SAndroid Build Coastguard Worker return s 35*1cddb830SAndroid Build Coastguard Worker return "" 36*1cddb830SAndroid Build Coastguard Worker 37*1cddb830SAndroid Build Coastguard Workerdef parse_args(): 38*1cddb830SAndroid Build Coastguard Worker parser = argparse.ArgumentParser() 39*1cddb830SAndroid Build Coastguard Worker 40*1cddb830SAndroid Build Coastguard Worker # To pull the latest registry file from GitHub, pass: 41*1cddb830SAndroid Build Coastguard Worker # -registry "https://raw.githubusercontent.com/KhronosGroup/OpenCL-Docs/main/xml/cl.xml" 42*1cddb830SAndroid Build Coastguard Worker 43*1cddb830SAndroid Build Coastguard Worker parser.add_argument('-registry', action='store', 44*1cddb830SAndroid Build Coastguard Worker default='cl.xml', 45*1cddb830SAndroid Build Coastguard Worker help='Use specified registry file instead of cl.xml') 46*1cddb830SAndroid Build Coastguard Worker parser.add_argument('-o', action='store', dest='directory', 47*1cddb830SAndroid Build Coastguard Worker default='.', 48*1cddb830SAndroid Build Coastguard Worker help='Create target and related files in specified directory') 49*1cddb830SAndroid Build Coastguard Worker 50*1cddb830SAndroid Build Coastguard Worker args = parser.parse_args() 51*1cddb830SAndroid Build Coastguard Worker return args 52*1cddb830SAndroid Build Coastguard Worker 53*1cddb830SAndroid Build Coastguard Workerdef load_spec(args): 54*1cddb830SAndroid Build Coastguard Worker specpath = args.registry 55*1cddb830SAndroid Build Coastguard Worker 56*1cddb830SAndroid Build Coastguard Worker print('Parsing XML file from: ' + specpath) 57*1cddb830SAndroid Build Coastguard Worker spec = parse_xml(specpath) 58*1cddb830SAndroid Build Coastguard Worker return spec 59*1cddb830SAndroid Build Coastguard Worker 60*1cddb830SAndroid Build Coastguard Workerdef get_apisigs(spec): 61*1cddb830SAndroid Build Coastguard Worker # Generate the API function signatures dictionary: 62*1cddb830SAndroid Build Coastguard Worker apisigs = OrderedDict() 63*1cddb830SAndroid Build Coastguard Worker ApiSignature = namedtuple('ApiSignature', 'Name RetType Params Suffix') 64*1cddb830SAndroid Build Coastguard Worker ApiParam = namedtuple('ApiParam', 'Type TypeEnd Name') 65*1cddb830SAndroid Build Coastguard Worker print('Generating API signatures dictionary...') 66*1cddb830SAndroid Build Coastguard Worker for command in spec.findall('commands/command'): 67*1cddb830SAndroid Build Coastguard Worker suffix = noneStr(command.get('suffix')) 68*1cddb830SAndroid Build Coastguard Worker proto = command.find('proto') 69*1cddb830SAndroid Build Coastguard Worker ret = noneStr(proto.text) 70*1cddb830SAndroid Build Coastguard Worker name = "" 71*1cddb830SAndroid Build Coastguard Worker params = "" 72*1cddb830SAndroid Build Coastguard Worker for elem in proto: 73*1cddb830SAndroid Build Coastguard Worker if elem.tag == 'name': 74*1cddb830SAndroid Build Coastguard Worker name = noneStr(elem.text) + noneStr(elem.tail) 75*1cddb830SAndroid Build Coastguard Worker else: 76*1cddb830SAndroid Build Coastguard Worker ret = ret + noneStr(elem.text) + noneStr(elem.tail) 77*1cddb830SAndroid Build Coastguard Worker ret = ret.strip() 78*1cddb830SAndroid Build Coastguard Worker name = name.strip() 79*1cddb830SAndroid Build Coastguard Worker 80*1cddb830SAndroid Build Coastguard Worker plist = [] 81*1cddb830SAndroid Build Coastguard Worker for param in command.findall('param'): 82*1cddb830SAndroid Build Coastguard Worker ptype = noneStr(param.text) 83*1cddb830SAndroid Build Coastguard Worker ptypeend = "" 84*1cddb830SAndroid Build Coastguard Worker pname = "" 85*1cddb830SAndroid Build Coastguard Worker for elem in param: 86*1cddb830SAndroid Build Coastguard Worker if elem.tag == 'name': 87*1cddb830SAndroid Build Coastguard Worker pname = noneStr(elem.text) 88*1cddb830SAndroid Build Coastguard Worker ptypeend = noneStr(elem.tail) 89*1cddb830SAndroid Build Coastguard Worker else: 90*1cddb830SAndroid Build Coastguard Worker ptype = ptype + noneStr(elem.text) + noneStr(elem.tail) 91*1cddb830SAndroid Build Coastguard Worker ptype = ptype.strip() 92*1cddb830SAndroid Build Coastguard Worker ptypeend = ptypeend.strip() 93*1cddb830SAndroid Build Coastguard Worker pname = pname.strip() 94*1cddb830SAndroid Build Coastguard Worker plist.append(ApiParam(ptype, ptypeend, pname)) 95*1cddb830SAndroid Build Coastguard Worker 96*1cddb830SAndroid Build Coastguard Worker # For an empty parameter list (for e.g. clUnloadCompiler), add a single 97*1cddb830SAndroid Build Coastguard Worker # unnamed void parameter to make generation easier. 98*1cddb830SAndroid Build Coastguard Worker if len(plist) == 0: 99*1cddb830SAndroid Build Coastguard Worker plist.append(ApiParam("void", "", "")) 100*1cddb830SAndroid Build Coastguard Worker 101*1cddb830SAndroid Build Coastguard Worker apisigs[name] = ApiSignature(name, ret, plist, suffix) 102*1cddb830SAndroid Build Coastguard Worker return apisigs 103*1cddb830SAndroid Build Coastguard Worker 104*1cddb830SAndroid Build Coastguard Workerdef get_apis(spec, apisigs): 105*1cddb830SAndroid Build Coastguard Worker # Generate the core API dictionary: 106*1cddb830SAndroid Build Coastguard Worker coreapis = OrderedDict() 107*1cddb830SAndroid Build Coastguard Worker print('Generating core API dictionary...') 108*1cddb830SAndroid Build Coastguard Worker for feature in spec.findall('feature'): 109*1cddb830SAndroid Build Coastguard Worker version = noneStr(feature.get('name')) 110*1cddb830SAndroid Build Coastguard Worker 111*1cddb830SAndroid Build Coastguard Worker alist = [] 112*1cddb830SAndroid Build Coastguard Worker for function in feature.findall('require/command'): 113*1cddb830SAndroid Build Coastguard Worker name = function.get('name') 114*1cddb830SAndroid Build Coastguard Worker alist.append(apisigs[name]) 115*1cddb830SAndroid Build Coastguard Worker coreapis[version] = alist 116*1cddb830SAndroid Build Coastguard Worker 117*1cddb830SAndroid Build Coastguard Worker # Generate the extensions API dictionary: 118*1cddb830SAndroid Build Coastguard Worker extapis = OrderedDict() 119*1cddb830SAndroid Build Coastguard Worker print('Generating API extensions dictionary...') 120*1cddb830SAndroid Build Coastguard Worker for feature in spec.findall('extensions/extension'): 121*1cddb830SAndroid Build Coastguard Worker extension = noneStr(feature.get('name')) 122*1cddb830SAndroid Build Coastguard Worker 123*1cddb830SAndroid Build Coastguard Worker alist = [] 124*1cddb830SAndroid Build Coastguard Worker for function in feature.findall('require/command'): 125*1cddb830SAndroid Build Coastguard Worker name = function.get('name') 126*1cddb830SAndroid Build Coastguard Worker alist.append(apisigs[name]) 127*1cddb830SAndroid Build Coastguard Worker extapis[extension] = alist 128*1cddb830SAndroid Build Coastguard Worker return (coreapis, extapis) 129*1cddb830SAndroid Build Coastguard Worker 130*1cddb830SAndroid Build Coastguard Worker 131