import xml.dom
import xml.dom.minidom
+### Command line processing ###
+
if len(sys.argv)<2:
print """Usage:
- extgen.py <extension> [<version>] [<secondary> ...]"
+ extgen.py <extension> [<core_version>] [<secondary> ...]
+ extgen.py <extfile> [<outfile>]
-Reads gl.spec and generates files to use <extension>. Any promoted functions
+Reads gl.xml and generates files to use <extension>. Any promoted functions
are exposed with their promoted names. If <secondary> extensions are given,
-any promoted functions from those are pulled in as well. <version> can be
-given to override the version where <extension> was promoted to core."""
+any promoted functions from those are pulled in as well. <core_version> can
+be given to override the version where <extension> was promoted to core.
+
+In the second form, the parameters are read from <extfile>. If <outfile> is
+absent, the extension's lowercased name is used. Anything after the last dot
+in <outfile> is removed and replaced with cpp and h."""
sys.exit(0)
ext = sys.argv[1]
ver = secondary.pop(0)
exttype = ext.split('_')[0]
-bp_ext = None
+backport_ext = None
if not out_base:
out_base = ext.lower()
+### XML file parsing ###
+
class Function:
def __init__(self, name):
self.name = name
self.typedef = None
self.version = None
- self.category = None
+ self.extension = None
self.vectorequiv = None
self.aliases = []
self.extfunc = None
funcs = {}
-cur_func = None
def get_nested_elements(elem, path):
if '/' in path:
name = c.getAttribute("name")
func = funcs.get(name)
if func:
- func.category = ext_name
+ func.extension = ext_name
parse_file("gl.xml")
parse_file("gl.fixes.xml")
+### Additional processing ###
+
+# Create references from core functions to their extension counterparts
for f in funcs.itervalues():
- if f.category==ext or f.category in secondary:
+ if f.extension==ext or f.extension in secondary:
for a in f.aliases:
aliasfunc = funcs.get(a)
if aliasfunc:
aliasfunc.extfunc = f
def is_relevant(f):
- if f.category==ext and not f.aliases:
+ # Unpromoted extension functions are relevant
+ if f.extension==ext and not f.aliases:
return True
+
+ # Core functions promoted from the extension are also relevant
if f.extfunc:
e = f.extfunc
- if e.category==ext or e.category in secondary:
+ if e.extension==ext or e.extension in secondary:
return True
+
return False
funcs = [f for f in funcs.itervalues() if is_relevant(f)]
if not ver:
ver = f.version
- if f.category and not f.name.endswith(exttype):
- bp_ext = f.category
+ # Functions in backport extensions don't acquire an extension suffix
+ if f.extension and not f.name.endswith(exttype):
+ backport_ext = f.extension
if f.extfunc:
+ # Typedefs for early core functions are not available in all
+ # implementations
f.typedef = "PFN%sPROC"%f.extfunc.name.upper()
else:
f.typedef = "PFN%sPROC"%f.name.upper()
if ver:
ver = map(int, ver.split('.'))
+### Output ###
+
out = file(out_base+".h", "w")
out.write("#ifndef MSP_GL_%s_\n"%ext.upper())
out.write("#define MSP_GL_%s_\n"%ext.upper())
out.write("\nExtension::SupportLevel init_%s()\n{\n"%ext.lower())
if ver:
out.write("\tif(is_version_at_least(%d, %d)"%tuple(ver))
- if bp_ext:
- out.write(" || is_supported(\"GL_%s\")"%bp_ext)
+ if backport_ext:
+ out.write(" || is_supported(\"GL_%s\")"%backport_ext)
out.write(")\n\t{\n")
for f in funcs:
out.write("\t\t%s = reinterpret_cast<%s>(get_proc_address(\"%s\"));\n"%(f.name, f.typedef, f.name))
out.write("\t\treturn Extension::CORE;\n")
out.write("\t}\n")
-if ext!=bp_ext:
+if ext!=backport_ext:
out.write("\tif(is_supported(\"GL_%s\"))\n\t{\n"%(ext))
for f in funcs:
n = f.name