in <outfile> is removed and replaced with cpp and h."""
sys.exit(0)
-ext = sys.argv[1]
+target_ext = sys.argv[1]
out_base = None
-if ext.endswith(".glext"):
- fn = ext
- ext = None
- ver = None
+if target_ext.endswith(".glext"):
+ fn = target_ext
+ target_ext = None
+ core_version = None
secondary = []
for line in open(fn):
parts = line.split()
if parts[0]=="extension":
- ext = parts[1]
+ target_ext = parts[1]
elif parts[0]=="core_version":
- ver = parts[1]
+ core_version = parts[1]
elif parts[0]=="secondary":
secondary.append(parts[1])
if len(sys.argv)>=3:
out_base = os.path.splitext(sys.argv[2])[0]
else:
secondary = sys.argv[2:]
- ver = None
+ core_version = None
if secondary and secondary[0][0].isdigit():
- ver = secondary.pop(0)
+ core_version = secondary.pop(0)
-exttype = ext.split('_')[0]
+ext_type = target_ext.split('_')[0]
backport_ext = None
+if core_version:
+ core_version = map(int, core_version.split('.'))
+
if not out_base:
- out_base = ext.lower()
+ out_base = target_ext.lower()
### XML file parsing ###
self.return_type = "void"
self.params = []
self.typedef = None
- self.vectorequiv = None
class Enum(Thing):
def __init__(self, name):
things = {}
def get_nested_elements(elem, path):
+ childElements = [c for c in elem.childNodes if c.nodeType==xml.dom.Node.ELEMENT_NODE]
if '/' in path:
head, tail = path.split('/', 1)
result = []
- for e in elem.getElementsByTagName(head):
- result += get_nested_elements(e, tail)
+ for c in childElements:
+ if c.tagName==head:
+ result += get_nested_elements(c, tail)
return result
else:
- return elem.getElementsByTagName(path)
+ return [c for c in childElements if c.tagName==path]
+
+def get_first_child(elem, tag):
+ for c in elem.childNodes:
+ if c.nodeType==xml.dom.Node.ELEMENT_NODE and c.tagName==tag:
+ return c
+ return None
def get_text_contents(node):
result = ""
result += get_text_contents(c)
return result
+def parse_command(cmd):
+ proto = get_first_child(cmd, "proto")
+ name = get_text_contents(get_first_child(proto, "name"))
+ func = things.get(name)
+ if not func:
+ func = Function(name)
+ things[name] = func
+
+ aliases = get_nested_elements(cmd, "alias")
+ func.aliases = [a.getAttribute("name") for a in aliases]
+
+ ptype = get_first_child(proto, "ptype")
+ if ptype:
+ func.return_type = get_text_contents(ptype)
+ else:
+ for c in proto.childNodes:
+ if c.nodeType==xml.dom.Node.TEXT_NODE and c.data.strip():
+ func.return_type = c.data.strip()
+ break
+
+ params = get_nested_elements(cmd, "param")
+ func.params = map(get_text_contents, params)
+
+def parse_enum(en):
+ name = en.getAttribute("name")
+ enum = things.get(name)
+ if not enum:
+ enum = Enum(name)
+ things[name] = enum
+
+ enum.value = int(en.getAttribute("value"), 16)
+
+def parse_feature(feat):
+ api = feat.getAttribute("api")
+ if api=="gl":
+ version = feat.getAttribute("number")
+ if version:
+ version = map(int, version.split('.'))
+ else:
+ version = None
+
+ commands = get_nested_elements(feat, "require/command")
+ 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")
+ enums = get_nested_elements(feat, "remove/enum")
+ for t in itertools.chain(commands, enums):
+ name = t.getAttribute("name")
+ if name in things:
+ del things[name]
+
+def parse_extension(ext):
+ ext_name = ext.getAttribute("name")
+ if ext_name.startswith("GL_"):
+ ext_name = ext_name[3:]
+
+ supported = ext.getAttribute("supported").split('|')
+ if "gl" in supported:
+ commands = get_nested_elements(ext, "require/command")
+ 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
+
def parse_file(fn):
doc = xml.dom.minidom.parse(fn)
root = doc.documentElement
+
commands = get_nested_elements(root, "commands/command")
for cmd in commands:
- proto = cmd.getElementsByTagName("proto")[0]
- name = get_text_contents(proto.getElementsByTagName("name")[0])
- func = things.get(name)
- if not func:
- func = Function(name)
- things[name] = func
-
- aliases = cmd.getElementsByTagName("alias")
- for a in aliases:
- func.aliases.append(a.getAttribute("name"))
-
- vec = cmd.getElementsByTagName("vecequiv")
- if vec:
- func.vectorequiv = vec[0].getAttribute("name")
-
- ptype = proto.getElementsByTagName("ptype")
- if ptype:
- func.return_type = get_text_contents(ptype[0])
- else:
- for c in proto.childNodes:
- if c.nodeType==xml.dom.Node.TEXT_NODE and c.data.strip():
- func.return_type = c.data.strip()
- break
-
- params = cmd.getElementsByTagName("param")
- for p in params:
- func.params.append(get_text_contents(p))
+ parse_command(cmd)
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
+ parse_enum(en)
- enum.value = int(en.getAttribute("value"), 16)
-
- features = root.getElementsByTagName("feature")
+ features = get_nested_elements(root, "feature")
for feat in features:
- api = feat.getAttribute("api")
- if api=="gl":
- version = feat.getAttribute("number")
-
- commands = get_nested_elements(feat, "require/command")
- 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")
- 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]
+ parse_feature(feat)
extensions = get_nested_elements(root, "extensions/extension")
for ext in extensions:
- ext_name = ext.getAttribute("name")
- if ext_name.startswith("GL_"):
- ext_name = ext_name[3:]
- supported = ext.getAttribute("supported").split('|')
- if "gl" in supported:
- commands = get_nested_elements(ext, "require/command")
- 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_extension(ext)
parse_file("gl.xml")
parse_file("gl.fixes.xml")
# Create references from core things to their extension counterparts
for t in things.itervalues():
- if t.extension==ext or t.extension in secondary:
+ if t.extension==target_ext or t.extension in secondary:
for a in t.aliases:
alias = things.get(a)
if alias:
def is_relevant(t):
# Unpromoted extension things are relevant
- if t.extension==ext and not t.aliases:
+ if t.extension==target_ext and not t.aliases:
return True
# Core things promoted from the extension are also relevant
if t.source:
e = t.source
- if e.extension==ext or e.extension in secondary:
+ if e.extension==target_ext or e.extension in secondary:
return True
return False
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 = filter(is_relevant, enums)
enums.sort(key=(lambda e: e.value))
for t in itertools.chain(funcs, enums):
- if not ver:
- ver = t.version
+ if not core_version:
+ core_version = t.version
# Things in backport extensions don't acquire an extension suffix
- if t.extension and not t.name.endswith(exttype):
+ if t.extension and not t.name.endswith(ext_type):
backport_ext = t.extension
for f in funcs:
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("#ifndef MSP_GL_%s_\n"%target_ext.upper())
+out.write("#define MSP_GL_%s_\n"%target_ext.upper())
out.write("""
#include <msp/gl/extension.h>
if funcs or enums:
if funcs:
- out.write("#if defined(__APPLE__) || !defined(GL_%s)\n"%ext)
+ out.write("#if defined(__APPLE__) || !defined(GL_%s)\n"%target_ext)
for f in funcs:
out.write("typedef %s (*%s)(%s);\n"%(f.return_type, f.typedef, ", ".join(f.params)))
out.write("#endif\n\n")
if enums:
- if ver:
- out.write("#ifndef GL_VERSION_%s\n"%"_".join(map(str, ver)))
+ if core_version:
+ out.write("#ifndef GL_VERSION_%s\n"%"_".join(map(str, core_version)))
else:
- out.write("#ifndef GL_%s\n"%ext)
+ out.write("#ifndef GL_%s\n"%target_ext)
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("extern Extension %s;\n"%ext)
+out.write("extern Extension %s;\n"%target_ext)
out.write("""
} // namespace GL
""")
out = file(out_base+".cpp", "w")
-out.write("#include \"%s.h\"\n"%ext.lower())
+out.write("#include \"%s.h\"\n"%target_ext.lower())
-out.write("""
+if funcs:
+ out.write("""
#ifdef __APPLE__
#define GET_PROC_ADDRESS(x) ::x
#else
#define GET_PROC_ADDRESS(x) get_proc_address(#x)
#endif
-
+""")
+out.write("""
namespace Msp {
namespace GL {
for f in funcs:
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))
+out.write("\nExtension::SupportLevel init_%s()\n{\n"%target_ext.lower())
+out.write("#ifdef GL_%s\n"%target_ext)
+if core_version:
+ out.write("\tif(is_version_at_least(%d, %d)"%tuple(core_version))
if backport_ext:
out.write(" || is_supported(\"GL_%s\")"%backport_ext)
out.write(")\n\t{\n")
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!=backport_ext:
- out.write("\tif(is_supported(\"GL_%s\"))\n\t{\n"%(ext))
+if target_ext!=backport_ext:
+ out.write("\tif(is_supported(\"GL_%s\"))\n\t{\n"%(target_ext))
if funcs:
for f in funcs:
n = f.name
out.write("\treturn Extension::UNSUPPORTED;\n")
out.write("}\n")
-out.write("\nExtension %s(\"GL_%s\", init_%s);\n"%(ext, ext, ext.lower()))
+out.write("\nExtension %s(\"GL_%s\", init_%s);\n"%(target_ext, target_ext, target_ext.lower()))
out.write("""
} // namespace GL