blob: 87ce758099261a2049a4dc93482851ab659570fd [file] [log] [blame] [edit]
#!/usr/bin/python3
# Copyright (c) 2019-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
import argparse
import sys
import os
import urllib
import xml.etree.ElementTree as etree
import urllib.request
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
# File Header:
def GetHeader():
return """// Copyright 2017-2020 The Khronos Group. This work is licensed under a
// Creative Commons Attribution 4.0 International License; see
// http://creativecommons.org/licenses/by/4.0/
"""
# File Footer:
def GetFooter():
return """
"""
def FullNote(name, added_in, deprecated_by):
# Four patterns: (1) always present in OpenCL, (2) added after 1.0, (3) in
# 1.0 but now deprecated, and (4) added after 1.0 but now deprecated.
if added_in == "1.0" and deprecated_by == None:
return "\n// Intentionally empty, %s has always been present." % name
if added_in != "1.0" and deprecated_by == None:
return "\nIMPORTANT: {%s} is <<unified-spec, missing before>> version %s." % (name, added_in)
if added_in == "1.0" and deprecated_by != None:
return "\nIMPORTANT: {%s} is <<unified-spec, deprecated by>> version %s." % (name, deprecated_by)
if added_in != "1.0" and deprecated_by != None:
return "\nIMPORTANT: {%s} is <<unified-spec, missing before>> version %s and <<unified-spec, deprecated by>> version %s." % (name, added_in, deprecated_by)
def ShortNote(name, added_in, deprecated_by):
# Four patterns: (1) always present in OpenCL, (2) added after 1.0, (3) in
# 1.0 but now deprecated, and (4) added after 1.0 but now deprecated.
if added_in == "1.0" and deprecated_by == None:
return "// Intentionally empty, %s has always been present." % name
if added_in != "1.0" and deprecated_by == None:
return "<<unified-spec, Missing before>> version %s." % added_in
if added_in == "1.0" and deprecated_by != None:
return "<<unified-spec, Deprecated by>> version %s." % deprecated_by
if added_in != "1.0" and deprecated_by != None:
return "<<unified-spec, Missing before>> version %s and <<unified-spec, deprecated by>> version %s." % (added_in, deprecated_by)
# Find feature groups that are parents of a feature/require/${entry_type}
# hierarchy, and then find all the ${entry_type} within each hierarchy:
def process_xml(spec, entry_type, note_printer):
numberOfEntries = 0
numberOfNewEntries = 0
numberOfDeprecatedEntries = 0
for feature in spec.findall('.//feature/require/%s/../..' % entry_type):
for entry in feature.findall('.//%s' % entry_type):
name = entry.get('name')
numberOfEntries += 1
added_in = feature.get('number')
deprecated_by = None
# All the groups that this specific API ${entry_type} belongs.
categories = spec.findall(
'.//require[@comment]/%s[@name="%s"]/..' % (entry_type, name))
for category in categories:
comment = category.get('comment')
if "deprecated in OpenCL" in comment:
words = comment.split(" ")
assert " ".join(words[-4:-1]) == "deprecated in OpenCL"
assert deprecated_by == None # Can't deprecate something twice.
deprecated_by = words[-1]
versionFileName = os.path.join(args.directory, name + ".asciidoc")
with open(versionFileName, 'w') as versionFile:
versionFile.write(GetHeader())
versionFile.write(note_printer(name, added_in, deprecated_by))
versionFile.write(GetFooter())
numberOfNewEntries += 0 if added_in == "1.0" else 1
numberOfDeprecatedEntries += 0 if deprecated_by == None else 1
print('Found ' + str(numberOfEntries) + ' API ' + entry_type + 's, '
+ str(numberOfNewEntries) + " newer than 1.0, "
+ str(numberOfDeprecatedEntries) + " are deprecated.")
if __name__ == "__main__":
parser = argparse.ArgumentParser()
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()
specpath = args.registry
print('Generating version notes from: ' + specpath)
spec = parse_xml(specpath)
# Generate the API functions dictionaries:
process_xml(spec, "command", FullNote)
process_xml(spec, "enum", ShortNote)