]> git.tdb.fi Git - libs/gl.git/blobdiff - scripts/extgen.py
Migrate to the new XML-based OpenGL API registry
[libs/gl.git] / scripts / extgen.py
index d6727123d97cb842a5836ea1b7d2f4a901396962..3cd2f5728f3b3d2019f17a0c9171eb230b85c454 100755 (executable)
@@ -1,6 +1,9 @@
 #!/usr/bin/python
 
 import sys
+import os
+import xml.dom
+import xml.dom.minidom
 
 if len(sys.argv)<2:
        print """Usage:
@@ -13,16 +16,38 @@ given to override the version where <extension> was promoted to core."""
        sys.exit(0)
 
 ext = sys.argv[1]
+out_base = None
+if ext.endswith(".glext"):
+       fn = ext
+       ext = None
+       ver = None
+       secondary = []
+       for line in open(fn):
+               parts = line.split()
+               if parts[0]=="extension":
+                       ext = parts[1]
+               elif parts[0]=="core_version":
+                       ver = 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
+       if secondary and secondary[0][0].isdigit():
+               ver = secondary.pop(0)
+
 exttype = ext.split('_')[0]
-secondary = sys.argv[2:]
-ver = None
-if secondary and secondary[0][0].isdigit():
-       ver = secondary.pop(0)
 bp_ext = None
 
+if not out_base:
+       out_base = ext.lower()
+
 class Function:
        def __init__(self, name):
                self.name = name
+               self.typedef = None
                self.version = None
                self.category = None
                self.vectorequiv = None
@@ -32,48 +57,87 @@ class Function:
 funcs = {}
 cur_func = None
 
-def parse_file(fn):
-       for line in open(fn):
-               if line[0]=='#' or line.find(':')>=0:
-                       continue
-               elif line[0]=='\t':
-                       if cur_func:
-                               parts = line.split()
-                               if parts[0]=="category":
-                                       cur_func.category = parts[1]
-                               elif parts[0]=="vectorequiv":
-                                       cur_func.vectorequiv = parts[1]
-                               elif parts[0]=="alias":
-                                       cur_func.aliases.append(parts[1])
-                               elif parts[0]=="version":
-                                       cur_func.version = parts[1]
-                               elif parts[0]=="delete":
-                                       del funcs[cur_func.name]
-                                       cur_func = None
+def get_nested_elements(elem, path):
+       if '/' in path:
+               head, tail = path.split('/', 1)
+               result = []
+               for e in elem.getElementsByTagName(head):
+                       result += get_nested_elements(e, tail)
+               return result
+       else:
+               return elem.getElementsByTagName(path)
+
+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:
-                       paren = line.find('(')
-                       if paren>0:
-                               name = line[:paren]
-                               if name in funcs:
-                                       cur_func = funcs[name]
-                               else:
-                                       cur_func = Function(name)
-                                       funcs[name] = cur_func
-
-parse_file("gl.spec")
-parse_file("gl.spec.fixes")
+                       result += get_text_contents(c)
+       return result
+
+def parse_file(fn):
+       doc = xml.dom.minidom.parse(fn)
+       root = doc.documentElement
+       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)
+               if not func:
+                       func = Function(name)
+                       funcs[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")
+
+       features = root.getElementsByTagName("feature")
+       for feat in features:
+               api = feat.getAttribute("api")
+               if api=="gl":
+                       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
+
+                       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]
+
+       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")
+                       for c in commands:
+                               name = c.getAttribute("name")
+                               func = funcs.get(name)
+                               if func:
+                                       func.category = ext_name
+
+parse_file("gl.xml")
+parse_file("gl.fixes.xml")
 
 for f in funcs.itervalues():
        if f.category==ext or f.category in secondary:
-               if not f.aliases and f.vectorequiv:
-                       for g in funcs.itervalues():
-                               if g!=f and g.vectorequiv==f.vectorequiv and f.name.startswith(g.name):
-                                       f.aliases.append(g.name)
-                                       break
-
                for a in f.aliases:
-                       if a in funcs:
-                               funcs[a].extfunc = f
+                       aliasfunc = funcs.get(a)
+                       if aliasfunc:
+                               aliasfunc.extfunc = f
 
 def is_relevant(f):
        if f.category==ext and not f.aliases:
@@ -88,25 +152,27 @@ funcs = [f for f in funcs.itervalues() if is_relevant(f)]
 funcs.sort(key=(lambda f: f.name))
 
 for f in funcs:
-       if f.extfunc:
-               if not ver:
-                       ver = f.version
-               if not f.category.startswith("VERSION_"):
-                       bp_ext = f.category
-       if not f.extfunc and not f.name.endswith(exttype):
+       if not ver:
+               ver = f.version
+
+       if f.category and not f.name.endswith(exttype):
                bp_ext = f.category
 
+       if f.extfunc:
+               f.typedef = "PFN%sPROC"%f.extfunc.name.upper()
+       else:
+               f.typedef = "PFN%sPROC"%f.name.upper()
+
 if ver:
        ver = map(int, ver.split('.'))
 
-out = file(ext.lower()+".h", "w")
+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("""
-#include "extension.h"
-#include "gl.h"
-#include <GL/glext.h>
+#include <msp/gl/extension.h>
+#include <msp/gl/gl.h>
 
 namespace Msp {
 namespace GL {
@@ -115,7 +181,7 @@ namespace GL {
 if funcs:
        out.write("\n")
 for f in funcs:
-       out.write("extern PFNGL%sPROC gl%s;\n"%(f.name.upper(), f.name))
+       out.write("extern %s %s;\n"%(f.typedef, f.name))
 
 out.write("\nextern Extension %s;\n"%ext)
 
@@ -126,7 +192,7 @@ out.write("""
 #endif
 """)
 
-out = file(ext.lower()+".cpp", "w")
+out = file(out_base+".cpp", "w")
 out.write("#include \"%s.h\"\n"%ext.lower())
 
 out.write("""
@@ -137,7 +203,7 @@ namespace GL {
 if funcs:
        out.write("\n")
 for f in funcs:
-       out.write("PFNGL%sPROC gl%s = 0;\n"%(f.name.upper(), f.name))
+       out.write("%s %s = 0;\n"%(f.typedef, f.name))
 
 out.write("\nExtension::SupportLevel init_%s()\n{\n"%ext.lower())
 if ver:
@@ -146,7 +212,7 @@ if ver:
                out.write(" || is_supported(\"GL_%s\")"%bp_ext)
        out.write(")\n\t{\n")
        for f in funcs:
-               out.write("\t\tgl%s = reinterpret_cast<PFNGL%sPROC>(get_proc_address(\"gl%s\"));\n"%(f.name, f.name.upper(), f.name))
+               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:
@@ -155,7 +221,7 @@ if ext!=bp_ext:
                n = f.name
                if f.extfunc:
                        n = f.extfunc.name
-               out.write("\t\tgl%s = reinterpret_cast<PFNGL%sPROC>(get_proc_address(\"gl%s\"));\n"%(f.name, f.name.upper(), n))
+               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("\treturn Extension::UNSUPPORTED;\n")