]> git.tdb.fi Git - libs/gl.git/commitdiff
Convert the extension generator script to Python 3
authorMikko Rasa <tdb@tdb.fi>
Sat, 9 Jan 2021 16:53:09 +0000 (18:53 +0200)
committerMikko Rasa <tdb@tdb.fi>
Sat, 9 Jan 2021 16:53:09 +0000 (18:53 +0200)
scripts/extgen.py

index 15ef167bfaf60c9d3de0a162e53b13f7150ace26..9c859c3336aabcf7936682a7fa71d1a3b518d557 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/python3
 
 import sys
 import os
@@ -16,16 +16,16 @@ class Version:
                        self.major = args[0]
                        self.minor = args[1]
                else:
-                       raise TypeError, "__init__() takes zero or two arguments (%d given)"%len(args)
+                       raise TypeError("__init__() takes zero or two arguments ({} given)".format(len(args)))
 
        def __str__(self):
-               return "%d.%d"%(self.major, self.minor)
+               return "{}.{}".format(self.major, self.minor)
 
        def __repr__(self):
-               return "Version(%d, %d)"%(self.major, self.minor)
+               return "Version({}, {})".format(self.major, self.minor)
 
        def as_define(self):
-               return "VERSION_%d_%d"%(self.major, self.minor)
+               return "VERSION_{}_{}".format(self.major, self.minor)
 
        def __lt__(self, other):
                if other is None:
@@ -43,6 +43,12 @@ class Version:
                        return self.major>other.major
                return self.minor>other.minor
 
+       def __le__(self, other):
+               return not self.__gt__(other)
+
+       def __ge__(self, other):
+               return not self.__lt__(other)
+
        def __eq__(self, other):
                if other is None:
                        return False
@@ -273,21 +279,20 @@ class GlXmlParser:
                        self.parse_extension(ext)
 
        def check_backport_extensions(self, api):
-               for e in api.extensions.itervalues():
+               for e in api.extensions.values():
                        if e.ext_type!="ARB":
                                continue
 
                        e.backport = True
-                       for t in e.things.itervalues():
+                       for t in e.things.values():
                                if t.name.endswith(e.ext_type):
                                        e.backport = False
                                        break
 
        def resolve_enum_aliases(self, api):
-               for e in api.extensions.itervalues():
-                       ext_enums = filter((lambda t: t.kind==Thing.ENUM), e.things.itervalues())
+               for e in api.extensions.values():
                        enum_suffix = "_"+e.ext_type
-                       for n in ext_enums:
+                       for n in (t for t in e.things.values() if t.kind==Thing.ENUM):
                                if n.api_support[api.name].core_version:
                                        continue
 
@@ -299,8 +304,8 @@ class GlXmlParser:
                                        n.aliases.append(ce.name)
 
        def resolve_sources(self, api):
-               for e in api.extensions.itervalues():
-                       for t in e.things.itervalues():
+               for e in api.extensions.values():
+                       for t in e.things.values():
                                for a in t.aliases:
                                        # There are a few cases where a vendor function is aliased to
                                        # an EXT or ARB function but those are rare and not relevant for
@@ -312,12 +317,12 @@ class GlXmlParser:
                                                        sources.append(t)
 
        def sort_extensions(self):
-               for t in self.things.itervalues():
-                       for s in t.api_support.itervalues():
+               for t in self.things.values():
+                       for s in t.api_support.values():
                                s.extensions.sort(key=(lambda e: e.preference), reverse=True)
 
        def finalize(self):
-               for a in self.apis.itervalues():
+               for a in self.apis.values():
                        self.check_backport_extensions(a)
                        self.resolve_enum_aliases(a)
                        self.resolve_sources(a)
@@ -344,14 +349,14 @@ def detect_core_version(host_api, things, debug=None):
                        missing.append(t)
 
        if lower_count>max_count or (missing and len(missing)*2<lower_count+max_count):
-               print "Warning: Inconsistent core version %s"%max_version
+               print("Warning: Inconsistent core version {}".format(max_version))
 
        if missing:
                if debug:
-                       print "---"
-                       print "%d things missing from core:"%len(missing)
+                       print("---")
+                       print("{} things missing from core:".format(len(missing)))
                        for t in missing:
