+### Command line processing ###
+
+if len(sys.argv)<2:
+ print """Usage:
+ extgen.py [api] <extension> [<core_version>] [<secondary> ...]
+ extgen.py [api] <extfile> [<outfile>]
+
+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. <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)
+
+target_api = "gl"
+
+i = 1
+if sys.argv[i].startswith("gl"):
+ target_api = sys.argv[i]
+ i += 1
+
+target_ext = sys.argv[i]
+out_base = 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":
+ target_ext = parts[1]
+ elif parts[0]=="core_version":
+ if parts[1]==target_api:
+ core_version = parts[2]
+ elif parts[0]=="secondary":
+ secondary.append(parts[1])
+ if i+1<len(sys.argv):
+ out_base = os.path.splitext(sys.argv[i+1])[0]
+else:
+ secondary = sys.argv[i+1:]
+ core_version = None
+ if secondary and secondary[0][0].isdigit():
+ core_version = secondary.pop(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 = target_ext.lower()
+
+### XML file parsing ###
+
+class Thing:
+ FUNCTION = 1
+ ENUM = 2
+
+ def __init__(self, name, kind):
+ self.name = name
+ self.kind = kind
+ self.version = None
+ self.extension = None
+ self.supported_apis = {}
+ self.aliases = []
+ self.sources = []
+
+class Function(Thing):
+ def __init__(self, name):
+ Thing.__init__(self, name, Thing.FUNCTION)
+ self.return_type = "void"
+ self.params = []
+ self.typedef = None
+
+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('.'))