+ extensions = get_nested_elements(root, "extensions/extension")
+ for ext in extensions:
+ parse_extension(ext)
+
+parse_file("gl.xml")
+parse_file("gl.fixes.xml")
+
+### Additional processing ###
+
+if target_ext in extensions:
+ target_ext = extensions[target_ext]
+else:
+ print "Extension %s not found"%target_ext
+ sys.exit(1)
+
+# Find aliases for enums
+enums = [t for t in things.itervalues() if t.kind==Thing.ENUM]
+core_enums = [e for e in enums if any(v!="ext" for v in e.supported_apis.itervalues())]
+core_enums_by_value = dict((e.value, None) for e in core_enums)
+
+def get_key_api(things):
+ common_apis = set(target_ext.supported_apis)
+ for t in things:
+ common_apis.intersection_update(t.supported_apis.keys())
+ if common_apis:
+ return common_apis.pop()
+ else:
+ return target_api
+
+for e in enums:
+ if all(v=="ext" for v in e.supported_apis.values()) and e.value in core_enums_by_value:
+ if core_enums_by_value[e.value] is None:
+ candidates = [ce for ce in core_enums if ce.value==e.value]
+ key_api = get_key_api(candidates)
+ core_enums_by_value[e.value] = list(sorted(candidates, key=(lambda x: x.supported_apis.get(key_api, "ext"))))
+ for ce in core_enums_by_value[e.value]:
+ if ce.bitmask==e.bitmask:
+ e.aliases.append(ce.name)
+ break
+
+# Create references from core things to their extension counterparts
+for t in things.itervalues():
+ if t.extension:
+ for a in t.aliases:
+ alias = things.get(a)
+ if alias:
+ if target_api in t.supported_apis:
+ alias.sources.insert(0, t)
+ else:
+ alias.sources.append(t)
+
+# Find the things we want to include in this extension
+def is_relevant(t):
+ # Unpromoted extension things are relevant
+ if t.extension and t.extension==target_ext and not t.aliases:
+ return True
+
+ # Core things promoted from the extension are also relevant
+ for s in t.sources:
+ if s.extension==target_ext or s.extension.name 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 = filter(is_relevant, enums)
+enums.sort(key=(lambda e: e.value))
+
+# Some final preparations for creating the files
+core_version_candidates = {}
+min_deprecated_version = [999, 0]
+backport_ext_candidates = []
+for t in itertools.chain(funcs, enums):
+ if target_api in t.supported_apis and t.supported_apis[target_api]!="ext":
+ t.version = t.supported_apis[target_api]
+ if t.version:
+ ver_tuple = tuple(t.version)
+ core_version_candidates[ver_tuple] = core_version_candidates.get(ver_tuple, 0)+1
+
+ if target_api in t.deprecated:
+ t.deprecated_version = t.deprecated[target_api]
+ min_deprecated_version = min(min_deprecated_version, t.deprecated_version)
+ else:
+ min_deprecated_version = None
+
+ # Things in backport extensions don't acquire an extension suffix
+ if t.extension and not t.name.endswith(ext_type) and target_api in t.supported_apis:
+ if t.extension not in backport_ext_candidates:
+ backport_ext_candidates.append(t.extension)
+
+if not core_version and core_version_candidates:
+ core_version_candidates = list((v, k) for k, v in core_version_candidates.items())
+ if len(core_version_candidates)>1:
+ core_version_candidates.sort(reverse=True)
+ if core_version_candidates[1][0]+1>=core_version_candidates[0][0]:
+ ver0 = core_version_candidates[0][1]
+ ver1 = core_version_candidates[1][1]
+ print "Warning: multiple likely core version candidates: %d.%d %d.%d"%(ver0[0], ver0[1], ver1[0], ver1[1])
+ core_version = core_version_candidates[0][1]
+
+if not deprecated_version:
+ deprecated_version = min_deprecated_version
+
+if backport_ext:
+ if backport_ext=="none":
+ backport_ext = None
+ else:
+ backport_ext = extensions[backport_ext]
+
+ if backport_ext not in backport_ext_candidates:
+ print "Warning: explicitly specified backport extension %s does not look like a backport extension"
+elif backport_ext_candidates:
+ if len(backport_ext_candidates)>1:
+ print "Warning: multiple backport extension candidates: %s"%(" ".join(e.name for e in backport_ext_candidates))
+
+ for e in backport_ext_candidates:
+ if e.base_name==target_ext.base_name:
+ backport_ext = e
+
+ if not backport_ext and len(backport_ext_candidates)==1:
+ print "Warning: potential backport extension has mismatched name: %s"%backport_ext_candidates[0].name
+
+for f in funcs:
+ f.typedef = "FPtr_%s"%f.name
+
+if target_api in target_ext.supported_apis:
+ source_ext = target_ext
+else:
+ candidates = {}
+ for t in itertools.chain(funcs, enums):
+ for s in t.sources:
+ if target_api in s.supported_apis:
+ candidates[s.extension.name] = candidates.get(s.extension.name, 0)+1
+ if candidates:
+ source_ext = extensions[max(candidates.iteritems(), key=(lambda x: x[1]))[0]]
+ else:
+ source_ext = None
+
+if funcs or enums:
+ any_supported = False
+ all_supported = True
+ for t in itertools.chain(funcs, enums):
+ if target_api in t.supported_apis:
+ any_supported = True
+ else:
+ all_supported = False
+
+ if not any_supported:
+ print "Warning: %s is not supported by the target API"%target_ext.name
+ elif not all_supported:
+ print "Warning: %s is only partially supported by the target API"%target_ext.name
+ unsupported = ""
+ label = "Warning: Unsupported tokens: "
+ for t in itertools.chain(funcs, enums):
+ if target_api not in t.supported_apis:
+ if unsupported and len(label)+len(unsupported)+2+len(t.name)>78:
+ print label+unsupported
+ label = " "*len(label)
+ unsupported = ""
+ if unsupported:
+ unsupported += ", "
+ unsupported += t.name
+ if unsupported:
+ print label+unsupported
+
+### Output ###
+
+out = file(out_base+".h", "w")
+out.write("#ifndef MSP_GL_%s_\n"%target_ext.name.upper())
+out.write("#define MSP_GL_%s_\n"%target_ext.name.upper())