-                               print "  "+t.name
+                               print("  "+t.name)
                return None
 
        return max_version
@@ -369,12 +374,12 @@ def detect_deprecated_version(host_api, things, debug):
                        deprecated.append(t)
 
        if min_version and len(deprecated)*2<len(things):
-               print "Warning: Inconsistent deprecation version %s"%min_version
+               print("Warning: Inconsistent deprecation version {}".format(min_version))
                if debug:
-                       print "---"
-                       print "%d things are deprecated:"%len(deprecated)
+                       print("---")
+                       print("{} things are deprecated:".format(len(deprecated)))
                        for t in deprecated:
-                               print "  "+t.name
+                               print("  "+t.name)
 
        return min_version
 
@@ -391,8 +396,7 @@ def detect_backport_extension(host_api, things):
        best_ext = None
        best_count = 0
        for e in candidates:
-               things_in_ext = filter((lambda t: t.name in e.things), things)
-               count = len(things_in_ext)
+               count = sum(t.name in e.things for t in things)
                if count==total_count:
                        return e
                elif count>best_count:
@@ -400,7 +404,7 @@ def detect_backport_extension(host_api, things):
                        best_count = count
 
        if total_count and best_count*2>=total_count:
-               print "Warning: Inconsistent backport extension %s"%best_ext.name
+               print("Warning: Inconsistent backport extension {}".format(best_ext.name))
 
 def collect_extensions(thing, api, exts):
        supp = thing.api_support.get(api)
@@ -423,8 +427,8 @@ def detect_source_extension(host_api, things, debug=False):
                        things_by_ext.setdefault(e, []).append(t)
 
        if debug:
-               print "---"
-               print "Looking for %d things in %d extensions"%(len(things), len(things_by_ext))
+               print("---")
+               print("Looking for {} things in {} extensions".format(len(things), len(things_by_ext)))
 
        extensions = []
        keep_exts = 0
@@ -455,7 +459,7 @@ def detect_source_extension(host_api, things, debug=False):
 
                largest_ext = None
                largest_count = 0
-               for e, t in things_by_ext.iteritems():
+               for e, t in things_by_ext.items():
                        count = len(t)
                        if count>largest_count:
                                largest_ext = e
@@ -464,7 +468,7 @@ def detect_source_extension(host_api, things, debug=False):
                                largest_ext = e
 
                if debug:
-                       print "Found %d things in %s"%(largest_count, largest_ext.name)
+                       print("Found {} things in {}".format(largest_count, largest_ext.name))
 
                extensions.append(largest_ext)
                for t in things_by_ext[largest_ext]:
@@ -475,8 +479,8 @@ def detect_source_extension(host_api, things, debug=False):
                                recheck_base_version = True
 
                del things_by_ext[largest_ext]
-               for e in things_by_ext.keys():
-                       unseen = filter((lambda t: t in missing), things_by_ext[e])
+               for e in list(things_by_ext.keys()):
+                       unseen = [t for t in things_by_ext[e] if t in missing]
                        if unseen:
                                things_by_ext[e] = unseen
                        else:
@@ -486,16 +490,16 @@ def detect_source_extension(host_api, things, debug=False):
                return None, extensions
        elif base_version:
                if debug:
-                       print "Found remaining things in version %s"%base_version
+                       print("Found remaining things in version {}".format(base_version))
                        if keep_exts<len(extensions):
-                               print "Discarding %d extensions that do not improve base version"%(len(extensions)-keep_exts)
+                               print("Discarding {} extensions that do not improve base version".format(len(extensions)-keep_exts))
                del extensions[keep_exts:]
                return base_version, extensions
        else:
                if debug:
-                       print "%d things still missing:"%len(missing)
+                       print("{} things still missing:".format(len(missing)))
                        for t in missing:
-                               print "  "+t.name
+                               print("  "+t.name)
                return None, None
 
 
@@ -507,10 +511,10 @@ class SourceGenerator:
                        self.api_prefix = "GL_ES"
                self.ext_name = ext_name
                all_things = things+optional_things
