import os
import xml.dom
import xml.dom.minidom
+import itertools
### Command line processing ###
### XML file parsing ###
-class Function:
- def __init__(self, name):
+class Thing:
+ FUNCTION = 1
+ ENUM = 2
+
+ def __init__(self, name, kind):
self.name = name
- self.typedef = None
+ self.kind = kind
self.version = None
self.extension = None
- self.vectorequiv = None
self.aliases = []
- self.extfunc = None
+ self.source = None
+
+class Function(Thing):
+ def __init__(self, name):
+ Thing.__init__(self, name, Thing.FUNCTION)
+ self.typedef = None
+ self.vectorequiv = None
+
+class Enum(Thing):
+ def __init__(self, name):
+ Thing.__init__(self, name, Thing.ENUM)
+ self.value = 0
-funcs = {}
+things = {}
def get_nested_elements(elem, path):
if '/' in path:
commands = get_nested_elements(root, "commands/command")
for cmd in commands:
name = get_text_contents(get_nested_elements(cmd, "proto/name")[0])
- func = funcs.get(name)
+ func = things.get(name)
if not func:
func = Function(name)
- funcs[name] = func
+ things[name] = func
aliases = cmd.getElementsByTagName("alias")
for a in aliases:
if vec:
func.vectorequiv = vec[0].getAttribute("name")
+ enums = get_nested_elements(root, "enums/enum")
+ for en in enums:
+ name = en.getAttribute("name")
+ enum = things.get(name)
+ if not enum:
+ enum = Enum(name)
+ things[name] = enum
+
+ enum.value = int(en.getAttribute("value"), 16)
+
features = root.getElementsByTagName("feature")
for feat in features:
api = feat.getAttribute("api")
version = feat.getAttribute("number")
commands = get_nested_elements(feat, "require/command")
- for c in commands:
- name = c.getAttribute("name")
- func = funcs.get(name)
- if func:
- func.version = version
+ enums = get_nested_elements(feat, "require/enum")
+ for t in itertools.chain(commands, enums):
+ name = t.getAttribute("name")
+ thing = things.get(name)
+ if thing:
+ thing.version = version
if feat.getAttribute("name")=="MSPGL_REMOVE":
commands = get_nested_elements(feat, "remove/command")
- for c in commands:
- name = c.getAttribute("name")
- if name in funcs:
- del funcs[name]
+ enums = get_nested_elements(feat, "require/enum")
+ for t in itertools.chain(commands, enums):
+ name = t.getAttribute("name")
+ if name in things:
+ del things[name]
extensions = get_nested_elements(root, "extensions/extension")
for ext in extensions:
supported = ext.getAttribute("supported").split('|')
if "gl" in supported:
commands = get_nested_elements(ext, "require/command")
- for c in commands:
- name = c.getAttribute("name")
- func = funcs.get(name)
- if func:
- func.extension = ext_name
+ enums = get_nested_elements(ext, "require/enum")
+ for t in itertools.chain(commands, enums):
+ name = t.getAttribute("name")
+ thing = things.get(name)
+ if thing:
+ thing.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.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):
- # Unpromoted extension functions are relevant
- if f.extension==ext and not f.aliases:
+# Find aliases for enums
+enums = [t for t in things.itervalues() if t.kind==Thing.ENUM]
+core_enums_by_value = dict((e.value, e) for e in enums if e.version)
+
+for e in enums:
+ if e.kind==t.ENUM and e.extension:
+ ce = core_enums_by_value.get(e.value)
+ if ce and ce!=e:
+ e.aliases.append(ce.name)
+
+# Create references from core things to their extension counterparts
+for t in things.itervalues():
+ if t.extension==ext or t.extension in secondary:
+ for a in t.aliases:
+ alias = things.get(a)
+ if alias:
+ alias.source = t
+
+def is_relevant(t):
+ # Unpromoted extension things are relevant
+ if t.extension==ext and not t.aliases:
return True
- # Core functions promoted from the extension are also relevant
- if f.extfunc:
- e = f.extfunc
+ # Core things promoted from the extension are also relevant
+ if t.source:
+ e = t.source
if e.extension==ext or e.extension in secondary:
return True
return False
-funcs = [f for f in funcs.itervalues() if is_relevant(f)]
+funcs = [t for t in things.itervalues() if t.kind==Thing.FUNCTION and is_relevant(t)]
funcs.sort(key=(lambda f: f.name))
+enums = [e for e in enums if is_relevant(e)]
+enums.sort(key=(lambda e: e.value))
-for f in funcs:
+for t in itertools.chain(funcs, enums):
if not ver:
- ver = f.version
+ ver = t.version
- # Functions in backport extensions don't acquire an extension suffix
- if f.extension and not f.name.endswith(exttype):
- backport_ext = f.extension
+ # Things in backport extensions don't acquire an extension suffix
+ if t.extension and not t.name.endswith(exttype):
+ backport_ext = t.extension
- if f.extfunc:
+for f in funcs:
+ if f.source:
# Typedefs for early core functions are not available in all
# implementations
- f.typedef = "PFN%sPROC"%f.extfunc.name.upper()
+ f.typedef = "PFN%sPROC"%f.source.name.upper()
else:
f.typedef = "PFN%sPROC"%f.name.upper()
namespace GL {
""")
-if funcs:
- out.write("\n")
-for f in funcs:
- out.write("extern %s %s;\n"%(f.typedef, f.name))
+if funcs or enums:
+ out.write("\n#ifndef GL_%s\n"%ext)
+ for f in funcs:
+ out.write("typedef int (*%s)(...);\n"%f.typedef)
+ if funcs and enums:
+ out.write("\n")
+ for e in enums:
+ out.write("#define %s 0x%04X\n"%(e.name, e.value))
+ out.write("#endif\n\n")
+ for f in funcs:
+ out.write("extern %s %s;\n"%(f.typedef, f.name))
out.write("\nextern Extension %s;\n"%ext)
out.write("%s %s = 0;\n"%(f.typedef, f.name))
out.write("\nExtension::SupportLevel init_%s()\n{\n"%ext.lower())
+out.write("#ifdef GL_%s\n"%ext)
if ver:
out.write("\tif(is_version_at_least(%d, %d)"%tuple(ver))
if backport_ext:
out.write("\tif(is_supported(\"GL_%s\"))\n\t{\n"%(ext))
for f in funcs:
n = f.name
- if f.extfunc:
- n = f.extfunc.name
+ if f.source:
+ n = f.source.name
out.write("\t\t%s = reinterpret_cast<%s>(get_proc_address(\"%s\"));\n"%(f.name, f.typedef, n))
out.write("\t\treturn Extension::EXTENSION;\n")
out.write("\t}\n")
+out.write("#endif\n")
out.write("\treturn Extension::UNSUPPORTED;\n")
out.write("}\n")