97e07a6e24
* Main.cs: Removed unused comments. Improved parameter handling. Added -o:keep_untyped_parameters option. * Settings.cs: Added KeepUntypedEnums compatibility setting. * Structures/Delegate.cs: Removed stale comments. Refactored CreateWrappers() method to support untyped enum overload generation and simplified method implementation. Replaced CurrentType translations with QualifiedType. * Structures/Function.cs: Removed stale code. Fixed copy constructors to copy all necessary fields. Use QualifiedType instead of CurrentType in WrapReturnType and CreateBody methods. Made Body statement lists static to improve performance. Added hack to modify callstring casts in keep_untyped_enums wrappers. Generate call string from the Function CreateBody was called on, rather than the current Function (solves issues with invalid casts in specific cases). * Structures/Parameter.cs: Use fully qualified type instead of current type in several caeses. * Structures/Type.cs: Added explicit support for fully qualified types.
831 lines
32 KiB
C#
831 lines
32 KiB
C#
#region --- License ---
|
|
/* Copyright (c) 2006, 2007 Stefanos Apostolopoulos
|
|
* See license.txt for license info
|
|
*/
|
|
#endregion
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Text.RegularExpressions;
|
|
using System.Xml.XPath;
|
|
using Bind.Structures;
|
|
using Delegate=Bind.Structures.Delegate;
|
|
using Enum=Bind.Structures.Enum;
|
|
using Type=Bind.Structures.Type;
|
|
|
|
namespace Bind.GL2
|
|
{
|
|
class Generator : IBind
|
|
{
|
|
#region --- Fields ---
|
|
|
|
protected static string glTypemap = "GL2/gl.tm";
|
|
protected static string csTypemap = "csharp.tm";
|
|
protected static string enumSpec = "GL2/enum.spec";
|
|
protected static string enumSpecExt = "GL2/enumext.spec";
|
|
protected static string glSpec = "GL2/gl.spec";
|
|
protected static string glSpecExt = "";
|
|
|
|
protected static string importsFile = "GLCore.cs";
|
|
protected static string delegatesFile = "GLDelegates.cs";
|
|
protected static string enumsFile = "GLEnums.cs";
|
|
protected static string wrappersFile = "GL.cs";
|
|
|
|
protected static string functionOverridesFile = "GL2/gloverrides.xml";
|
|
|
|
protected static string loadAllFuncName = "LoadAll";
|
|
|
|
protected static Regex enumToDotNet = new Regex("_[a-z|A-Z]?", RegexOptions.Compiled);
|
|
|
|
protected static readonly char[] numbers = "0123456789".ToCharArray();
|
|
//protected static readonly Dictionary<string, string> doc_replacements;
|
|
#endregion
|
|
|
|
#region --- Constructors ---
|
|
|
|
public Generator()
|
|
{
|
|
if (Settings.Compatibility == Settings.Legacy.Tao)
|
|
{
|
|
Settings.OutputNamespace = "Tao.OpenGl";
|
|
Settings.OutputClass = "Gl";
|
|
}
|
|
else
|
|
{
|
|
// Defaults
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region public void Process()
|
|
|
|
public virtual void Process()
|
|
{
|
|
// Matches functions that cannot have their trailing 'v' trimmed for CLS-Compliance reasons.
|
|
// Built through trial and error :)
|
|
//Function.endingsAddV =
|
|
// new Regex(@"(Coord1|Attrib(I?)1(u?)|Stream1|Uniform2(u?)|(Point|Convolution|Transform|Sprite|List|Combiner|Tex)Parameter|Fog(Coord)?.*|VertexWeight|(Fragment)?Light(Model)?|Material|ReplacementCodeu?b?|Tex(Gen|Env)|Indexu?|TextureParameter.v)",
|
|
// RegexOptions.Compiled);
|
|
|
|
Type.Initialize(glTypemap, csTypemap);
|
|
Enum.Initialize(enumSpec, enumSpecExt);
|
|
Enum.GLEnums.Translate(new XPathDocument(Path.Combine(Settings.InputPath, functionOverridesFile)));
|
|
Function.Initialize();
|
|
Delegate.Initialize(glSpec, glSpecExt);
|
|
|
|
WriteBindings(
|
|
Delegate.Delegates,
|
|
Function.Wrappers,
|
|
Enum.GLEnums);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region private void Translate()
|
|
#if false
|
|
protected virtual void Translate()
|
|
{
|
|
Bind.Structures.Enum.GLEnums.Translate();
|
|
}
|
|
#endif
|
|
#endregion
|
|
|
|
#region ISpecReader Members
|
|
|
|
#region public virtual DelegateCollection ReadDelegates(StreamReader specFile)
|
|
|
|
public virtual DelegateCollection ReadDelegates(StreamReader specFile)
|
|
{
|
|
Console.WriteLine("Reading function specs.");
|
|
|
|
DelegateCollection delegates = new DelegateCollection();
|
|
|
|
XPathDocument function_overrides = new XPathDocument(Path.Combine(Settings.InputPath, functionOverridesFile));
|
|
|
|
do
|
|
{
|
|
string line = NextValidLine(specFile);
|
|
if (String.IsNullOrEmpty(line))
|
|
break;
|
|
|
|
while (line.Contains("(") && !specFile.EndOfStream)
|
|
{
|
|
// Get next OpenGL function
|
|
|
|
Delegate d = new Delegate();
|
|
|
|
// Get function name:
|
|
d.Name = line.Split(Utilities.Separators, StringSplitOptions.RemoveEmptyEntries)[0];
|
|
|
|
do
|
|
{
|
|
// Get function parameters and return value
|
|
|
|
line = specFile.ReadLine();
|
|
List<string> words = new List<string>(
|
|
line.Replace('\t', ' ').Split(Utilities.Separators, StringSplitOptions.RemoveEmptyEntries)
|
|
);
|
|
|
|
if (words.Count == 0)
|
|
break;
|
|
|
|
// Identify line:
|
|
switch (words[0])
|
|
{
|
|
case "return": // Line denotes return value
|
|
d.ReturnType.CurrentType = words[1];
|
|
break;
|
|
|
|
case "param": // Line denotes parameter
|
|
Parameter p = new Parameter();
|
|
|
|
p.Name = Utilities.Keywords.Contains(words[1]) ? "@" + words[1] : words[1];
|
|
p.CurrentType = words[2];
|
|
p.Pointer += words[4].Contains("array") ? 1 : 0;
|
|
p.Pointer += words[4].Contains("reference") ? 1 : 0;
|
|
if (p.Pointer != 0 && words.Count > 5 && words[5].Contains("[1]"))
|
|
p.ElementCount = 1;
|
|
p.Flow = words[3] == "in" ? FlowDirection.In : FlowDirection.Out;
|
|
|
|
d.Parameters.Add(p);
|
|
break;
|
|
|
|
// GetTexParameterIivEXT and GetTexParameterIuivEXT define two(!) versions (why?)
|
|
case "version": // Line denotes function version (i.e. 1.0, 1.2, 1.5)
|
|
d.Version = words[1];
|
|
break;
|
|
|
|
case "category":
|
|
d.Category = words[1];
|
|
break;
|
|
}
|
|
}
|
|
while (!specFile.EndOfStream);
|
|
|
|
d.Translate(function_overrides);
|
|
|
|
delegates.Add(d);
|
|
}
|
|
}
|
|
while (!specFile.EndOfStream);
|
|
|
|
return delegates;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region public virtual EnumCollection ReadEnums(StreamReader specFile)
|
|
|
|
public virtual EnumCollection ReadEnums(StreamReader specFile)
|
|
{
|
|
Trace.WriteLine("Reading opengl enumerant specs.");
|
|
Trace.Indent();
|
|
|
|
EnumCollection enums = new EnumCollection();
|
|
|
|
// complete_enum contains all opengl enumerants.
|
|
Enum complete_enum = new Enum();
|
|
complete_enum.Name = Settings.CompleteEnumName;
|
|
|
|
do
|
|
{
|
|
string line = NextValidLine(specFile);
|
|
if (String.IsNullOrEmpty(line))
|
|
break;
|
|
|
|
line = line.Replace('\t', ' ');
|
|
|
|
// We just encountered the start of a new enumerant:
|
|
while (!String.IsNullOrEmpty(line) && line.Contains("enum"))
|
|
{
|
|
string[] words = line.Split(Utilities.Separators, StringSplitOptions.RemoveEmptyEntries);
|
|
if (words.Length == 0)
|
|
continue;
|
|
|
|
// Declare a new enumerant
|
|
Enum e = new Enum();
|
|
e.Name = Char.IsDigit(words[0][0]) ? Settings.ConstantPrefix + words[0] : words[0];
|
|
|
|
// And fill in the values for this enumerant
|
|
do
|
|
{
|
|
line = NextValidLine(specFile);
|
|
|
|
if (String.IsNullOrEmpty(line) || line.StartsWith("#"))
|
|
continue;
|
|
|
|
if (line.Contains("enum:") || specFile.EndOfStream)
|
|
break;
|
|
|
|
line = line.Replace('\t', ' ');
|
|
words = line.Split(Utilities.Separators, StringSplitOptions.RemoveEmptyEntries);
|
|
|
|
if (words.Length == 0)
|
|
continue;
|
|
|
|
// If we reach this point, we have found a new value for the current enumerant
|
|
Constant c = new Constant();
|
|
if (line.Contains("="))
|
|
{
|
|
// Trim the name's prefix, but only if not in Tao compat mode.
|
|
if (Settings.Compatibility == Settings.Legacy.Tao)
|
|
{
|
|
}
|
|
else
|
|
{
|
|
if (words[0].StartsWith(Settings.ConstantPrefix))
|
|
words[0] = words[0].Substring(Settings.ConstantPrefix.Length);
|
|
|
|
if (Char.IsDigit(words[0][0]))
|
|
words[0] = Settings.ConstantPrefix + words[0];
|
|
}
|
|
|
|
c.Name = words[0];
|
|
c.Value = words[2];
|
|
}
|
|
else if (words[0] == "use")
|
|
{
|
|
// Trim the prefix.
|
|
if (words[2].StartsWith(Settings.ConstantPrefix))
|
|
words[2] = words[2].Substring(Settings.ConstantPrefix.Length);
|
|
|
|
// If the remaining string starts with a digit, we were wrong above.
|
|
// Re-add the "GL_"
|
|
if (Char.IsDigit(words[2][0]))
|
|
words[2] = Settings.ConstantPrefix + words[2];
|
|
|
|
c.Name = words[2];
|
|
c.Reference = words[1];
|
|
c.Value = words[2];
|
|
}
|
|
else
|
|
{
|
|
// Typical cause is hand-editing the specs and forgetting to add an '=' sign.
|
|
throw new InvalidOperationException(String.Format(
|
|
"[Error] Invalid constant definition: \"{0}\"", line));
|
|
}
|
|
|
|
//if (!String.IsNullOrEmpty(c.Name) && !e.Members.Contains.Contains(c))
|
|
//SpecTranslator.Merge(e.Members, c);
|
|
if (!e.ConstantCollection.ContainsKey(c.Name))
|
|
e.ConstantCollection.Add(c.Name, c);
|
|
else
|
|
Trace.WriteLine(String.Format(
|
|
"Spec error: Constant {0} defined twice in enum {1}, discarding last definition.",
|
|
c.Name, e.Name));
|
|
|
|
// Insert the current constant in the list of all constants.
|
|
//SpecTranslator.Merge(complete_enum.Members, c);
|
|
complete_enum = Utilities.Merge(complete_enum, c);
|
|
}
|
|
while (!specFile.EndOfStream);
|
|
|
|
// At this point, the complete value list for the current enumerant has been read, so add this
|
|
// enumerant to the list.
|
|
//e.StartDirectives.Add(new CodeRegionDirective(CodeRegionMode.Start, "public enum " + e.Name));
|
|
//e.EndDirectives.Add(new CodeRegionDirective(CodeRegionMode.End, "public enum " + e.Name));
|
|
|
|
// (disabled) Hack - discard Boolean enum, it fsucks up the fragile translation code ahead.
|
|
//if (!e.Name.Contains("Bool"))
|
|
//Utilities.Merge(enums, e);
|
|
|
|
//e.Translate();
|
|
|
|
if (!enums.ContainsKey(e.Name))
|
|
enums.Add(e.Name, e);
|
|
else
|
|
{
|
|
// The enum already exists, merge constants.
|
|
foreach (Constant t in e.ConstantCollection.Values)
|
|
Utilities.Merge(enums[e.Name], t);
|
|
}
|
|
}
|
|
}
|
|
while (!specFile.EndOfStream);
|
|
|
|
enums.Add(complete_enum.Name, complete_enum);
|
|
|
|
Trace.Unindent();
|
|
|
|
return enums;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region public virtual Dictionary<string, string> ReadTypeMap(StreamReader specFile)
|
|
|
|
public virtual Dictionary<string, string> ReadTypeMap(StreamReader specFile)
|
|
{
|
|
Console.WriteLine("Reading opengl types.");
|
|
Dictionary<string, string> GLTypes = new Dictionary<string, string>();
|
|
|
|
if (specFile == null)
|
|
return GLTypes;
|
|
|
|
do
|
|
{
|
|
string line = specFile.ReadLine();
|
|
|
|
if (String.IsNullOrEmpty(line) || line.StartsWith("#"))
|
|
continue;
|
|
|
|
string[] words = line.Split(" ,*\t".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
|
|
|
|
if (words[0].ToLower() == "void")
|
|
{
|
|
// Special case for "void" -> "". We make it "void" -> "void"
|
|
GLTypes.Add(words[0], "void");
|
|
}
|
|
else if (words[0] == "VoidPointer" || words[0] == "ConstVoidPointer")
|
|
{
|
|
// "(Const)VoidPointer" -> "void*"
|
|
GLTypes.Add(words[0], "void*");
|
|
}
|
|
else if (words[0] == "CharPointer" || words[0] == "charPointerARB")
|
|
{
|
|
// The typematching logic cannot handle pointers to pointers, e.g. CharPointer* -> char** -> string* -> string[].
|
|
// Hence we give it a push.
|
|
// Note: When both CurrentType == "String" and Pointer == true, the typematching is hardcoded to use
|
|
// String[] or StringBuilder[].
|
|
GLTypes.Add(words[0], "String");
|
|
}
|
|
/*else if (words[0].Contains("Pointer"))
|
|
{
|
|
GLTypes.Add(words[0], words[1].Replace("Pointer", "*"));
|
|
}*/
|
|
else if (words[1].Contains("GLvoid"))
|
|
{
|
|
GLTypes.Add(words[0], "void");
|
|
}
|
|
else
|
|
{
|
|
GLTypes.Add(words[0], words[1]);
|
|
}
|
|
}
|
|
while (!specFile.EndOfStream);
|
|
|
|
return GLTypes;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region public virtual Dictionary<string, string> ReadCSTypeMap(StreamReader specFile)
|
|
|
|
public virtual Dictionary<string, string> ReadCSTypeMap(StreamReader specFile)
|
|
{
|
|
Dictionary<string, string> CSTypes = new Dictionary<string, string>();
|
|
Console.WriteLine("Reading C# types.");
|
|
|
|
while (!specFile.EndOfStream)
|
|
{
|
|
string line = specFile.ReadLine();
|
|
if (String.IsNullOrEmpty(line) || line.StartsWith("#"))
|
|
continue;
|
|
|
|
string[] words = line.Split(" ,\t".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
|
|
if (words.Length < 2)
|
|
continue;
|
|
|
|
if (((Settings.Compatibility & Settings.Legacy.NoBoolParameters) != Settings.Legacy.None) && words[1] == "bool")
|
|
words[1] = "Int32";
|
|
|
|
CSTypes.Add(words[0], words[1]);
|
|
}
|
|
|
|
return CSTypes;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region private string NextValidLine(StreamReader sr)
|
|
|
|
private string NextValidLine(StreamReader sr)
|
|
{
|
|
string line;
|
|
|
|
do
|
|
{
|
|
if (sr.EndOfStream)
|
|
return null;
|
|
|
|
line = sr.ReadLine().Trim();
|
|
|
|
if (String.IsNullOrEmpty(line) ||
|
|
line.StartsWith("#") || // Disregard comments.
|
|
line.StartsWith("passthru") || // Disregard passthru statements.
|
|
line.StartsWith("required-props:") ||
|
|
line.StartsWith("param:") ||
|
|
line.StartsWith("dlflags:") ||
|
|
line.StartsWith("glxflags:") ||
|
|
line.StartsWith("vectorequiv:") ||
|
|
//line.StartsWith("category:") ||
|
|
line.StartsWith("version:") ||
|
|
line.StartsWith("glxsingle:") ||
|
|
line.StartsWith("glxropcode:") ||
|
|
line.StartsWith("glxvendorpriv:") ||
|
|
line.StartsWith("glsflags:") ||
|
|
line.StartsWith("glsopcode:") ||
|
|
line.StartsWith("glsalias:") ||
|
|
line.StartsWith("wglflags:") ||
|
|
line.StartsWith("extension:") ||
|
|
line.StartsWith("alias:") ||
|
|
line.StartsWith("offset:"))
|
|
continue;
|
|
|
|
return line;
|
|
}
|
|
while (true);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#endregion
|
|
|
|
#region ISpecWriter Members
|
|
|
|
#region void WriteBindings
|
|
|
|
public void WriteBindings(DelegateCollection delegates, FunctionCollection functions, EnumCollection enums)
|
|
{
|
|
Console.WriteLine("Writing bindings to {0}", Settings.OutputPath);
|
|
if (!Directory.Exists(Settings.OutputPath))
|
|
Directory.CreateDirectory(Settings.OutputPath);
|
|
|
|
string temp_enums_file = Path.GetTempFileName();
|
|
string temp_delegates_file = Path.GetTempFileName();
|
|
string temp_core_file = Path.GetTempFileName();
|
|
string temp_wrappers_file = Path.GetTempFileName();
|
|
|
|
// Enums
|
|
using (BindStreamWriter sw = new BindStreamWriter(temp_enums_file))
|
|
{
|
|
WriteLicense(sw);
|
|
|
|
sw.WriteLine("using System;");
|
|
sw.WriteLine();
|
|
|
|
if ((Settings.Compatibility & Settings.Legacy.NestedEnums) != Settings.Legacy.None)
|
|
{
|
|
sw.WriteLine("namespace {0}", Settings.OutputNamespace);
|
|
sw.WriteLine("{");
|
|
sw.Indent();
|
|
sw.WriteLine("static partial class {0}", Settings.OutputClass);
|
|
}
|
|
else
|
|
sw.WriteLine("namespace {0}", Settings.EnumsOutput);
|
|
|
|
sw.WriteLine("{");
|
|
|
|
sw.Indent();
|
|
WriteEnums(sw, Enum.GLEnums);
|
|
sw.Unindent();
|
|
|
|
if ((Settings.Compatibility & Settings.Legacy.NestedEnums) != Settings.Legacy.None)
|
|
{
|
|
sw.WriteLine("}");
|
|
sw.Unindent();
|
|
}
|
|
|
|
sw.WriteLine("}");
|
|
}
|
|
|
|
// Delegates
|
|
using (BindStreamWriter sw = new BindStreamWriter(temp_delegates_file))
|
|
{
|
|
WriteLicense(sw);
|
|
sw.WriteLine("namespace {0}", Settings.OutputNamespace);
|
|
sw.WriteLine("{");
|
|
sw.Indent();
|
|
|
|
sw.WriteLine("using System;");
|
|
sw.WriteLine("using System.Text;");
|
|
sw.WriteLine("using System.Runtime.InteropServices;");
|
|
|
|
sw.WriteLine("#pragma warning disable 0649");
|
|
WriteDelegates(sw, Delegate.Delegates);
|
|
|
|
sw.Unindent();
|
|
sw.WriteLine("}");
|
|
}
|
|
|
|
// Core
|
|
using (BindStreamWriter sw = new BindStreamWriter(temp_core_file))
|
|
{
|
|
WriteLicense(sw);
|
|
sw.WriteLine("namespace {0}", Settings.OutputNamespace);
|
|
sw.WriteLine("{");
|
|
sw.Indent();
|
|
//specWriter.WriteTypes(sw, Bind.Structures.Type.CSTypes);
|
|
sw.WriteLine("using System;");
|
|
sw.WriteLine("using System.Text;");
|
|
sw.WriteLine("using System.Runtime.InteropServices;");
|
|
|
|
WriteImports(sw, Delegate.Delegates);
|
|
|
|
sw.Unindent();
|
|
sw.WriteLine("}");
|
|
}
|
|
|
|
// Wrappers
|
|
using (BindStreamWriter sw = new BindStreamWriter(temp_wrappers_file))
|
|
{
|
|
WriteLicense(sw);
|
|
sw.WriteLine("namespace {0}", Settings.OutputNamespace);
|
|
sw.WriteLine("{");
|
|
sw.Indent();
|
|
|
|
sw.WriteLine("using System;");
|
|
sw.WriteLine("using System.Text;");
|
|
sw.WriteLine("using System.Runtime.InteropServices;");
|
|
|
|
WriteWrappers(sw, Function.Wrappers, Type.CSTypes);
|
|
|
|
sw.Unindent();
|
|
sw.WriteLine("}");
|
|
}
|
|
|
|
string output_enums = Path.Combine(Settings.OutputPath, enumsFile);
|
|
string output_delegates = Path.Combine(Settings.OutputPath, delegatesFile);
|
|
string output_core = Path.Combine(Settings.OutputPath, importsFile);
|
|
string output_wrappers = Path.Combine(Settings.OutputPath, wrappersFile);
|
|
|
|
if (File.Exists(output_enums)) File.Delete(output_enums);
|
|
if (File.Exists(output_delegates)) File.Delete(output_delegates);
|
|
if (File.Exists(output_core)) File.Delete(output_core);
|
|
if (File.Exists(output_wrappers)) File.Delete(output_wrappers);
|
|
|
|
File.Move(temp_enums_file, output_enums);
|
|
File.Move(temp_delegates_file, output_delegates);
|
|
File.Move(temp_core_file, output_core);
|
|
File.Move(temp_wrappers_file, output_wrappers);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region void WriteDelegates
|
|
|
|
public virtual void WriteDelegates(BindStreamWriter sw, DelegateCollection delegates)
|
|
{
|
|
Trace.WriteLine(String.Format("Writing delegates to:\t{0}.{1}.{2}", Settings.OutputNamespace, Settings.OutputClass, Settings.DelegatesClass));
|
|
|
|
sw.WriteLine("#pragma warning disable 3019"); // CLSCompliant attribute
|
|
sw.WriteLine("#pragma warning disable 1591"); // Missing doc comments
|
|
|
|
sw.WriteLine();
|
|
sw.WriteLine("partial class {0}", Settings.OutputClass);
|
|
sw.WriteLine("{");
|
|
sw.Indent();
|
|
|
|
sw.WriteLine("internal static partial class {0}", Settings.DelegatesClass);
|
|
sw.WriteLine("{");
|
|
sw.Indent();
|
|
|
|
foreach (Delegate d in delegates.Values)
|
|
{
|
|
sw.WriteLine("[System.Security.SuppressUnmanagedCodeSecurity()]");
|
|
sw.WriteLine("internal {0};", d.ToString());
|
|
sw.WriteLine("internal {0}static {1} {2}{1};", // = null
|
|
d.Unsafe ? "unsafe " : "",
|
|
d.Name,
|
|
Settings.FunctionPrefix);
|
|
}
|
|
|
|
sw.Unindent();
|
|
sw.WriteLine("}");
|
|
|
|
sw.Unindent();
|
|
sw.WriteLine("}");
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region void WriteImports
|
|
|
|
public virtual void WriteImports(BindStreamWriter sw, DelegateCollection delegates)
|
|
{
|
|
Trace.WriteLine(String.Format("Writing imports to:\t{0}.{1}.{2}", Settings.OutputNamespace, Settings.OutputClass, Settings.ImportsClass));
|
|
|
|
sw.WriteLine("#pragma warning disable 3019"); // CLSCompliant attribute
|
|
sw.WriteLine("#pragma warning disable 1591"); // Missing doc comments
|
|
|
|
sw.WriteLine();
|
|
sw.WriteLine("partial class {0}", Settings.OutputClass);
|
|
sw.WriteLine("{");
|
|
sw.Indent();
|
|
sw.WriteLine();
|
|
sw.WriteLine("internal static partial class {0}", Settings.ImportsClass);
|
|
sw.WriteLine("{");
|
|
sw.Indent();
|
|
//sw.WriteLine("static {0}() {1} {2}", Settings.ImportsClass, "{", "}"); // Disable BeforeFieldInit
|
|
sw.WriteLine();
|
|
foreach (Delegate d in delegates.Values)
|
|
{
|
|
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"
|
|
);
|
|
sw.WriteLine("internal extern static {0};", d.DeclarationString());
|
|
}
|
|
sw.Unindent();
|
|
sw.WriteLine("}");
|
|
sw.Unindent();
|
|
sw.WriteLine("}");
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region void WriteWrappers
|
|
|
|
public void WriteWrappers(BindStreamWriter sw, FunctionCollection wrappers, Dictionary<string, string> CSTypes)
|
|
{
|
|
Trace.WriteLine(String.Format("Writing wrappers to:\t{0}.{1}", Settings.OutputNamespace, Settings.OutputClass));
|
|
|
|
sw.WriteLine("#pragma warning disable 3019"); // CLSCompliant attribute
|
|
sw.WriteLine("#pragma warning disable 1591"); // Missing doc comments
|
|
sw.WriteLine("#pragma warning disable 1572"); // Wrong param comments
|
|
sw.WriteLine("#pragma warning disable 1573"); // Missing param comments
|
|
|
|
sw.WriteLine();
|
|
sw.WriteLine("partial class {0}", Settings.OutputClass);
|
|
sw.WriteLine("{");
|
|
|
|
sw.Indent();
|
|
//sw.WriteLine("static {0}() {1} {2}", className, "{", "}"); // Static init in GLHelper.cs
|
|
sw.WriteLine();
|
|
|
|
int current = 0;
|
|
foreach (string key in wrappers.Keys)
|
|
{
|
|
if (((Settings.Compatibility & Settings.Legacy.NoSeparateFunctionNamespaces) == Settings.Legacy.None) && key != "Core")
|
|
{
|
|
if (!Char.IsDigit(key[0]))
|
|
{
|
|
sw.WriteLine("public static partial class {0}", key);
|
|
}
|
|
else
|
|
{
|
|
// Identifiers cannot start with a number:
|
|
sw.WriteLine("public static partial class {0}{1}", Settings.ConstantPrefix, key);
|
|
}
|
|
sw.WriteLine("{");
|
|
sw.Indent();
|
|
}
|
|
|
|
wrappers[key].Sort();
|
|
foreach (Function f in wrappers[key])
|
|
{
|
|
current = WriteWrapper(sw, current, f);
|
|
}
|
|
|
|
if (((Settings.Compatibility & Settings.Legacy.NoSeparateFunctionNamespaces) == Settings.Legacy.None) && key != "Core")
|
|
{
|
|
sw.Unindent();
|
|
sw.WriteLine("}");
|
|
sw.WriteLine();
|
|
}
|
|
}
|
|
sw.Unindent();
|
|
sw.WriteLine("}");
|
|
}
|
|
|
|
private static int WriteWrapper(BindStreamWriter sw, int current, Function f)
|
|
{
|
|
if ((Settings.Compatibility & Settings.Legacy.NoDocumentation) == 0)
|
|
{
|
|
Console.WriteLine("Creating docs for #{0} ({1})", current++, f.Name);
|
|
WriteDocumentation(sw, f);
|
|
}
|
|
WriteMethod(sw, f);
|
|
return current;
|
|
}
|
|
|
|
private static void WriteMethod(BindStreamWriter sw, Function f)
|
|
{
|
|
if (!f.CLSCompliant)
|
|
{
|
|
sw.WriteLine("[System.CLSCompliant(false)]");
|
|
}
|
|
sw.WriteLine("[AutoGenerated(Category = \"{0}\", Version = \"{1}\", EntryPoint = \"{2}\")]",
|
|
f.Category, f.Version, Settings.FunctionPrefix + f.WrappedDelegate.Name);
|
|
sw.WriteLine("public static ");
|
|
sw.Write(f);
|
|
sw.WriteLine();
|
|
}
|
|
|
|
private static void WriteDocumentation(BindStreamWriter sw, Function f)
|
|
{
|
|
try
|
|
{
|
|
string path = Path.Combine(Settings.DocPath, Settings.FunctionPrefix + f.WrappedDelegate.Name + ".xml");
|
|
if (!File.Exists(path))
|
|
path = Path.Combine(Settings.DocPath, Settings.FunctionPrefix +
|
|
f.TrimmedName + ".xml");
|
|
|
|
if (!File.Exists(path))
|
|
path = Path.Combine(Settings.DocPath, Settings.FunctionPrefix + f.TrimmedName.TrimEnd(numbers) + ".xml");
|
|
|
|
if (File.Exists(path))
|
|
{
|
|
DocProcessor doc_processor = new DocProcessor(Path.Combine(Settings.DocPath, Settings.DocFile));
|
|
sw.WriteLine(doc_processor.ProcessFile(path));
|
|
}
|
|
}
|
|
catch (FileNotFoundException)
|
|
{ }
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region void WriteTypes
|
|
|
|
public void WriteTypes(BindStreamWriter sw, Dictionary<string, string> CSTypes)
|
|
{
|
|
sw.WriteLine();
|
|
foreach (string s in CSTypes.Keys)
|
|
{
|
|
sw.WriteLine("using {0} = System.{1};", s, CSTypes[s]);
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region void WriteEnums
|
|
|
|
public void WriteEnums(BindStreamWriter sw, EnumCollection enums)
|
|
{
|
|
//sw.WriteLine("#pragma warning disable 3019"); // CLSCompliant attribute
|
|
sw.WriteLine("#pragma warning disable 1591"); // Missing doc comments
|
|
sw.WriteLine();
|
|
|
|
if ((Settings.Compatibility & Settings.Legacy.NestedEnums) != Settings.Legacy.None)
|
|
Trace.WriteLine(String.Format("Writing enums to:\t{0}.{1}.{2}", Settings.OutputNamespace, Settings.OutputClass, Settings.NestedEnumsClass));
|
|
else
|
|
Trace.WriteLine(String.Format("Writing enums to:\t{0}", Settings.EnumsOutput));
|
|
|
|
if ((Settings.Compatibility & Settings.Legacy.ConstIntEnums) == Settings.Legacy.None)
|
|
{
|
|
if ((Settings.Compatibility & Settings.Legacy.NestedEnums) != Settings.Legacy.None &&
|
|
!String.IsNullOrEmpty(Settings.NestedEnumsClass))
|
|
{
|
|
sw.WriteLine("public class Enums");
|
|
sw.WriteLine("{");
|
|
sw.Indent();
|
|
}
|
|
|
|
foreach (Enum @enum in enums.Values)
|
|
{
|
|
sw.Write(@enum);
|
|
sw.WriteLine();
|
|
}
|
|
|
|
if ((Settings.Compatibility & Settings.Legacy.NestedEnums) != Settings.Legacy.None &&
|
|
!String.IsNullOrEmpty(Settings.NestedEnumsClass))
|
|
{
|
|
sw.Unindent();
|
|
sw.WriteLine("}");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Tao legacy mode: dump all enums as constants in GLClass.
|
|
foreach (Constant c in enums[Settings.CompleteEnumName].ConstantCollection.Values)
|
|
{
|
|
// Print constants avoiding circular definitions
|
|
if (c.Name != c.Value)
|
|
{
|
|
sw.WriteLine(String.Format(
|
|
"public const int {0} = {2}((int){1});",
|
|
c.Name.StartsWith(Settings.ConstantPrefix) ? c.Name : Settings.ConstantPrefix + c.Name,
|
|
Char.IsDigit(c.Value[0]) ? c.Value : c.Value.StartsWith(Settings.ConstantPrefix) ? c.Value : Settings.ConstantPrefix + c.Value,
|
|
c.Unchecked ? "unchecked" : ""));
|
|
}
|
|
else
|
|
{
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region void WriteLicense
|
|
|
|
public void WriteLicense(BindStreamWriter sw)
|
|
{
|
|
sw.WriteLine(File.ReadAllText(Path.Combine(Settings.InputPath, Settings.LicenseFile)));
|
|
sw.WriteLine();
|
|
}
|
|
|
|
#endregion
|
|
|
|
#endregion
|
|
}
|
|
}
|