-               self.funcs = filter((lambda t: t.kind==Thing.FUNCTION), all_things)
+               self.funcs = [t for t in all_things if t.kind==Thing.FUNCTION]
                self.funcs.sort(key=(lambda f: f.name))
                self.func_typedefs = dict((f.name, "FPtr_"+f.name) for f in self.funcs)
-               self.enums = filter((lambda t: t.kind==Thing.ENUM), all_things)
+               self.enums = [t for t in all_things if t.kind==Thing.ENUM]
                self.enums.sort(key=(lambda e: e.value))
                self.core_version = detect_core_version(host_api, things, debug)
                self.deprecated_version = detect_deprecated_version(host_api, things, debug)
@@ -520,24 +524,24 @@ class SourceGenerator:
                self.source_exts = e
 
                if not self.core_version and not self.backport_ext and not self.source_exts:
-                       print "Warning: Not supportable on host API"
+                       print("Warning: Not supportable on host API")
 
        def dump_info(self):
-               print "--- Extension information ---"
-               print "Extension %s"%self.ext_name
-               print "Core %s"%self.core_version
-               print "Deprecated %s"%self.deprecated_version
+               print("--- Extension information ---")
+               print("Extension {}".format(self.ext_name))
+               print("Core {}".format(self.core_version))
+               print("Deprecated {}".format(self.deprecated_version))
                if self.backport_ext:
-                       print "Backport %s"%self.backport_ext.name
+                       print("Backport {}".format(self.backport_ext.name))
                if self.source_exts:
                        names = [e.name for e in self.source_exts]
                        if self.base_version:
-                               names.insert(0, "Version %s"%self.base_version)
-                       print "Sources %s"%", ".join(names)
+                               names.insert(0, "Version {}".format(self.base_version))
+                       print("Sources {}".format(", ".join(names)))
 
        def write_header_intro(self, out):
-               out.write("#ifndef MSP_GL_%s_\n"%self.ext_name.upper())
-               out.write("#define MSP_GL_%s_\n"%self.ext_name.upper())
+               out.write("#ifndef MSP_GL_{}_\n".format(self.ext_name.upper()))
+               out.write("#define MSP_GL_{}_\n".format(self.ext_name.upper()))
 
                out.write("""
 #include <msp/gl/extension.h>
@@ -555,16 +559,16 @@ namespace GL {
                        supp = e.api_support.get(self.host_api.name)
                        if supp:
                                if supp.core_version:
-                                       cat = "%s_%s"%(self.api_prefix, supp.core_version.as_define())
+                                       cat = "{}_{}".format(self.api_prefix, supp.core_version.as_define())
                                elif supp.extensions:
                                        cat = "GL_"+supp.extensions[0].name
                        enums_by_category.setdefault(cat, []).append(e)
 
                for cat in sorted(enums_by_category.keys()):
                        if cat:
-                               out.write("#ifndef %s\n"%cat)
+                               out.write("#ifndef {}\n".format(cat))
                        for e in enums_by_category[cat]:
-                               out.write("#define %s 0x%04X\n"%(e.name, e.value))
+                               out.write("#define {} 0x{:04X}\n".format(e.name, e.value))
                        if cat:
                                out.write("#endif\n")
                        out.write("\n")
@@ -572,8 +576,8 @@ namespace GL {
        def write_function_pointer_declarations(self, out):
                for f in self.funcs:
                        typedef = self.func_typedefs[f.name]
-                       out.write("typedef %s (APIENTRY *%s)(%s);\n"%(f.return_type, typedef, ", ".join(f.params)))
-                       out.write("extern %s %s;\n"%(typedef, f.name))
+                       out.write("typedef {} (APIENTRY *{})({});\n".format(f.return_type, typedef, ", ".join(f.params)))
+                       out.write("extern {} {};\n".format(typedef, f.name))
                        out.write("\n")
 
        def write_header_outro(self, out):
@@ -585,7 +589,7 @@ namespace GL {
 """)
 
        def write_source_intro(self, out):
