2009-02-22 10:43:35 +00:00
|
|
|
|
#region --- License ---
|
|
|
|
|
/* Copyright (c) 2006, 2007 Stefanos Apostolopoulos
|
|
|
|
|
* See license.txt for license info
|
|
|
|
|
*/
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Text;
|
|
|
|
|
using System.Text.RegularExpressions;
|
|
|
|
|
|
|
|
|
|
namespace Bind.Structures
|
|
|
|
|
{
|
2009-05-30 15:28:52 +00:00
|
|
|
|
public class Function : Delegate, IEquatable<Function>, IComparable<Function>
|
2009-02-22 10:43:35 +00:00
|
|
|
|
{
|
2009-02-28 19:29:34 +00:00
|
|
|
|
#region Static Members
|
|
|
|
|
|
2009-02-22 10:43:35 +00:00
|
|
|
|
internal static FunctionCollection Wrappers;
|
|
|
|
|
|
2009-02-28 19:29:34 +00:00
|
|
|
|
static bool loaded;
|
2009-02-22 10:43:35 +00:00
|
|
|
|
|
|
|
|
|
#region internal static void Initialize()
|
|
|
|
|
|
|
|
|
|
internal static void Initialize()
|
|
|
|
|
{
|
|
|
|
|
if (!loaded)
|
|
|
|
|
{
|
|
|
|
|
Wrappers = new FunctionCollection();
|
|
|
|
|
loaded = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
2009-02-28 19:29:34 +00:00
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region Fields
|
|
|
|
|
|
|
|
|
|
Delegate wrapped_delegate;
|
2009-03-21 21:44:07 +00:00
|
|
|
|
int index;
|
2009-02-28 19:29:34 +00:00
|
|
|
|
|
|
|
|
|
#endregion
|
2009-02-22 10:43:35 +00:00
|
|
|
|
|
|
|
|
|
#region --- Constructors ---
|
|
|
|
|
|
|
|
|
|
public Function(Delegate d)
|
|
|
|
|
: base(d)
|
|
|
|
|
{
|
2009-03-21 21:44:07 +00:00
|
|
|
|
Name = d.Name;
|
|
|
|
|
Body = new FunctionBody();
|
2009-02-28 19:29:34 +00:00
|
|
|
|
WrappedDelegate = d;
|
2009-02-22 10:43:35 +00:00
|
|
|
|
}
|
|
|
|
|
|
2009-03-21 21:44:07 +00:00
|
|
|
|
public Function(Function f)
|
2009-10-28 23:09:25 +00:00
|
|
|
|
: this(f.WrappedDelegate)
|
2009-03-21 21:44:07 +00:00
|
|
|
|
{
|
2009-10-28 23:09:25 +00:00
|
|
|
|
Parameters = new ParameterCollection(f.Parameters);
|
|
|
|
|
ReturnType = new Type(f.ReturnType);
|
|
|
|
|
Body.AddRange(f.Body);
|
2009-03-21 21:44:07 +00:00
|
|
|
|
}
|
|
|
|
|
|
2009-02-22 10:43:35 +00:00
|
|
|
|
#endregion
|
|
|
|
|
|
2009-03-25 17:55:37 +00:00
|
|
|
|
#region public Delegate WrappedDelegate
|
|
|
|
|
|
2009-02-28 19:29:34 +00:00
|
|
|
|
public Delegate WrappedDelegate
|
|
|
|
|
{
|
|
|
|
|
get { return wrapped_delegate; }
|
|
|
|
|
set { wrapped_delegate = value; }
|
|
|
|
|
}
|
|
|
|
|
|
2009-03-25 17:55:37 +00:00
|
|
|
|
#endregion
|
|
|
|
|
|
2009-02-28 19:29:34 +00:00
|
|
|
|
#region public void TurnVoidPointersToIntPtr()
|
|
|
|
|
|
2009-02-22 10:43:35 +00:00
|
|
|
|
public void TurnVoidPointersToIntPtr()
|
|
|
|
|
{
|
2009-08-25 15:59:57 +00:00
|
|
|
|
foreach (Parameter p in Parameters)
|
2009-02-22 10:43:35 +00:00
|
|
|
|
{
|
2009-07-15 22:33:26 +00:00
|
|
|
|
if (p.Pointer != 0 && p.CurrentType == "void")
|
2009-02-22 10:43:35 +00:00
|
|
|
|
{
|
|
|
|
|
p.CurrentType = "IntPtr";
|
2009-07-15 22:33:26 +00:00
|
|
|
|
p.Pointer = 0;
|
2009-02-22 10:43:35 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2009-02-28 19:29:34 +00:00
|
|
|
|
#endregion
|
|
|
|
|
|
2009-02-22 10:43:35 +00:00
|
|
|
|
#region public override bool Unsafe
|
|
|
|
|
|
|
|
|
|
public override bool Unsafe
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
if ((Settings.Compatibility & Settings.Legacy.NoPublicUnsafeFunctions) != Settings.Legacy.None)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
return base.Unsafe;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region public FunctionBody Body
|
|
|
|
|
|
|
|
|
|
FunctionBody _body;
|
|
|
|
|
|
|
|
|
|
public FunctionBody Body
|
|
|
|
|
{
|
|
|
|
|
get { return _body; }
|
|
|
|
|
set { _body = value; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region public string TrimmedName
|
|
|
|
|
|
|
|
|
|
public string TrimmedName;
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region public override string Name
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Gets or sets the name of the opengl function.
|
|
|
|
|
/// If no Tao compatibility is set, set TrimmedName to Name, after removing
|
|
|
|
|
/// [u][bsifd][v].
|
|
|
|
|
/// </summary>
|
|
|
|
|
public override string Name
|
|
|
|
|
{
|
|
|
|
|
get { return base.Name; }
|
|
|
|
|
set
|
|
|
|
|
{
|
|
|
|
|
base.Name = value;
|
|
|
|
|
|
|
|
|
|
if ((Settings.Compatibility & Settings.Legacy.NoTrimFunctionEnding) != Settings.Legacy.None)
|
|
|
|
|
{
|
|
|
|
|
// If we don't need compatibility with Tao,
|
|
|
|
|
// remove the Extension and the overload information from the name
|
|
|
|
|
// (Extension == "ARB", "EXT", etc, overload == [u][bsidf][v])
|
|
|
|
|
// TODO: Use some regex's here, to reduce clutter.
|
|
|
|
|
TrimmedName = value;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
TrimmedName = Utilities.StripGL2Extension(value);
|
|
|
|
|
|
|
|
|
|
Match m = endingsNotToTrim.Match(TrimmedName);
|
|
|
|
|
if ((m.Index + m.Length) != TrimmedName.Length)
|
|
|
|
|
{
|
|
|
|
|
// Some endings should not be trimmed, for example: 'b' from Attrib
|
|
|
|
|
|
|
|
|
|
m = endings.Match(TrimmedName);
|
|
|
|
|
|
|
|
|
|
if (m.Length > 0 && m.Index + m.Length == TrimmedName.Length)
|
|
|
|
|
{
|
|
|
|
|
// Only trim endings, not internal matches.
|
|
|
|
|
if (m.Value[m.Length - 1] == 'v' && endingsAddV.IsMatch(Name) &&
|
|
|
|
|
!Name.StartsWith("Get") && !Name.StartsWith("MatrixIndex"))
|
|
|
|
|
{
|
|
|
|
|
// Only trim ending 'v' when there is a number
|
|
|
|
|
TrimmedName = TrimmedName.Substring(0, m.Index) + "v";
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (!TrimmedName.EndsWith("xedv"))
|
|
|
|
|
TrimmedName = TrimmedName.Substring(0, m.Index);
|
|
|
|
|
else
|
|
|
|
|
TrimmedName = TrimmedName.Substring(0, m.Index + 1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region public override string ToString()
|
|
|
|
|
|
|
|
|
|
public override string ToString()
|
|
|
|
|
{
|
|
|
|
|
StringBuilder sb = new StringBuilder();
|
|
|
|
|
|
|
|
|
|
sb.Append(Unsafe ? "unsafe " : "");
|
|
|
|
|
sb.Append(ReturnType);
|
|
|
|
|
sb.Append(" ");
|
|
|
|
|
if ((Settings.Compatibility & Settings.Legacy.NoTrimFunctionEnding) != Settings.Legacy.None)
|
|
|
|
|
{
|
|
|
|
|
sb.Append(Settings.FunctionPrefix);
|
|
|
|
|
}
|
|
|
|
|
sb.Append(!String.IsNullOrEmpty(TrimmedName) ? TrimmedName : Name);
|
2009-03-21 21:44:07 +00:00
|
|
|
|
|
|
|
|
|
if (Parameters.HasGenericParameters)
|
|
|
|
|
{
|
|
|
|
|
sb.Append("<");
|
|
|
|
|
foreach (Parameter p in Parameters)
|
|
|
|
|
{
|
|
|
|
|
if (p.Generic)
|
|
|
|
|
{
|
|
|
|
|
sb.Append(p.CurrentType);
|
|
|
|
|
sb.Append(",");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
sb.Remove(sb.Length - 1, 1);
|
|
|
|
|
sb.Append(">");
|
|
|
|
|
}
|
|
|
|
|
sb.AppendLine(Parameters.ToString(false));
|
|
|
|
|
if (Parameters.HasGenericParameters)
|
|
|
|
|
{
|
|
|
|
|
foreach (Parameter p in Parameters)
|
|
|
|
|
{
|
|
|
|
|
if (p.Generic)
|
|
|
|
|
sb.AppendLine(String.Format(" where {0} : struct", p.CurrentType));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2009-02-22 10:43:35 +00:00
|
|
|
|
if (Body.Count > 0)
|
|
|
|
|
{
|
|
|
|
|
sb.Append(Body.ToString());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return sb.ToString();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region IEquatable<Function> Members
|
|
|
|
|
|
|
|
|
|
public bool Equals(Function other)
|
|
|
|
|
{
|
|
|
|
|
return
|
2009-08-25 15:59:57 +00:00
|
|
|
|
!String.IsNullOrEmpty(TrimmedName) && !String.IsNullOrEmpty(other.TrimmedName) &&
|
|
|
|
|
TrimmedName == other.TrimmedName &&
|
|
|
|
|
Parameters.ToString(true) == other.Parameters.ToString(true);
|
2009-02-22 10:43:35 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region public void WrapParameters(List<Function> wrappers)
|
|
|
|
|
|
|
|
|
|
public void WrapParameters(List<Function> wrappers)
|
|
|
|
|
{
|
|
|
|
|
Function f;
|
|
|
|
|
|
|
|
|
|
if (Parameters.HasPointerParameters)
|
|
|
|
|
{
|
2009-08-11 14:06:40 +00:00
|
|
|
|
Function _this = new Function(this);
|
2009-02-22 10:43:35 +00:00
|
|
|
|
// Array overloads
|
2009-08-11 14:06:40 +00:00
|
|
|
|
foreach (Parameter p in _this.Parameters)
|
2009-02-22 10:43:35 +00:00
|
|
|
|
{
|
2009-04-15 13:14:41 +00:00
|
|
|
|
if (p.WrapperType == WrapperTypes.ArrayParameter && p.ElementCount != 1)
|
2009-02-22 10:43:35 +00:00
|
|
|
|
{
|
|
|
|
|
p.Reference = false;
|
2009-08-11 14:06:40 +00:00
|
|
|
|
p.Array++;
|
|
|
|
|
p.Pointer--;
|
2009-02-22 10:43:35 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2009-08-11 14:06:40 +00:00
|
|
|
|
f = new Function(_this);
|
2009-02-22 10:43:35 +00:00
|
|
|
|
f.CreateBody(false);
|
|
|
|
|
wrappers.Add(f);
|
|
|
|
|
new Function(f).WrapVoidPointers(wrappers);
|
|
|
|
|
|
2009-08-11 14:06:40 +00:00
|
|
|
|
_this = new Function(this);
|
2009-02-22 10:43:35 +00:00
|
|
|
|
// Reference overloads
|
2009-08-11 14:06:40 +00:00
|
|
|
|
foreach (Parameter p in _this.Parameters)
|
2009-02-22 10:43:35 +00:00
|
|
|
|
{
|
|
|
|
|
if (p.WrapperType == WrapperTypes.ArrayParameter)
|
|
|
|
|
{
|
|
|
|
|
p.Reference = true;
|
2009-08-11 14:06:40 +00:00
|
|
|
|
p.Array--;
|
|
|
|
|
p.Pointer--;
|
2009-02-22 10:43:35 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2009-08-11 14:06:40 +00:00
|
|
|
|
f = new Function(_this);
|
2009-02-22 10:43:35 +00:00
|
|
|
|
f.CreateBody(false);
|
|
|
|
|
wrappers.Add(f);
|
|
|
|
|
new Function(f).WrapVoidPointers(wrappers);
|
|
|
|
|
|
2009-08-11 14:06:40 +00:00
|
|
|
|
_this = this;
|
2009-02-22 10:43:35 +00:00
|
|
|
|
// Pointer overloads
|
|
|
|
|
// Should be last to work around Intellisense bug, where
|
|
|
|
|
// array overloads are not reported if there is a pointer overload.
|
2009-08-11 14:06:40 +00:00
|
|
|
|
foreach (Parameter p in _this.Parameters)
|
2009-02-22 10:43:35 +00:00
|
|
|
|
{
|
|
|
|
|
if (p.WrapperType == WrapperTypes.ArrayParameter)
|
|
|
|
|
{
|
|
|
|
|
p.Reference = false;
|
2009-08-11 14:06:40 +00:00
|
|
|
|
//p.Array--;
|
|
|
|
|
//p.Pointer++;
|
2009-02-22 10:43:35 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2009-08-11 14:06:40 +00:00
|
|
|
|
f = new Function(_this);
|
2009-02-22 10:43:35 +00:00
|
|
|
|
f.CreateBody(false);
|
|
|
|
|
wrappers.Add(f);
|
|
|
|
|
new Function(f).WrapVoidPointers(wrappers);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
f = new Function(this);
|
|
|
|
|
f.CreateBody(false);
|
|
|
|
|
wrappers.Add(f);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region public void WrapVoidPointers(List<Function> wrappers)
|
|
|
|
|
|
|
|
|
|
public void WrapVoidPointers(List<Function> wrappers)
|
|
|
|
|
{
|
|
|
|
|
if (index >= 0 && index < Parameters.Count)
|
|
|
|
|
{
|
|
|
|
|
if (Parameters[index].WrapperType == WrapperTypes.GenericParameter)
|
|
|
|
|
{
|
|
|
|
|
// Recurse to the last parameter
|
|
|
|
|
++index;
|
|
|
|
|
WrapVoidPointers(wrappers);
|
|
|
|
|
--index;
|
|
|
|
|
|
2009-04-15 13:14:41 +00:00
|
|
|
|
// On stack rewind, create generic wrappers
|
2009-03-21 21:44:07 +00:00
|
|
|
|
Parameters[index].Reference = true;
|
2009-02-22 10:43:35 +00:00
|
|
|
|
Parameters[index].Array = 0;
|
2009-07-15 22:33:26 +00:00
|
|
|
|
Parameters[index].Pointer = 0;
|
2009-03-21 21:44:07 +00:00
|
|
|
|
Parameters[index].Generic = true;
|
|
|
|
|
Parameters[index].CurrentType = "T" + index.ToString();
|
2009-07-15 22:33:26 +00:00
|
|
|
|
Parameters[index].Flow = FlowDirection.Undefined;
|
2009-02-22 10:43:35 +00:00
|
|
|
|
Parameters.Rebuild = true;
|
|
|
|
|
CreateBody(false);
|
2009-03-21 21:44:07 +00:00
|
|
|
|
wrappers.Add(new Function(this));
|
2009-02-22 10:43:35 +00:00
|
|
|
|
|
2009-03-21 21:44:07 +00:00
|
|
|
|
Parameters[index].Reference = false;
|
|
|
|
|
Parameters[index].Array = 1;
|
2009-07-15 22:33:26 +00:00
|
|
|
|
Parameters[index].Pointer = 0;
|
2009-03-21 21:44:07 +00:00
|
|
|
|
Parameters[index].Generic = true;
|
|
|
|
|
Parameters[index].CurrentType = "T" + index.ToString();
|
2009-07-15 22:33:26 +00:00
|
|
|
|
Parameters[index].Flow = FlowDirection.Undefined;
|
2009-03-21 21:44:07 +00:00
|
|
|
|
Parameters.Rebuild = true;
|
|
|
|
|
CreateBody(false);
|
|
|
|
|
wrappers.Add(new Function(this));
|
|
|
|
|
|
|
|
|
|
Parameters[index].Reference = false;
|
|
|
|
|
Parameters[index].Array = 2;
|
2009-07-15 22:33:26 +00:00
|
|
|
|
Parameters[index].Pointer = 0;
|
2009-03-21 21:44:07 +00:00
|
|
|
|
Parameters[index].Generic = true;
|
|
|
|
|
Parameters[index].CurrentType = "T" + index.ToString();
|
2009-07-15 22:33:26 +00:00
|
|
|
|
Parameters[index].Flow = FlowDirection.Undefined;
|
2009-03-21 21:44:07 +00:00
|
|
|
|
Parameters.Rebuild = true;
|
|
|
|
|
CreateBody(false);
|
|
|
|
|
wrappers.Add(new Function(this));
|
|
|
|
|
|
|
|
|
|
Parameters[index].Reference = false;
|
|
|
|
|
Parameters[index].Array = 3;
|
2009-07-15 22:33:26 +00:00
|
|
|
|
Parameters[index].Pointer = 0;
|
2009-03-21 21:44:07 +00:00
|
|
|
|
Parameters[index].Generic = true;
|
|
|
|
|
Parameters[index].CurrentType = "T" + index.ToString();
|
2009-07-15 22:33:26 +00:00
|
|
|
|
Parameters[index].Flow = FlowDirection.Undefined;
|
2009-03-21 21:44:07 +00:00
|
|
|
|
Parameters.Rebuild = true;
|
|
|
|
|
CreateBody(false);
|
|
|
|
|
wrappers.Add(new Function(this));
|
2009-02-22 10:43:35 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// Recurse to the last parameter
|
|
|
|
|
++index;
|
|
|
|
|
WrapVoidPointers(wrappers);
|
|
|
|
|
--index;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region public void WrapReturnType()
|
|
|
|
|
|
|
|
|
|
public void WrapReturnType()
|
|
|
|
|
{
|
|
|
|
|
switch (ReturnType.WrapperType)
|
|
|
|
|
{
|
|
|
|
|
case WrapperTypes.StringReturnType:
|
2009-10-28 23:09:25 +00:00
|
|
|
|
ReturnType.QualifiedType = "String";
|
2009-02-22 10:43:35 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region public void CreateBody(bool wantCLSCompliance)
|
|
|
|
|
|
2009-10-28 23:09:25 +00:00
|
|
|
|
readonly static List<string> handle_statements = new List<string>();
|
|
|
|
|
readonly static List<string> handle_release_statements = new List<string>();
|
|
|
|
|
readonly static List<string> fixed_statements = new List<string>();
|
|
|
|
|
readonly static List<string> assign_statements = new List<string>();
|
2009-02-22 10:43:35 +00:00
|
|
|
|
|
2009-08-11 14:06:40 +00:00
|
|
|
|
// For example, if parameter foo has indirection level = 1, then it
|
|
|
|
|
// is consumed as 'foo*' in the fixed_statements and the call string.
|
|
|
|
|
string[] indirection_levels = new string[] { "", "*", "**", "***", "****" };
|
|
|
|
|
|
2009-02-22 10:43:35 +00:00
|
|
|
|
public void CreateBody(bool wantCLSCompliance)
|
|
|
|
|
{
|
|
|
|
|
Function f = new Function(this);
|
|
|
|
|
|
|
|
|
|
f.Body.Clear();
|
|
|
|
|
handle_statements.Clear();
|
|
|
|
|
handle_release_statements.Clear();
|
|
|
|
|
fixed_statements.Clear();
|
|
|
|
|
assign_statements.Clear();
|
|
|
|
|
|
|
|
|
|
// Obtain pointers by pinning the parameters
|
|
|
|
|
foreach (Parameter p in f.Parameters)
|
|
|
|
|
{
|
|
|
|
|
if (p.NeedsPin)
|
|
|
|
|
{
|
|
|
|
|
if (p.WrapperType == WrapperTypes.GenericParameter)
|
|
|
|
|
{
|
|
|
|
|
// Use GCHandle to obtain pointer to generic parameters and 'fixed' for arrays.
|
|
|
|
|
// This is because fixed can only take the address of fields, not managed objects.
|
|
|
|
|
handle_statements.Add(String.Format(
|
2009-03-21 21:44:07 +00:00
|
|
|
|
"{0} {1}_ptr = {0}.Alloc({1}, GCHandleType.Pinned);",
|
|
|
|
|
"GCHandle", p.Name));
|
2009-02-22 10:43:35 +00:00
|
|
|
|
|
|
|
|
|
handle_release_statements.Add(String.Format("{0}_ptr.Free();", p.Name));
|
|
|
|
|
|
2009-10-17 20:02:53 +00:00
|
|
|
|
// Due to the GCHandle-style pinning (which boxes value types), we need to assign the modified
|
|
|
|
|
// value back to the reference parameter (but only if it has an out or in/out flow direction).
|
|
|
|
|
if ((p.Flow == FlowDirection.Out || p.Flow == FlowDirection.Undefined) && p.Reference)
|
2009-02-22 10:43:35 +00:00
|
|
|
|
{
|
|
|
|
|
assign_statements.Add(String.Format(
|
|
|
|
|
"{0} = ({1}){0}_ptr.Target;",
|
2009-10-28 23:09:25 +00:00
|
|
|
|
p.Name, p.QualifiedType));
|
2009-02-22 10:43:35 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Note! The following line modifies f.Parameters, *not* this.Parameters
|
|
|
|
|
p.Name = "(IntPtr)" + p.Name + "_ptr.AddrOfPinnedObject()";
|
|
|
|
|
}
|
|
|
|
|
else if (p.WrapperType == WrapperTypes.PointerParameter ||
|
|
|
|
|
p.WrapperType == WrapperTypes.ArrayParameter ||
|
|
|
|
|
p.WrapperType == WrapperTypes.ReferenceParameter)
|
|
|
|
|
{
|
|
|
|
|
// A fixed statement is issued for all non-generic pointers, arrays and references.
|
|
|
|
|
fixed_statements.Add(String.Format(
|
2009-08-11 14:06:40 +00:00
|
|
|
|
"fixed ({0}{3} {1} = {2})",
|
2009-10-28 23:09:25 +00:00
|
|
|
|
wantCLSCompliance && !p.CLSCompliant ? p.GetCLSCompliantType() : p.QualifiedType,
|
2009-02-22 10:43:35 +00:00
|
|
|
|
p.Name + "_ptr",
|
2009-08-11 14:06:40 +00:00
|
|
|
|
p.Array > 0 ? p.Name : "&" + p.Name,
|
|
|
|
|
indirection_levels[p.IndirectionLevel]));
|
2009-02-22 10:43:35 +00:00
|
|
|
|
|
2009-10-17 20:02:53 +00:00
|
|
|
|
if (p.Name == "pixels_ptr")
|
|
|
|
|
System.Diagnostics.Debugger.Break();
|
|
|
|
|
|
|
|
|
|
// Arrays are not value types, so we don't need to do anything for them.
|
|
|
|
|
// Pointers are passed directly by value, so we don't need to assign them back either (they don't change).
|
|
|
|
|
if ((p.Flow == FlowDirection.Out || p.Flow == FlowDirection.Undefined) && p.Reference)
|
2009-02-22 10:43:35 +00:00
|
|
|
|
{
|
|
|
|
|
assign_statements.Add(String.Format("{0} = *{0}_ptr;", p.Name));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
p.Name = p.Name + "_ptr";
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
throw new ApplicationException("Unknown parameter type");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2009-03-25 17:55:37 +00:00
|
|
|
|
// Automatic OpenGL error checking.
|
|
|
|
|
// See OpenTK.Graphics.ErrorHelper for more information.
|
|
|
|
|
// Make sure that no error checking is added to the GetError function,
|
|
|
|
|
// as that would cause infinite recursion!
|
2009-08-11 14:06:40 +00:00
|
|
|
|
if ((Settings.Compatibility & Settings.Legacy.NoDebugHelpers) == 0)
|
2009-03-25 17:55:37 +00:00
|
|
|
|
{
|
2009-08-11 14:06:40 +00:00
|
|
|
|
if (f.TrimmedName != "GetError")
|
|
|
|
|
{
|
|
|
|
|
f.Body.Add("#if DEBUG");
|
|
|
|
|
f.Body.Add("using (new ErrorHelper(GraphicsContext.CurrentContext))");
|
|
|
|
|
f.Body.Add("{");
|
|
|
|
|
if (f.TrimmedName == "Begin")
|
|
|
|
|
f.Body.Add("GraphicsContext.CurrentContext.ErrorChecking = false;");
|
|
|
|
|
f.Body.Add("#endif");
|
|
|
|
|
}
|
2009-03-25 17:55:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!f.Unsafe && fixed_statements.Count > 0)
|
2009-02-22 10:43:35 +00:00
|
|
|
|
{
|
|
|
|
|
f.Body.Add("unsafe");
|
|
|
|
|
f.Body.Add("{");
|
|
|
|
|
f.Body.Indent();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (fixed_statements.Count > 0)
|
|
|
|
|
{
|
|
|
|
|
f.Body.AddRange(fixed_statements);
|
|
|
|
|
f.Body.Add("{");
|
|
|
|
|
f.Body.Indent();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (handle_statements.Count > 0)
|
|
|
|
|
{
|
|
|
|
|
f.Body.AddRange(handle_statements);
|
|
|
|
|
f.Body.Add("try");
|
|
|
|
|
f.Body.Add("{");
|
|
|
|
|
f.Body.Indent();
|
|
|
|
|
}
|
|
|
|
|
|
2009-10-28 23:09:25 +00:00
|
|
|
|
// Hack: When creating untyped enum wrappers, it is possible that the wrapper uses an "All"
|
|
|
|
|
// enum, while the delegate uses a specific enum (e.g. "TextureUnit"). For this reason, we need
|
|
|
|
|
// to modify the parameters before generating the call string.
|
|
|
|
|
// Note: We cannot generate a callstring using WrappedDelegate directly, as its parameters will
|
|
|
|
|
// typically be different than the parameters of the wrapper. We need to modify the parameters
|
|
|
|
|
// of the wrapper directly.
|
|
|
|
|
if ((Settings.Compatibility & Settings.Legacy.KeepUntypedEnums) != 0)
|
|
|
|
|
{
|
|
|
|
|
int parameter_index = -1; // Used for comparing wrapper parameters with delegate parameters
|
|
|
|
|
foreach (Parameter p in f.Parameters)
|
|
|
|
|
{
|
|
|
|
|
parameter_index++;
|
|
|
|
|
if (p.IsEnum && p.QualifiedType != f.WrappedDelegate.Parameters[parameter_index].QualifiedType)
|
|
|
|
|
{
|
|
|
|
|
p.QualifiedType = f.WrappedDelegate.Parameters[parameter_index].QualifiedType;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2009-02-22 10:43:35 +00:00
|
|
|
|
if (assign_statements.Count > 0)
|
|
|
|
|
{
|
|
|
|
|
// Call function
|
2009-10-28 23:09:25 +00:00
|
|
|
|
string method_call = f.CallString();
|
2009-02-22 10:43:35 +00:00
|
|
|
|
if (f.ReturnType.CurrentType.ToLower().Contains("void"))
|
2009-10-28 23:09:25 +00:00
|
|
|
|
f.Body.Add(String.Format("{0};", method_call));
|
2009-02-22 10:43:35 +00:00
|
|
|
|
else if (ReturnType.CurrentType.ToLower().Contains("string"))
|
2009-11-03 12:59:25 +00:00
|
|
|
|
f.Body.Add(String.Format("{0} {1} = null; unsafe {{ {1} = new string((sbyte*){2}); }}",
|
2009-10-28 23:09:25 +00:00
|
|
|
|
ReturnType.QualifiedType, "retval", method_call));
|
2009-02-22 10:43:35 +00:00
|
|
|
|
else
|
2009-10-28 23:09:25 +00:00
|
|
|
|
f.Body.Add(String.Format("{0} {1} = {2};", f.ReturnType.QualifiedType, "retval", method_call));
|
2009-02-22 10:43:35 +00:00
|
|
|
|
|
|
|
|
|
// Assign out parameters
|
|
|
|
|
f.Body.AddRange(assign_statements);
|
|
|
|
|
|
|
|
|
|
// Return
|
|
|
|
|
if (!f.ReturnType.CurrentType.ToLower().Contains("void"))
|
|
|
|
|
{
|
|
|
|
|
f.Body.Add("return retval;");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// Call function and return
|
|
|
|
|
if (f.ReturnType.CurrentType.ToLower().Contains("void"))
|
|
|
|
|
f.Body.Add(String.Format("{0};", f.CallString()));
|
|
|
|
|
else if (ReturnType.CurrentType.ToLower().Contains("string"))
|
2009-11-03 12:59:25 +00:00
|
|
|
|
f.Body.Add(String.Format("unsafe {{ return new string((sbyte*){0}); }}",
|
2009-10-28 23:09:25 +00:00
|
|
|
|
f.CallString()));
|
2009-02-22 10:43:35 +00:00
|
|
|
|
else
|
|
|
|
|
f.Body.Add(String.Format("return {0};", f.CallString()));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Free all allocated GCHandles
|
|
|
|
|
if (handle_statements.Count > 0)
|
|
|
|
|
{
|
|
|
|
|
f.Body.Unindent();
|
|
|
|
|
f.Body.Add("}");
|
|
|
|
|
f.Body.Add("finally");
|
|
|
|
|
f.Body.Add("{");
|
|
|
|
|
f.Body.Indent();
|
|
|
|
|
|
|
|
|
|
f.Body.AddRange(handle_release_statements);
|
|
|
|
|
|
|
|
|
|
f.Body.Unindent();
|
|
|
|
|
f.Body.Add("}");
|
|
|
|
|
}
|
|
|
|
|
|
2009-03-25 17:55:37 +00:00
|
|
|
|
if (!f.Unsafe && fixed_statements.Count > 0)
|
2009-02-22 10:43:35 +00:00
|
|
|
|
{
|
|
|
|
|
f.Body.Unindent();
|
|
|
|
|
f.Body.Add("}");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (fixed_statements.Count > 0)
|
|
|
|
|
{
|
|
|
|
|
f.Body.Unindent();
|
|
|
|
|
f.Body.Add("}");
|
|
|
|
|
}
|
|
|
|
|
|
2009-08-11 14:06:40 +00:00
|
|
|
|
if ((Settings.Compatibility & Settings.Legacy.NoDebugHelpers) == 0)
|
2009-03-25 17:55:37 +00:00
|
|
|
|
{
|
2009-08-11 14:06:40 +00:00
|
|
|
|
if (f.TrimmedName != "GetError")
|
|
|
|
|
{
|
|
|
|
|
f.Body.Add("#if DEBUG");
|
|
|
|
|
if (f.TrimmedName == "End")
|
|
|
|
|
f.Body.Add("GraphicsContext.CurrentContext.ErrorChecking = true;");
|
|
|
|
|
f.Body.Add("}");
|
|
|
|
|
f.Body.Add("#endif");
|
|
|
|
|
}
|
2009-03-25 17:55:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
2009-08-25 15:59:57 +00:00
|
|
|
|
Body = f.Body;
|
2009-02-22 10:43:35 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endregion
|
2009-05-30 15:28:52 +00:00
|
|
|
|
|
|
|
|
|
#region IComparable<Function> Members
|
|
|
|
|
|
|
|
|
|
public int CompareTo(Function other)
|
|
|
|
|
{
|
2009-08-11 14:06:40 +00:00
|
|
|
|
int ret = Name.CompareTo(other.Name);
|
|
|
|
|
if (ret == 0)
|
2009-11-17 09:33:14 +00:00
|
|
|
|
ret = Parameters.CompareTo(other.Parameters);
|
2009-08-11 14:06:40 +00:00
|
|
|
|
if (ret == 0)
|
2009-11-17 09:33:14 +00:00
|
|
|
|
ret = ReturnType.CompareTo(other.ReturnType);
|
2009-08-11 14:06:40 +00:00
|
|
|
|
return ret;
|
2009-05-30 15:28:52 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endregion
|
2009-02-22 10:43:35 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#region class FunctionBody : List<string>
|
|
|
|
|
|
|
|
|
|
public class FunctionBody : List<string>
|
|
|
|
|
{
|
|
|
|
|
public FunctionBody()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public FunctionBody(FunctionBody fb)
|
|
|
|
|
{
|
|
|
|
|
foreach (string s in fb)
|
|
|
|
|
{
|
2009-08-25 15:59:57 +00:00
|
|
|
|
Add(s);
|
2009-02-22 10:43:35 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private string indent = "";
|
|
|
|
|
|
|
|
|
|
public void Indent()
|
|
|
|
|
{
|
|
|
|
|
indent += " ";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void Unindent()
|
|
|
|
|
{
|
|
|
|
|
if (indent.Length >= 4)
|
|
|
|
|
indent = indent.Substring(4);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
new public void Add(string s)
|
|
|
|
|
{
|
|
|
|
|
base.Add(indent + s);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
new public void AddRange(IEnumerable<string> collection)
|
|
|
|
|
{
|
|
|
|
|
foreach (string t in collection)
|
|
|
|
|
{
|
2009-08-25 15:59:57 +00:00
|
|
|
|
Add(t);
|
2009-02-22 10:43:35 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override string ToString()
|
|
|
|
|
{
|
2009-08-25 15:59:57 +00:00
|
|
|
|
if (Count == 0)
|
2009-02-22 10:43:35 +00:00
|
|
|
|
return String.Empty;
|
|
|
|
|
|
2009-08-25 15:59:57 +00:00
|
|
|
|
StringBuilder sb = new StringBuilder(Count);
|
2009-02-22 10:43:35 +00:00
|
|
|
|
|
|
|
|
|
sb.AppendLine("{");
|
|
|
|
|
foreach (string s in this)
|
|
|
|
|
{
|
|
|
|
|
sb.AppendLine(" " + s);
|
|
|
|
|
}
|
|
|
|
|
sb.Append("}");
|
|
|
|
|
|
|
|
|
|
return sb.ToString();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
2009-05-29 15:57:01 +00:00
|
|
|
|
#region class FunctionCollection : SortedDictionary<string, List<Function>>
|
2009-02-22 10:43:35 +00:00
|
|
|
|
|
2009-05-29 15:57:01 +00:00
|
|
|
|
class FunctionCollection : SortedDictionary<string, List<Function>>
|
2009-02-22 10:43:35 +00:00
|
|
|
|
{
|
|
|
|
|
Regex unsignedFunctions = new Regex(@".+(u[dfisb]v?)", RegexOptions.Compiled);
|
|
|
|
|
|
|
|
|
|
public void Add(Function f)
|
|
|
|
|
{
|
2009-08-25 15:59:57 +00:00
|
|
|
|
if (!ContainsKey(f.Extension))
|
2009-02-22 10:43:35 +00:00
|
|
|
|
{
|
2009-08-25 15:59:57 +00:00
|
|
|
|
Add(f.Extension, new List<Function>());
|
2009-02-22 10:43:35 +00:00
|
|
|
|
this[f.Extension].Add(f);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
this[f.Extension].Add(f);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void AddRange(IEnumerable<Function> functions)
|
|
|
|
|
{
|
|
|
|
|
foreach (Function f in functions)
|
|
|
|
|
{
|
2009-08-25 15:59:57 +00:00
|
|
|
|
Add(f);
|
2009-02-22 10:43:35 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2009-03-08 19:19:52 +00:00
|
|
|
|
/// Adds the function to the collection, if a function with the same name and parameters doesn't already exist.
|
2009-02-22 10:43:35 +00:00
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="f">The Function to add.</param>
|
|
|
|
|
public void AddChecked(Function f)
|
|
|
|
|
{
|
2009-08-21 20:28:14 +00:00
|
|
|
|
if (Function.Wrappers.ContainsKey(f.Extension))
|
2009-02-22 10:43:35 +00:00
|
|
|
|
{
|
2009-08-21 20:28:14 +00:00
|
|
|
|
int index = Function.Wrappers[f.Extension].IndexOf(f);
|
2009-02-22 10:43:35 +00:00
|
|
|
|
if (index == -1)
|
|
|
|
|
{
|
2009-08-21 20:28:14 +00:00
|
|
|
|
Function.Wrappers.Add(f);
|
2009-02-22 10:43:35 +00:00
|
|
|
|
}
|
2009-03-08 22:00:13 +00:00
|
|
|
|
else
|
|
|
|
|
{
|
2009-08-21 20:28:14 +00:00
|
|
|
|
Function existing = Function.Wrappers[f.Extension][index];
|
2009-03-08 22:00:13 +00:00
|
|
|
|
if ((existing.Parameters.HasUnsignedParameters && !unsignedFunctions.IsMatch(existing.Name) && unsignedFunctions.IsMatch(f.Name)) ||
|
|
|
|
|
(!existing.Parameters.HasUnsignedParameters && unsignedFunctions.IsMatch(existing.Name) && !unsignedFunctions.IsMatch(f.Name)))
|
|
|
|
|
{
|
2009-08-21 20:28:14 +00:00
|
|
|
|
Function.Wrappers[f.Extension].RemoveAt(index);
|
|
|
|
|
Function.Wrappers[f.Extension].Add(f);
|
2009-03-08 22:00:13 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2009-02-22 10:43:35 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2009-08-21 20:28:14 +00:00
|
|
|
|
Function.Wrappers.Add(f);
|
2009-02-22 10:43:35 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
}
|