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