-               out.write("#include \"%s.h\"\n"%self.ext_name.lower())
+               out.write("#include \"{}.h\"\n".format(self.ext_name.lower()))
                if self.funcs:
                        out.write("""
 #ifdef __APPLE__
@@ -608,19 +612,19 @@ namespace GL {
 
        def write_function_pointer_definitions(self, out):
                for f in self.funcs:
-                       out.write("%s %s = 0;\n"%(self.func_typedefs[f.name], f.name))
+                       out.write("{} {} = 0;\n".format(self.func_typedefs[f.name], f.name))
 
        def write_init_function(self, out):
-               out.write("\nExtension::SupportLevel init_%s()\n{\n"%self.ext_name.lower())
+               out.write("\nExtension::SupportLevel init_{}()\n{{\n".format(self.ext_name.lower()))
                if self.core_version:
-                       out.write("\tif(is_disabled(\"GL_%s\"))\n\t\treturn Extension::UNSUPPORTED;\n"%self.ext_name)
-                       out.write("#if !defined(__APPLE__) || defined(%s_%s)\n"%(self.api_prefix, self.core_version.as_define()))
+                       out.write("\tif(is_disabled(\"GL_{}\"))\n\t\treturn Extension::UNSUPPORTED;\n".format(self.ext_name))
+                       out.write("#if !defined(__APPLE__) || defined({}_{})\n".format(self.api_prefix, self.core_version.as_define()))
                        out.write("\tif(")
                        if self.backport_ext:
-                               out.write("is_supported(\"GL_%s\") || "%self.backport_ext.name)
-                       out.write("is_supported(%r"%self.core_version)
+                               out.write("is_supported(\"GL_{}\") || ".format(self.backport_ext.name))
+                       out.write("is_supported({!r}".format(self.core_version))
                        if self.deprecated_version:
-                               out.write(", %r"%self.deprecated_version)
+                               out.write(", {!r}".format(self.deprecated_version))
                        out.write("))\n\t{\n")
                        for f in self.funcs:
                                supp = f.api_support.get(self.host_api.name)
@@ -628,16 +632,16 @@ namespace GL {
                                        gpa_suffix = ""
                                        if supp.core_version is not None and supp.core_version<=Version(1, 1):
                                                gpa_suffix = "_1_1"
-                                       out.write("\t\t%s = reinterpret_cast<%s>(GET_PROC_ADDRESS%s(%s));\n"%(f.name, self.func_typedefs[f.name], gpa_suffix, f.name))
+                                       out.write("\t\t{} = reinterpret_cast<{}>(GET_PROC_ADDRESS{}({}));\n".format(f.name, self.func_typedefs[f.name], gpa_suffix, f.name))
                        out.write("\t\treturn Extension::CORE;\n")
                        out.write("\t}\n")
                        out.write("#endif\n")
                if self.source_exts:
-                       out.write("#if !defined(__APPLE__) || defined(GL_%s)\n"%self.ext_name)
+                       out.write("#if !defined(__APPLE__) || defined(GL_{})\n".format(self.ext_name))
                        out.write("\tif(")
                        if self.base_version:
-                               out.write("is_supported(%r) && "%self.base_version)
-                       out.write("%s)\n\t{\n"%" && ".join("is_supported(\"GL_%s\")"%s.name for s in self.source_exts))
+                               out.write("is_supported({!r}) && ".format(self.base_version))
+                       out.write("{})\n\t{{\n".format(" && ".join("is_supported(\"GL_%s\")"%s.name for s in self.source_exts)))
                        for f in self.funcs:
                                supp = f.api_support.get(self.host_api.name)
                                src = None
@@ -655,7 +659,7 @@ namespace GL {
                                        sec = f
 
                                if src:
-                                       out.write("\t\t%s = reinterpret_cast<%s>(GET_PROC_ADDRESS(%s));\n"%(f.name, self.func_typedefs[f.name], src.name))
+                                       out.write("\t\t{} = reinterpret_cast<{}>(GET_PROC_ADDRESS({}));\n".format(f.name, self.func_typedefs[f.name], src.name))
                        out.write("\t\treturn Extension::EXTENSION;\n")
                        out.write("\t}\n")
                        out.write("#endif\n")
@@ -669,42 +673,42 @@ namespace GL {
 """)
 
        def write_header(self, fn):
