Allow overloads of the same function

It is now possible to define multiple overloads of the same function,
each with different parameters. This is extremely useful for
maintaining backwards compatibility in the face of the changes between
GL 4.3 and 4.4.
This commit is contained in:
Stefanos A. 2013-11-03 16:09:11 +01:00
parent 60f971ffed
commit 9789225e0c
8 changed files with 205 additions and 64 deletions

View file

@ -205,14 +205,22 @@ namespace Bind
sw.WriteLine("{");
sw.Indent();
foreach (Delegate d in delegates.Values)
foreach (var overloads in delegates.Values)
{
sw.WriteLine("[System.Security.SuppressUnmanagedCodeSecurity()]");
sw.WriteLine("internal {0};", GetDeclarationString(d, true));
sw.WriteLine("internal {0}static {1} {2}{1};", // = null
d.Unsafe ? "unsafe " : "",
d.Name,
Settings.FunctionPrefix);
int overload_count = -1;
foreach (var d in overloads)
{
overload_count++;
string overload_suffix = overload_count > 0 ? overload_count.ToString() : String.Empty;
d.Name += overload_suffix;
sw.WriteLine("[System.Security.SuppressUnmanagedCodeSecurity()]");
sw.WriteLine("internal {0};", GetDeclarationString(d, true));
sw.WriteLine("internal {0}static {2} {1}{2};", // = null
d.Unsafe ? "unsafe " : "",
Settings.FunctionPrefix,
d.Name);
}
}
sw.Unindent();
@ -243,15 +251,15 @@ namespace Bind
sw.Indent();
//sw.WriteLine("static {0}() {1} {2}", Settings.ImportsClass, "{", "}"); // Disable BeforeFieldInit
sw.WriteLine();
foreach (Delegate d in delegates.Values)
foreach (Delegate d in delegates.Values.SelectMany(v => v))
{
sw.WriteLine("[System.Security.SuppressUnmanagedCodeSecurity()]");
sw.WriteLine(
"[System.Runtime.InteropServices.DllImport({0}.Library, EntryPoint = \"{1}{2}\"{3})]",
Settings.OutputClass,
Settings.FunctionPrefix,
d.Name,
d.Name.EndsWith("W") || d.Name.EndsWith("A") ? ", CharSet = CharSet.Auto" : ", ExactSpelling = true"
d.EntryPoint,
d.EntryPoint.EndsWith("W") || d.EntryPoint.EndsWith("A") ? ", CharSet = CharSet.Auto" : ", ExactSpelling = true"
);
sw.WriteLine("internal extern static {0};", GetDeclarationString(d, false));
}
@ -346,7 +354,7 @@ namespace Bind
}
sw.WriteLine("[AutoGenerated(Category = \"{0}\", Version = \"{1}\", EntryPoint = \"{2}\")]",
f.Category, f.Version, Settings.FunctionPrefix + f.WrappedDelegate.Name);
f.Category, f.Version, Settings.FunctionPrefix + f.WrappedDelegate.EntryPoint);
sw.WriteLine("public static ");
sw.Write(GetDeclarationString(f));
sw.WriteLine();
@ -915,8 +923,6 @@ namespace Bind
string GetDeclarationString(Parameter p, bool override_unsafe_setting)
{
bool unsafe_allowed = override_unsafe_setting;
StringBuilder sb = new StringBuilder();
if (p.Flow == FlowDirection.Out)

View file

@ -69,21 +69,27 @@ namespace Bind
{
Console.WriteLine("Processing delegates.");
var nav = new XPathDocument(Overrides).CreateNavigator();
foreach (var d in delegates.Values)
foreach (var overloads in delegates.Values)
{
TranslateExtension(d);
TranslateReturnType(enum_processor, nav, d, enums, apiname);
TranslateParameters(enum_processor, nav, d, enums, apiname);
TranslateAttributes(nav, d, enums, apiname);
foreach (var d in overloads)
{
TranslateExtension(d);
TranslateReturnType(enum_processor, nav, d, enums, apiname);
TranslateParameters(enum_processor, nav, d, enums, apiname);
TranslateAttributes(nav, d, enums, apiname);
}
}
Console.WriteLine("Generating wrappers.");
var wrappers = CreateWrappers(delegates, enums);
Console.WriteLine("Creating CLS compliant overloads.");
wrappers = CreateCLSCompliantWrappers(wrappers, enums);
Console.WriteLine("Removing non-CLS compliant duplicates.");
return MarkCLSCompliance(wrappers);
Console.WriteLine("Removing non-CLS compliant duplicates.");
wrappers = MarkCLSCompliance(wrappers);
return wrappers;
}
public static string GetOverridesPath(string apiname, string function, string extension)
@ -132,6 +138,8 @@ namespace Bind
// Translate enum types
if (normal && @enum.Name != "GLenum" && @enum.Name != "Boolean")
{
type.IsEnum = true;
if ((Settings.Compatibility & Settings.Legacy.ConstIntEnums) != Settings.Legacy.None)
{
type.QualifiedType = "int";
@ -146,6 +154,8 @@ namespace Bind
}
else if (Generator.GLTypes.TryGetValue(type.CurrentType, out s))
{
type.IsEnum = true;
// Check if the parameter is a generic GLenum. If it is, search for a better match,
// otherwise fallback to Settings.CompleteEnumName (named 'All' by default).
if (s.Contains("GLenum") /*&& !String.IsNullOrEmpty(category)*/)
@ -157,7 +167,9 @@ namespace Bind
else
{
// Better match: enum.Name == function.Category (e.g. GL_VERSION_1_1 etc)
if (enums.ContainsKey(category))
// Note: for backwards compatibility we use "category" only for the gl api.
// glcore, gles1 and gles2 use the All enum instead.
if (apiname == "gl" && enums.ContainsKey(category))
{
type.QualifiedType = String.Format("{0}{1}{2}", Settings.EnumsOutput,
Settings.NamespaceSeparator, enum_processor.TranslateEnumName(category));
@ -486,7 +498,7 @@ namespace Bind
FunctionCollection CreateWrappers(DelegateCollection delegates, EnumCollection enums)
{
var wrappers = new FunctionCollection();
foreach (var d in delegates.Values)
foreach (var d in delegates.Values.SelectMany(v => v))
{
wrappers.AddRange(CreateNormalWrappers(d, enums));
}

View file

@ -19,8 +19,6 @@ namespace Bind.Structures
/// </summary>
class Constant : IComparable<Constant>
{
static StringBuilder translator = new StringBuilder();
#region PreviousName
string original_name;

View file

@ -51,6 +51,7 @@ namespace Bind.Structures
//this.Version = !String.IsNullOrEmpty(d.Version) ? new string(d.Version.ToCharArray()) : "";
Deprecated = d.Deprecated;
DeprecatedVersion = d.DeprecatedVersion;
EntryPoint = d.EntryPoint;
}
#endregion
@ -237,6 +238,7 @@ namespace Bind.Structures
public bool Deprecated { get; set; }
public string DeprecatedVersion { get; set; }
public string EntryPoint { get; set; }
#endregion
@ -261,7 +263,12 @@ namespace Bind.Structures
public int CompareTo(Delegate other)
{
return Name.CompareTo(other.Name);
int ret = Name.CompareTo(other.Name);
if (ret == 0)
ret = Parameters.CompareTo(other.Parameters);
if (ret == 0)
ret = ReturnType.CompareTo(other.ReturnType);
return ret;
}
#endregion
@ -270,29 +277,158 @@ namespace Bind.Structures
public bool Equals(Delegate other)
{
return CompareTo(other) == 0;
return
Name.Equals(other.Name) &&
Parameters.Equals(other.Parameters) &&
ReturnType.Equals(other.ReturnType);
}
#endregion
}
#region class DelegateCollection : SortedDictionary<string, Delegate>
#region DelegateCollection
class DelegateCollection : SortedDictionary<string, Delegate>
class DelegateCollection : IDictionary<string, List<Delegate>>
{
readonly SortedDictionary<string, List<Delegate>> Delegates =
new SortedDictionary<string, List<Delegate>>();
public void Add(Delegate d)
{
if (!ContainsKey(d.Name))
{
Add(d.Name, d);
Add(d.Name, new List<Delegate> { d });
}
else
{
Trace.WriteLine(String.Format(
"Spec error: function {0} redefined, ignoring second definition.",
d.Name));
var list = Delegates[d.Name];
if (!list.Contains(d))
{
list.Add(d);
}
else
{
Trace.WriteLine(String.Format(
"Spec error: function {0} redefined, ignoring second definition.",
d.Name));
}
}
}
#region IDictionary Members
public void Add(string key, List<Delegate> value)
{
Delegates.Add(key, value.ToList());
}
public bool ContainsKey(string key)
{
return Delegates.ContainsKey(key);
}
public bool Remove(string key)
{
return Delegates.Remove(key);
}
public bool TryGetValue(string key, out List<Delegate> value)
{
return Delegates.TryGetValue(key, out value);
}
public List<Delegate> this[string index]
{
get
{
return Delegates[index];
}
set
{
Delegates[index] = value;
}
}
public ICollection<string> Keys
{
get
{
return Delegates.Keys;
}
}
public ICollection<List<Delegate>> Values
{
get
{
return Delegates.Values;
}
}
#endregion
#region ICollection implementation
public void Add(KeyValuePair<string, List<Delegate>> item)
{
Delegates.Add(item.Key, item.Value.ToList());
}
public void Clear()
{
Delegates.Clear();
}
public bool Contains(KeyValuePair<string, List<Delegate>> item)
{
return Delegates.Contains(item);
}
public void CopyTo(KeyValuePair<string, List<Delegate>>[] array, int arrayIndex)
{
Delegates.CopyTo(array, arrayIndex);
}
public bool Remove(KeyValuePair<string, List<Delegate>> item)
{
return Delegates.Remove(item.Key);
}
public int Count
{
get
{
return Delegates.Count;
}
}
public bool IsReadOnly
{
get
{
return false;
}
}
#endregion
#region IEnumerable implementation
public IEnumerator<KeyValuePair<string, List<Delegate>>> GetEnumerator()
{
return Delegates.GetEnumerator();
}
#endregion
#region IEnumerable implementation
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return Delegates.GetEnumerator();
}
#endregion
}
#endregion

View file

@ -17,7 +17,6 @@ namespace Bind.Structures
class Enum
{
static StringBuilder translator = new StringBuilder();
string _name, _type;
// Returns true if the enum contains a collection of flags, i.e. 1, 2, 4, 8, ...

View file

@ -35,6 +35,7 @@ namespace Bind.Structures
Pointer = t.Pointer;
Reference = t.Reference;
ElementCount = t.ElementCount;
IsEnum = t.IsEnum;
}
}
@ -56,6 +57,8 @@ namespace Bind.Structures
#endregion
#region Public Members
public string QualifiedType
{
get
@ -176,15 +179,8 @@ namespace Bind.Structures
#endregion
//// Returns true if parameter is an enum.
//public bool IsEnum
//{
// get
// {
// return Enum.GLEnums.ContainsKey(CurrentType) ||
// Enum.AuxEnums.ContainsKey(CurrentType);
// }
//}
// Set to true if parameter is an enum.
public bool IsEnum { get; set; }
#region IndirectionLevel
@ -309,6 +305,8 @@ namespace Bind.Structures
#endregion
#endregion
#region IComparable<Type> Members
public int CompareTo(Type other)

View file

@ -238,19 +238,16 @@ namespace Bind
// Merges the specified delegate collections.
internal static void Merge(DelegateCollection delegates, DelegateCollection new_delegates)
{
foreach (var d in new_delegates)
foreach (var d in new_delegates.Values.SelectMany(v => v))
{
Merge(delegates, d.Value);
Merge(delegates, d);
}
}
// Merges the given delegate into the delegate list.
internal static void Merge(DelegateCollection delegates, Delegate t)
{
if (!delegates.ContainsKey(t.Name))
delegates.Add(t.Name, t);
else
Console.WriteLine("Function '{0}' redefined", t.Name);
delegates.Add(t);
}
#endregion

View file

@ -255,23 +255,18 @@ namespace Bind
continue;
// Check whether we are adding to an existing delegate or creating a new one.
Delegate d = null;
if (delegates.ContainsKey(name))
var d = new Delegate
{
d = delegates[name];
}
else
{
d = new Delegate();
d.Name = name;
d.Version = node.GetAttribute("version", String.Empty).Trim();
d.Category = node.GetAttribute("category", String.Empty).Trim();
d.DeprecatedVersion = node.GetAttribute("deprecated", String.Empty).Trim();
d.Deprecated = !String.IsNullOrEmpty(d.DeprecatedVersion);
d.Extension = node.GetAttribute("extension", String.Empty).Trim() ?? "Core";
if (!extensions.Contains(d.Extension))
extensions.Add(d.Extension);
}
Name = name,
EntryPoint = name,
Version = node.GetAttribute("version", String.Empty).Trim(),
Category = node.GetAttribute("category", String.Empty).Trim(),
DeprecatedVersion = node.GetAttribute("deprecated", String.Empty).Trim(),
Deprecated = !String.IsNullOrEmpty(node.GetAttribute("deprecated", String.Empty)),
Extension = node.GetAttribute("extension", String.Empty).Trim() ?? "Core",
};
if (!extensions.Contains(d.Extension))
extensions.Add(d.Extension);
foreach (XPathNavigator param in node.SelectChildren(XPathNodeType.Element))
{