+class Enum(Thing):
+ def __init__(self, name):
+ Thing.__init__(self, name, Thing.ENUM)
+ self.value = 0
+ self.bitmask = (name.endswith("_BIT") or "_BIT_" in name)
+
+class Extension:
+ def __init__(self, name):
+ self.name = name
+ self.supported_apis = []
+ self.ext_type = name[0:name.find('_')]
+
+extensions = {}
+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 c in childElements:
+ if c.tagName==head:
+ result += get_nested_elements(c, tail)
+ return result
+ else:
+ 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 = ""
+ for c in node.childNodes:
+ if c.nodeType==xml.dom.Node.TEXT_NODE or c.nodeType==xml.dom.Node.CDATA_SECTION_NODE:
+ result += c.data
+ else:
+ 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")
+ version = feat.getAttribute("number")
+ if version:
+ version = map(int, version.split('.'))
+ else:
+ version = None
+
+ requires = get_nested_elements(feat, "require")
+ for req in requires:
+ commands = get_nested_elements(req, "command")
+ enums = get_nested_elements(req, "enum")
+ for t in itertools.chain(commands, enums):
+ name = t.getAttribute("name")
+ thing = things.get(name)
+ if thing:
+ thing.supported_apis.setdefault(api, version)
+
+ if not api or api==target_api:
+ removes = get_nested_elements(feat, "remove")
+ for rem in removes:
+ profile = rem.getAttribute("profile")
+ commands = get_nested_elements(rem, "command")
+ enums = get_nested_elements(rem, "enum")
+
+ for t in itertools.chain(commands, enums):
+ name = t.getAttribute("name")
+ if profile!="core" and 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 target_api not in supported and ext_name!=target_ext:
+ return
+
+ extension = extensions.get(ext_name)
+ if not extension:
+ extension = Extension(ext_name)
+ extensions[ext_name] = extension
+
+ extension.supported_apis = supported
+
+ requires = get_nested_elements(ext, "require")
+ for req in requires:
+ api = req.getAttribute("api")
+ if api:
+ supported = [api]