-               out = file(fn, "w")
+               out = open(fn, "w")
                self.write_header_intro(out)
                self.write_enum_definitions(out)
                self.write_function_pointer_declarations(out)
-               out.write("extern Extension %s;\n"%self.ext_name)
+               out.write("extern Extension {};\n".format(self.ext_name))
                self.write_header_outro(out)
 
        def write_source(self, fn):
-               out = file(fn, "w")
+               out = open(fn, "w")
                self.write_source_intro(out)
                self.write_function_pointer_definitions(out)
                self.write_init_function(out)
-               out.write("\nExtension %s(\"GL_%s\", init_%s);\n"%(self.ext_name, self.ext_name, self.ext_name.lower()))
+               out.write("\nExtension {}(\"GL_{}\", init_{});\n".format(self.ext_name, self.ext_name, self.ext_name.lower()))
                self.write_source_outro(out)
 
 
 def dump_api_support(supp, api, indent):
        if supp.core_version:
-               print indent+"core in version "+str(supp.core_version)
+               print(indent+"core in version {}".format(supp.core_version))
        if supp.deprecated_version:
-               print indent+"deprecated in version "+str(supp.deprecated_version)
+               print(indent+"deprecated in version {}".format(supp.deprecated_version))
        for e in supp.extensions:
-               print indent+"extension %s (preference %d)"%(e.name, e.preference)
+               print(indent+"extension {} (preference {})".format(e.name, e.preference))
        for r in supp.sources:
-               print indent+"source "+r.name
+               print(indent+"source {}".format(r.name))
                dump_thing_info(r, api, indent+"  ")
 
 def dump_thing_info(thing, api, indent):
        for a in thing.aliases:
-               print indent+"alias "+a
+               print(indent+"alias {}".format(a))
        if api:
                supp = thing.api_support.get(api)
                dump_api_support(supp, api, indent)
        else:
-               for a, s in thing.api_support.iteritems():
-                       print indent+"api "+a
+               for a, s in thing.api_support.items():
+                       print(indent+"api {}".format(a))
                        dump_api_support(s, a, indent+"  ")
 
 
@@ -749,7 +753,7 @@ class ExtensionParser:
                        elif keyword=="optional":
                                self.optional_things.append(parts[1])
                        else:
-                               print "Unknown keyword "+keyword
+                               print("Unknown keyword "+keyword)
                                return False
 
                return True
@@ -766,7 +770,7 @@ def get_extension(api_map, ext_name):
 def resolve_things(api, things):
        rthings = []
        for t in things:
-               ct = filter(None, map(api.core_things.get, t.aliases))
+               ct = [api.core_things[a] for a in t.aliases if a in api.core_things]
                if ct:
                        rthings += ct
                else:
@@ -775,7 +779,7 @@ def resolve_things(api, things):
        return rthings
 
 def collect_extension_things(host_api, target_ext, ignore):
-       ext_things = [t for n, t in target_ext.things.iteritems() if n not in ignore]
+       ext_things = [t for n, t in target_ext.things.items() if n not in ignore]
        return resolve_things(target_ext.api, ext_things)
 
 def collect_optional_things(target_ext, names):
@@ -789,13 +793,13 @@ def collect_optional_things(target_ext, names):
 
 def main():
        if len(sys.argv)<2:
-               print """Usage:
+               print("""Usage:
   extgen.py [api] <extfile> [<outfile>]
 
 Reads gl.xml and generates C++ source files to use an OpenGL extension
 described in <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."""
+replaced with cpp and h.""")
                sys.exit(1)
 
        i = 1
@@ -832,13 +836,13 @@ replaced with cpp and h."""
        optional_things = collect_optional_things(target_ext, ext_parser.optional_things)
 
        if debug:
-               print "--- Things included in this extension ---"
+               print("--- Things included in this extension ---")
                all_things = things+optional_things
                all_things.sort(key=(lambda t: t.name))
                for t in all_things:
-                       print t.name
+                       print(t.name)
                        if t in optional_things:
-                               print "  optional"
+                               print("  optional")
                        dump_thing_info(t, None, "  ")
 
        generator = SourceGenerator(host_api, target_ext.name, things, optional_things, debug)