| # Copyright (c) 2020 The Khronos Group Inc. |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); |
| # you may not use this file except in compliance with the License. |
| # You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| |
| from collections import OrderedDict |
| from collections import namedtuple |
| |
| import argparse |
| import sys |
| import urllib |
| import xml.etree.ElementTree as etree |
| import urllib.request |
| |
| # parse_xml - Helper function to parse the XML file from a URL or local file. |
| def parse_xml(path): |
| file = urllib.request.urlopen(path) if path.startswith("http") else open(path, 'r') |
| with file: |
| tree = etree.parse(file) |
| return tree |
| |
| # noneStr - returns string argument, or "" if argument is None. |
| def noneStr(s): |
| if s: |
| return s |
| return "" |
| |
| def parse_args(): |
| parser = argparse.ArgumentParser() |
| |
| # To pull the latest registry file from GitHub, pass: |
| # -registry "https://raw.githubusercontent.com/KhronosGroup/OpenCL-Registry/master/xml/cl.xml" |
| |
| parser.add_argument('-registry', action='store', |
| default='cl.xml', |
| help='Use specified registry file instead of cl.xml') |
| parser.add_argument('-o', action='store', dest='directory', |
| default='.', |
| help='Create target and related files in specified directory') |
| |
| args = parser.parse_args() |
| return args |
| |
| def load_spec(args): |
| specpath = args.registry |
| |
| print('Parsing XML file from: ' + specpath) |
| spec = parse_xml(specpath) |
| return spec |
| |
| def get_apisigs(spec): |
| # Generate the API function signatures dictionary: |
| apisigs = OrderedDict() |
| ApiSignature = namedtuple('ApiSignature', 'Name RetType Params Suffix') |
| ApiParam = namedtuple('ApiParam', 'Type TypeEnd Name') |
| print('Generating API signatures dictionary...') |
| for command in spec.findall('commands/command'): |
| suffix = noneStr(command.get('suffix')) |
| proto = command.find('proto') |
| ret = noneStr(proto.text) |
| name = "" |
| params = "" |
| for elem in proto: |
| if elem.tag == 'name': |
| name = noneStr(elem.text) + noneStr(elem.tail) |
| else: |
| ret = ret + noneStr(elem.text) + noneStr(elem.tail) |
| ret = ret.strip() |
| name = name.strip() |
| |
| plist = [] |
| for param in command.findall('param'): |
| ptype = noneStr(param.text) |
| ptypeend = "" |
| pname = "" |
| for elem in param: |
| if elem.tag == 'name': |
| pname = noneStr(elem.text) |
| ptypeend = noneStr(elem.tail) |
| else: |
| ptype = ptype + noneStr(elem.text) + noneStr(elem.tail) |
| ptype = ptype.strip() |
| ptypeend = ptypeend.strip() |
| pname = pname.strip() |
| plist.append(ApiParam(ptype, ptypeend, pname)) |
| |
| # For an empty parameter list (for e.g. clUnloadCompiler), add a single |
| # unnamed void parameter to make generation easier. |
| if len(plist) == 0: |
| plist.append(ApiParam("void", "", "")) |
| |
| apisigs[name] = ApiSignature(name, ret, plist, suffix) |
| return apisigs |
| |
| def get_apis(spec, apisigs): |
| # Generate the core API dictionary: |
| coreapis = OrderedDict() |
| print('Generating core API dictionary...') |
| for feature in spec.findall('feature'): |
| version = noneStr(feature.get('name')) |
| |
| alist = [] |
| for function in feature.findall('require/command'): |
| name = function.get('name') |
| alist.append(apisigs[name]) |
| coreapis[version] = alist |
| |
| # Generate the extensions API dictionary: |
| extapis = OrderedDict() |
| print('Generating API extensions dictionary...') |
| for feature in spec.findall('extensions/extension'): |
| extension = noneStr(feature.get('name')) |
| |
| alist = [] |
| for function in feature.findall('require/command'): |
| name = function.get('name') |
| alist.append(apisigs[name]) |
| extapis[extension] = alist |
| return (coreapis, extapis) |
| |
| |