Refactored spec reading / writing functionality into its own classes.
Removed legacy spec reader.
This commit is contained in:
parent
bdde353a9e
commit
0ce332b318
8 changed files with 958 additions and 1018 deletions
484
Source/Bind/CSharpSpecWriter.cs
Normal file
484
Source/Bind/CSharpSpecWriter.cs
Normal file
|
@ -0,0 +1,484 @@
|
|||
#region License
|
||||
//
|
||||
// The Open Toolkit Library License
|
||||
//
|
||||
// Copyright (c) 2006 - 2010 the Open Toolkit library.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights to
|
||||
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
// the Software, and to permit persons to whom the Software is furnished to do
|
||||
// so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Bind.Structures;
|
||||
|
||||
namespace Bind
|
||||
{
|
||||
using Delegate = Bind.Structures.Delegate;
|
||||
using Enum = Bind.Structures.Enum;
|
||||
using Type = Bind.Structures.Type;
|
||||
|
||||
sealed class CSharpSpecWriter : ISpecWriter
|
||||
{
|
||||
readonly string wrappersFile;
|
||||
readonly string enumsFile;
|
||||
readonly string delegatesFile;
|
||||
readonly string importsFile;
|
||||
readonly char[] numbers = "0123456789".ToCharArray();
|
||||
|
||||
public CSharpSpecWriter(string wrappersFile, string importsFile, string enumsFile, string delegatesFile)
|
||||
{
|
||||
this.wrappersFile = wrappersFile;
|
||||
this.importsFile = importsFile;
|
||||
this.enumsFile = enumsFile;
|
||||
this.delegatesFile = delegatesFile;
|
||||
}
|
||||
|
||||
#region WriteBindings
|
||||
|
||||
public void WriteBindings(DelegateCollection delegates, FunctionCollection wrappers, 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, enums);
|
||||
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, 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, 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, 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 WriteDelegates
|
||||
|
||||
public 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 WriteImports
|
||||
|
||||
public 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 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("}");
|
||||
}
|
||||
|
||||
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.Deprecated && Settings.IsEnabled(Settings.Legacy.AddDeprecationWarnings))
|
||||
{
|
||||
sw.WriteLine("[Obsolete(\"Deprecated in OpenGL {0}\")]", f.DeprecatedVersion);
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
static DocProcessor processor = new DocProcessor(Path.Combine(Settings.DocPath, Settings.DocFile));
|
||||
static Dictionary<string, string> docfiles;
|
||||
void WriteDocumentation(BindStreamWriter sw, Function f)
|
||||
{
|
||||
if (docfiles == null)
|
||||
{
|
||||
docfiles = new Dictionary<string, string>();
|
||||
foreach (string file in Directory.GetFiles(Settings.DocPath))
|
||||
{
|
||||
docfiles.Add(Path.GetFileName(file), file);
|
||||
}
|
||||
}
|
||||
|
||||
string docfile = null;
|
||||
try
|
||||
{
|
||||
docfile = Settings.FunctionPrefix + f.WrappedDelegate.Name + ".xml";
|
||||
if (!docfiles.ContainsKey(docfile))
|
||||
docfile = Settings.FunctionPrefix + f.TrimmedName + ".xml";
|
||||
if (!docfiles.ContainsKey(docfile))
|
||||
docfile = Settings.FunctionPrefix + f.TrimmedName.TrimEnd(numbers) + ".xml";
|
||||
|
||||
string doc = null;
|
||||
if (docfiles.ContainsKey(docfile))
|
||||
{
|
||||
doc = processor.ProcessFile(docfiles[docfile]);
|
||||
}
|
||||
if (doc == null)
|
||||
{
|
||||
doc = "/// <summary></summary>";
|
||||
}
|
||||
|
||||
int summary_start = doc.IndexOf("<summary>") + "<summary>".Length;
|
||||
string warning = "[deprecated: v{0}]";
|
||||
string category = "[requires: {0}]";
|
||||
if (f.Deprecated)
|
||||
{
|
||||
warning = String.Format(warning, f.DeprecatedVersion);
|
||||
doc = doc.Insert(summary_start, warning);
|
||||
}
|
||||
|
||||
if (f.Extension != "Core" && !String.IsNullOrEmpty(f.Category))
|
||||
{
|
||||
category = String.Format(category, f.Category);
|
||||
doc = doc.Insert(summary_start, category);
|
||||
}
|
||||
else if (!String.IsNullOrEmpty(f.Version))
|
||||
{
|
||||
if (f.Category.StartsWith("VERSION"))
|
||||
category = String.Format(category, "v" + f.Version);
|
||||
else
|
||||
category = String.Format(category, "v" + f.Version + " and " + f.Category);
|
||||
doc = doc.Insert(summary_start, category);
|
||||
}
|
||||
|
||||
sw.WriteLine(doc);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine("[Warning] Error processing file {0}: {1}", docfile, e.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 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 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 WriteLicense
|
||||
|
||||
public void WriteLicense(BindStreamWriter sw)
|
||||
{
|
||||
sw.WriteLine(File.ReadAllText(Path.Combine(Settings.InputPath, Settings.LicenseFile)));
|
||||
sw.WriteLine();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
|
@ -38,171 +38,5 @@ namespace Bind.ES
|
|||
Settings.OutputNamespace = "OpenTK.Graphics." + nsName;
|
||||
Settings.OutputPath = Path.Combine(Settings.OutputPath, dirName);
|
||||
}
|
||||
|
||||
public override DelegateCollection ReadDelegates(StreamReader specFile)
|
||||
{
|
||||
DelegateCollection delegates = new DelegateCollection();
|
||||
XPathDocument specs = new XPathDocument(specFile);
|
||||
XPathDocument overrides = new XPathDocument(new StreamReader(Path.Combine(Settings.InputPath, functionOverridesFile)));
|
||||
|
||||
foreach (XPathNavigator nav in new XPathNavigator[] {
|
||||
specs.CreateNavigator().SelectSingleNode("/signatures"),
|
||||
overrides.CreateNavigator().SelectSingleNode("/overrides/add") })
|
||||
{
|
||||
if (nav != null)
|
||||
{
|
||||
foreach (XPathNavigator node in nav.SelectChildren("function", String.Empty))
|
||||
{
|
||||
var name = node.GetAttribute("name", String.Empty);
|
||||
|
||||
// Check whether we are adding to an existing delegate or creating a new one.
|
||||
Delegate d = null;
|
||||
if (delegates.ContainsKey(name))
|
||||
{
|
||||
d = delegates[name];
|
||||
}
|
||||
else
|
||||
{
|
||||
d = new Delegate();
|
||||
d.Name = name;
|
||||
d.Version = node.GetAttribute("version", String.Empty);
|
||||
d.Category = node.GetAttribute("category", String.Empty);
|
||||
d.DeprecatedVersion = node.GetAttribute("deprecated", String.Empty);
|
||||
d.Deprecated = !String.IsNullOrEmpty(d.DeprecatedVersion);
|
||||
}
|
||||
|
||||
foreach (XPathNavigator param in node.SelectChildren(XPathNodeType.Element))
|
||||
{
|
||||
switch (param.Name)
|
||||
{
|
||||
case "returns":
|
||||
d.ReturnType.CurrentType = param.GetAttribute("type", String.Empty);
|
||||
break;
|
||||
|
||||
case "param":
|
||||
Parameter p = new Parameter();
|
||||
p.CurrentType = param.GetAttribute("type", String.Empty);
|
||||
p.Name = param.GetAttribute("name", String.Empty);
|
||||
|
||||
string element_count = param.GetAttribute("elementcount", String.Empty);
|
||||
if (String.IsNullOrEmpty(element_count))
|
||||
element_count = param.GetAttribute("count", String.Empty);
|
||||
if (!String.IsNullOrEmpty(element_count))
|
||||
p.ElementCount = Int32.Parse(element_count);
|
||||
|
||||
p.Flow = Parameter.GetFlowDirection(param.GetAttribute("flow", String.Empty));
|
||||
|
||||
d.Parameters.Add(p);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
delegates.Add(d);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return delegates;
|
||||
}
|
||||
|
||||
public override Dictionary<string, string> ReadTypeMap(StreamReader specFile)
|
||||
{
|
||||
return base.ReadTypeMap(specFile);
|
||||
}
|
||||
|
||||
public override Dictionary<string, string> ReadCSTypeMap(StreamReader specFile)
|
||||
{
|
||||
return base.ReadCSTypeMap(specFile);
|
||||
}
|
||||
|
||||
public override EnumCollection ReadEnums(StreamReader specFile)
|
||||
{
|
||||
// First, read all enum definitions from spec and override file.
|
||||
// Afterwards, read all token/enum overrides from overrides file.
|
||||
// Every single enum is merged into
|
||||
|
||||
EnumCollection enums = new EnumCollection();
|
||||
Enum all = new Enum() { Name = Settings.CompleteEnumName };
|
||||
XPathDocument specs = new XPathDocument(specFile);
|
||||
XPathDocument overrides = new XPathDocument(new StreamReader(Path.Combine(Settings.InputPath, functionOverridesFile)));
|
||||
|
||||
foreach (XPathNavigator nav in new XPathNavigator[] {
|
||||
specs.CreateNavigator().SelectSingleNode("/signatures"),
|
||||
overrides.CreateNavigator().SelectSingleNode("/overrides/add") })
|
||||
{
|
||||
if (nav != null)
|
||||
{
|
||||
foreach (XPathNavigator node in nav.SelectChildren("enum", String.Empty))
|
||||
{
|
||||
Enum e = new Enum()
|
||||
{
|
||||
Name = node.GetAttribute("name", String.Empty),
|
||||
Type = node.GetAttribute("type", String.Empty)
|
||||
};
|
||||
if (String.IsNullOrEmpty(e.Name))
|
||||
throw new InvalidOperationException(String.Format("Empty name for enum element {0}", node.ToString()));
|
||||
|
||||
foreach (XPathNavigator param in node.SelectChildren(XPathNodeType.Element))
|
||||
{
|
||||
Constant c = null;
|
||||
switch (param.Name)
|
||||
{
|
||||
case "token":
|
||||
c = new Constant
|
||||
{
|
||||
Name = param.GetAttribute("name", String.Empty),
|
||||
Value = param.GetAttribute("value", String.Empty)
|
||||
};
|
||||
break;
|
||||
|
||||
case "use":
|
||||
c = new Constant
|
||||
{
|
||||
Name = param.GetAttribute("token", String.Empty),
|
||||
Reference = param.GetAttribute("enum", String.Empty),
|
||||
Value = param.GetAttribute("token", String.Empty),
|
||||
};
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
Utilities.Merge(all, c);
|
||||
try
|
||||
{
|
||||
if (!e.ConstantCollection.ContainsKey(c.Name))
|
||||
{
|
||||
e.ConstantCollection.Add(c.Name, c);
|
||||
}
|
||||
else if (e.ConstantCollection[c.Name].Value != c.Value)
|
||||
{
|
||||
var existing = e.ConstantCollection[c.Name];
|
||||
if (existing.Reference != null && c.Reference == null)
|
||||
{
|
||||
e.ConstantCollection[c.Name] = c;
|
||||
}
|
||||
else if (existing.Reference == null && c.Reference != null)
|
||||
{ } // Keep existing
|
||||
else
|
||||
{
|
||||
Console.WriteLine("[Warning] Conflicting token {0}.{1} with value {2} != {3}",
|
||||
e.Name, c.Name, e.ConstantCollection[c.Name].Value, c.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (ArgumentException ex)
|
||||
{
|
||||
Console.WriteLine("[Warning] Failed to add constant {0} to enum {1}: {2}", c.Name, e.Name, ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
Utilities.Merge(enums, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Utilities.Merge(enums, all);
|
||||
return enums;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,31 @@
|
|||
using System;
|
||||
#region License
|
||||
//
|
||||
// The Open Toolkit Library License
|
||||
//
|
||||
// Copyright (c) 2006 - 2010 the Open Toolkit library.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights to
|
||||
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
// the Software, and to permit persons to whom the Software is furnished to do
|
||||
// so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
|
|
@ -20,7 +20,7 @@ namespace Bind.GL2
|
|||
{
|
||||
class Generator : IBind
|
||||
{
|
||||
#region --- Fields ---
|
||||
#region Fields
|
||||
|
||||
protected static string glTypemap = "GL2/gl.tm";
|
||||
protected static string csTypemap = "csharp.tm";
|
||||
|
@ -42,9 +42,14 @@ namespace Bind.GL2
|
|||
|
||||
protected static readonly char[] numbers = "0123456789".ToCharArray();
|
||||
//protected static readonly Dictionary<string, string> doc_replacements;
|
||||
|
||||
protected ISpecReader SpecReader = new XmlSpecReader(functionOverridesFile);
|
||||
protected ISpecWriter SpecWriter = new CSharpSpecWriter(wrappersFile, importsFile,
|
||||
enumsFile, delegatesFile);
|
||||
|
||||
#endregion
|
||||
|
||||
#region --- Constructors ---
|
||||
#region Constructors
|
||||
|
||||
public Generator()
|
||||
{
|
||||
|
@ -61,823 +66,30 @@ namespace Bind.GL2
|
|||
|
||||
#endregion
|
||||
|
||||
#region public void Process()
|
||||
#region Process
|
||||
|
||||
public virtual void Process()
|
||||
{
|
||||
var overrides = new XPathDocument(Path.Combine(Settings.InputPath, functionOverridesFile));
|
||||
var overrides = new XPathDocument(Path.Combine(Settings.InputPath, functionOverridesFile));
|
||||
|
||||
Type.Initialize(glTypemap, csTypemap);
|
||||
var enums = ReadEnums(new StreamReader(Path.Combine(Settings.InputPath, enumSpec)));
|
||||
var delegates = ReadDelegates(new StreamReader(Path.Combine(Settings.InputPath, glSpec)));
|
||||
using (StreamReader sr = Utilities.OpenSpecFile(Settings.InputPath, glTypemap))
|
||||
{
|
||||
Type.GLTypes = SpecReader.ReadTypeMap(sr);
|
||||
}
|
||||
using (StreamReader sr = Utilities.OpenSpecFile(Settings.InputPath, csTypemap))
|
||||
{
|
||||
Type.CSTypes = SpecReader.ReadCSTypeMap(sr);
|
||||
}
|
||||
|
||||
var enums = SpecReader.ReadEnums(new StreamReader(Path.Combine(Settings.InputPath, enumSpec)));
|
||||
var delegates = SpecReader.ReadDelegates(new StreamReader(Path.Combine(Settings.InputPath, glSpec)));
|
||||
|
||||
enums = new EnumProcessor(overrides).Process(enums);
|
||||
var wrappers = new FuncProcessor(overrides).Process(delegates, enums);
|
||||
|
||||
WriteBindings(delegates, wrappers, enums);
|
||||
SpecWriter.WriteBindings(delegates, wrappers, enums);
|
||||
}
|
||||
|
||||
#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;
|
||||
|
||||
case "deprecated":
|
||||
d.Deprecated = true;
|
||||
d.DeprecatedVersion = words[1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (!specFile.EndOfStream);
|
||||
|
||||
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 if (words[1] == "const" && words[2] == "GLubyte")
|
||||
{
|
||||
GLTypes.Add(words[0], "String");
|
||||
}
|
||||
else if (words[1] == "struct")
|
||||
{
|
||||
GLTypes.Add(words[0], words[2]);
|
||||
}
|
||||
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 wrappers, 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, enums);
|
||||
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, 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, 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, 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.Deprecated && Settings.IsEnabled(Settings.Legacy.AddDeprecationWarnings))
|
||||
{
|
||||
sw.WriteLine("[Obsolete(\"Deprecated in OpenGL {0}\")]", f.DeprecatedVersion);
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
static DocProcessor processor = new DocProcessor(Path.Combine(Settings.DocPath, Settings.DocFile));
|
||||
static Dictionary<string, string> docfiles;
|
||||
private static void WriteDocumentation(BindStreamWriter sw, Function f)
|
||||
{
|
||||
if (docfiles == null)
|
||||
{
|
||||
docfiles = new Dictionary<string, string>();
|
||||
foreach (string file in Directory.GetFiles(Settings.DocPath))
|
||||
{
|
||||
docfiles.Add(Path.GetFileName(file), file);
|
||||
}
|
||||
}
|
||||
|
||||
string docfile = null;
|
||||
try
|
||||
{
|
||||
docfile = Settings.FunctionPrefix + f.WrappedDelegate.Name + ".xml";
|
||||
if (!docfiles.ContainsKey(docfile))
|
||||
docfile = Settings.FunctionPrefix + f.TrimmedName + ".xml";
|
||||
if (!docfiles.ContainsKey(docfile))
|
||||
docfile = Settings.FunctionPrefix + f.TrimmedName.TrimEnd(numbers) + ".xml";
|
||||
|
||||
string doc = null;
|
||||
if (docfiles.ContainsKey(docfile))
|
||||
{
|
||||
doc = processor.ProcessFile(docfiles[docfile]);
|
||||
}
|
||||
if (doc == null)
|
||||
{
|
||||
doc = "/// <summary></summary>";
|
||||
}
|
||||
|
||||
int summary_start = doc.IndexOf("<summary>") + "<summary>".Length;
|
||||
string warning = "[deprecated: v{0}]";
|
||||
string category = "[requires: {0}]";
|
||||
if (f.Deprecated)
|
||||
{
|
||||
warning = String.Format(warning, f.DeprecatedVersion);
|
||||
doc = doc.Insert(summary_start, warning);
|
||||
}
|
||||
|
||||
if (f.Extension != "Core" && !String.IsNullOrEmpty(f.Category))
|
||||
{
|
||||
category = String.Format(category, f.Category);
|
||||
doc = doc.Insert(summary_start, category);
|
||||
}
|
||||
else if (!String.IsNullOrEmpty(f.Version))
|
||||
{
|
||||
if (f.Category.StartsWith("VERSION"))
|
||||
category = String.Format(category, "v" + f.Version);
|
||||
else
|
||||
category = String.Format(category, "v" + f.Version + " and " + f.Category);
|
||||
doc = doc.Insert(summary_start, category);
|
||||
}
|
||||
|
||||
sw.WriteLine(doc);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine("[Warning] Error processing file {0}: {1}", docfile, e.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
#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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -139,6 +139,7 @@
|
|||
<Compile Include="..\GlobalAssemblyInfo.cs">
|
||||
<Link>Properties\GlobalAssemblyInfo.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="CSharpSpecWriter.cs" />
|
||||
<Compile Include="FuncProcessor.cs" />
|
||||
<Compile Include="GL2\GL4Generator.cs" />
|
||||
<Compile Include="IBind.cs">
|
||||
|
@ -199,6 +200,7 @@
|
|||
<Compile Include="ES\ESGenerator.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="XmlSpecReader.cs" />
|
||||
<None Include="..\..\OpenTK.snk">
|
||||
<Link>OpenTK.snk</Link>
|
||||
</None>
|
||||
|
@ -938,9 +940,125 @@
|
|||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="Specifications\GL2\signatures.xml">
|
||||
<None Include="Specifications\Docs\glActiveShaderProgram.xml" />
|
||||
<None Include="Specifications\Docs\glBeginConditionalRender.xml" />
|
||||
<None Include="Specifications\Docs\glBeginQueryIndexed.xml" />
|
||||
<None Include="Specifications\Docs\glBeginTransformFeedback.xml" />
|
||||
<None Include="Specifications\Docs\glBindBufferBase.xml" />
|
||||
<None Include="Specifications\Docs\glBindBufferRange.xml" />
|
||||
<None Include="Specifications\Docs\glBindFragDataLocation.xml" />
|
||||
<None Include="Specifications\Docs\glBindFragDataLocationIndexed.xml" />
|
||||
<None Include="Specifications\Docs\glBindFramebuffer.xml" />
|
||||
<None Include="Specifications\Docs\glBindProgramPipeline.xml" />
|
||||
<None Include="Specifications\Docs\glBindRenderbuffer.xml" />
|
||||
<None Include="Specifications\Docs\glBindSampler.xml" />
|
||||
<None Include="Specifications\Docs\glBindTransformFeedback.xml" />
|
||||
<None Include="Specifications\Docs\glBindVertexArray.xml" />
|
||||
<None Include="Specifications\Docs\glBlitFramebuffer.xml" />
|
||||
<None Include="Specifications\Docs\glCheckFramebufferStatus.xml" />
|
||||
<None Include="Specifications\Docs\glClampColor.xml" />
|
||||
<None Include="Specifications\Docs\glClearBuffer.xml" />
|
||||
<None Include="Specifications\Docs\glClientWaitSync.xml" />
|
||||
<None Include="Specifications\Docs\glCopyBufferSubData.xml" />
|
||||
<None Include="Specifications\Docs\glCreateShaderProgram.xml" />
|
||||
<None Include="Specifications\Docs\glDeleteFramebuffers.xml" />
|
||||
<None Include="Specifications\Docs\glDeleteProgramPipelines.xml" />
|
||||
<None Include="Specifications\Docs\glDeleteRenderbuffers.xml" />
|
||||
<None Include="Specifications\Docs\glDeleteSamplers.xml" />
|
||||
<None Include="Specifications\Docs\glDeleteSync.xml" />
|
||||
<None Include="Specifications\Docs\glDeleteTransformFeedbacks.xml" />
|
||||
<None Include="Specifications\Docs\glDeleteVertexArrays.xml" />
|
||||
<None Include="Specifications\Docs\glDepthRangeArray.xml" />
|
||||
<None Include="Specifications\Docs\glDepthRangeIndexed.xml" />
|
||||
<None Include="Specifications\Docs\glDrawArraysIndirect.xml" />
|
||||
<None Include="Specifications\Docs\glDrawArraysInstanced.xml" />
|
||||
<None Include="Specifications\Docs\glDrawElementsBaseVertex.xml" />
|
||||
<None Include="Specifications\Docs\glDrawElementsIndirect.xml" />
|
||||
<None Include="Specifications\Docs\glDrawElementsInstanced.xml" />
|
||||
<None Include="Specifications\Docs\glDrawElementsInstancedBaseVertex.xml" />
|
||||
<None Include="Specifications\Docs\glDrawRangeElementsBaseVertex.xml" />
|
||||
<None Include="Specifications\Docs\glDrawTransformFeedback.xml" />
|
||||
<None Include="Specifications\Docs\glDrawTransformFeedbackStream.xml" />
|
||||
<None Include="Specifications\Docs\glFenceSync.xml" />
|
||||
<None Include="Specifications\Docs\glFlushMappedBufferRange.xml" />
|
||||
<None Include="Specifications\Docs\glFramebufferRenderbuffer.xml" />
|
||||
<None Include="Specifications\Docs\glFramebufferTexture.xml" />
|
||||
<None Include="Specifications\Docs\glFramebufferTextureFace.xml" />
|
||||
<None Include="Specifications\Docs\glFramebufferTextureLayer.xml" />
|
||||
<None Include="Specifications\Docs\glGenerateMipmap.xml" />
|
||||
<None Include="Specifications\Docs\glGenFramebuffers.xml" />
|
||||
<None Include="Specifications\Docs\glGenProgramPipelines.xml" />
|
||||
<None Include="Specifications\Docs\glGenRenderbuffers.xml" />
|
||||
<None Include="Specifications\Docs\glGenSamplers.xml" />
|
||||
<None Include="Specifications\Docs\glGenTransformFeedbacks.xml" />
|
||||
<None Include="Specifications\Docs\glGenVertexArrays.xml" />
|
||||
<None Include="Specifications\Docs\glGetActiveSubroutineName.xml" />
|
||||
<None Include="Specifications\Docs\glGetActiveSubroutineUniform.xml" />
|
||||
<None Include="Specifications\Docs\glGetActiveSubroutineUniformName.xml" />
|
||||
<None Include="Specifications\Docs\glGetActiveUniformBlock.xml" />
|
||||
<None Include="Specifications\Docs\glGetActiveUniformBlockName.xml" />
|
||||
<None Include="Specifications\Docs\glGetActiveUniformName.xml" />
|
||||
<None Include="Specifications\Docs\glGetBufferParameter.xml" />
|
||||
<None Include="Specifications\Docs\glGetFragDataIndex.xml" />
|
||||
<None Include="Specifications\Docs\glGetFragDataLocation.xml" />
|
||||
<None Include="Specifications\Docs\glGetFramebufferAttachmentParameter.xml" />
|
||||
<None Include="Specifications\Docs\glGetMultisample.xml" />
|
||||
<None Include="Specifications\Docs\glGetProgramBinary.xml" />
|
||||
<None Include="Specifications\Docs\glGetProgramPipeline.xml" />
|
||||
<None Include="Specifications\Docs\glGetProgramPipelineInfoLog.xml" />
|
||||
<None Include="Specifications\Docs\glGetProgramStage.xml" />
|
||||
<None Include="Specifications\Docs\glGetQueryIndexed.xml" />
|
||||
<None Include="Specifications\Docs\glGetRenderbufferParameter.xml" />
|
||||
<None Include="Specifications\Docs\glGetSamplerParameter.xml" />
|
||||
<None Include="Specifications\Docs\glGetShaderPrecisionFormat.xml" />
|
||||
<None Include="Specifications\Docs\glGetSubroutineIndex.xml" />
|
||||
<None Include="Specifications\Docs\glGetSubroutineUniformLocation.xml" />
|
||||
<None Include="Specifications\Docs\glGetSync.xml" />
|
||||
<None Include="Specifications\Docs\glGetTransformFeedbackVarying.xml" />
|
||||
<None Include="Specifications\Docs\glGetUniformBlockIndex.xml" />
|
||||
<None Include="Specifications\Docs\glGetUniformIndices.xml" />
|
||||
<None Include="Specifications\Docs\glGetUniformSubroutine.xml" />
|
||||
<None Include="Specifications\Docs\glIsFramebuffer.xml" />
|
||||
<None Include="Specifications\Docs\glIsProgramPipeline.xml" />
|
||||
<None Include="Specifications\Docs\glIsRenderbuffer.xml" />
|
||||
<None Include="Specifications\Docs\glIsSampler.xml" />
|
||||
<None Include="Specifications\Docs\glIsSync.xml" />
|
||||
<None Include="Specifications\Docs\glIsTransformFeedback.xml" />
|
||||
<None Include="Specifications\Docs\glIsVertexArray.xml" />
|
||||
<None Include="Specifications\Docs\glMapBufferRange.xml" />
|
||||
<None Include="Specifications\Docs\glMultiDrawElementsBaseVertex.xml" />
|
||||
<None Include="Specifications\Docs\glPatchParameter.xml" />
|
||||
<None Include="Specifications\Docs\glPauseTransformFeedback.xml" />
|
||||
<None Include="Specifications\Docs\glPrimitiveRestartIndex.xml" />
|
||||
<None Include="Specifications\Docs\glProgramBinary.xml" />
|
||||
<None Include="Specifications\Docs\glProgramParameter.xml" />
|
||||
<None Include="Specifications\Docs\glProgramUniform.xml" />
|
||||
<None Include="Specifications\Docs\glProvokingVertex.xml" />
|
||||
<None Include="Specifications\Docs\glQueryCounter.xml" />
|
||||
<None Include="Specifications\Docs\glReleaseShaderCompiler.xml" />
|
||||
<None Include="Specifications\Docs\glRenderbufferStorage.xml" />
|
||||
<None Include="Specifications\Docs\glRenderbufferStorageMultisample.xml" />
|
||||
<None Include="Specifications\Docs\glResumeTransformFeedback.xml" />
|
||||
<None Include="Specifications\Docs\glSampleMaski.xml" />
|
||||
<None Include="Specifications\Docs\glSamplerParameter.xml" />
|
||||
<None Include="Specifications\Docs\glScissorArray.xml" />
|
||||
<None Include="Specifications\Docs\glScissorIndexed.xml" />
|
||||
<None Include="Specifications\Docs\glShaderBinary.xml" />
|
||||
<None Include="Specifications\Docs\glTexBuffer.xml" />
|
||||
<None Include="Specifications\Docs\glTexImage2DMultisample.xml" />
|
||||
<None Include="Specifications\Docs\glTexImage3DMultisample.xml" />
|
||||
<None Include="Specifications\Docs\glTransformFeedbackVaryings.xml" />
|
||||
<None Include="Specifications\Docs\glUniformBlockBinding.xml" />
|
||||
<None Include="Specifications\Docs\glUniformSubroutines.xml" />
|
||||
<None Include="Specifications\Docs\glUseProgramStages.xml" />
|
||||
<None Include="Specifications\Docs\glValidateProgramPipeline.xml" />
|
||||
<None Include="Specifications\Docs\glVertexAttribDivisor.xml" />
|
||||
<None Include="Specifications\Docs\glViewportArray.xml" />
|
||||
<None Include="Specifications\Docs\glViewportIndexed.xml" />
|
||||
<None Include="Specifications\Docs\glWaitSync.xml" />
|
||||
<None Include="Specifications\GL2\signatures.xml">
|
||||
<SubType>Designer</SubType>
|
||||
</Content>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSHARP.Targets" />
|
||||
<PropertyGroup>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
namespace Bind
|
||||
{
|
||||
interface IBind : ISpecReader, ISpecWriter
|
||||
interface IBind
|
||||
{
|
||||
void Process();
|
||||
}
|
||||
|
|
|
@ -16,38 +16,10 @@ namespace Bind.Structures
|
|||
internal static Dictionary<string, string> GLTypes;
|
||||
internal static Dictionary<string, string> CSTypes;
|
||||
|
||||
private static bool typesLoaded;
|
||||
|
||||
string current_qualifier = "", previous_qualifier = "";
|
||||
|
||||
#region internal static void Initialize(string glTypes, string csTypes)
|
||||
|
||||
internal static void Initialize(string glTypes, string csTypes)
|
||||
{
|
||||
if (!typesLoaded)
|
||||
{
|
||||
if (GLTypes == null)
|
||||
{
|
||||
using (StreamReader sr = Utilities.OpenSpecFile(Settings.InputPath, glTypes))
|
||||
{
|
||||
GLTypes = MainClass.Generator.ReadTypeMap(sr);
|
||||
}
|
||||
}
|
||||
if (CSTypes == null)
|
||||
{
|
||||
using (StreamReader sr = Utilities.OpenSpecFile(Settings.InputPath, csTypes))
|
||||
{
|
||||
CSTypes = MainClass.Generator.ReadCSTypeMap(sr);
|
||||
}
|
||||
}
|
||||
typesLoaded = true;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region --- Constructors ---
|
||||
|
||||
|
||||
public Type()
|
||||
{
|
||||
}
|
||||
|
@ -66,7 +38,7 @@ namespace Bind.Structures
|
|||
ElementCount = t.ElementCount;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
public string CurrentQualifier
|
||||
|
@ -81,7 +53,8 @@ namespace Bind.Structures
|
|||
private set { previous_qualifier = value; }
|
||||
}
|
||||
|
||||
public string QualifiedType {
|
||||
public string QualifiedType
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!String.IsNullOrEmpty(CurrentQualifier))
|
||||
|
@ -233,7 +206,7 @@ namespace Bind.Structures
|
|||
get
|
||||
{
|
||||
bool compliant = true;
|
||||
|
||||
|
||||
switch (CurrentType.ToLower())
|
||||
{
|
||||
case "sbyte":
|
||||
|
@ -244,16 +217,16 @@ namespace Bind.Structures
|
|||
case "uint16":
|
||||
case "uint32":
|
||||
case "uint64":
|
||||
compliant = false;
|
||||
compliant = false;
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
compliant = Pointer == 0;
|
||||
break;
|
||||
break;
|
||||
}
|
||||
|
||||
return compliant;
|
||||
|
||||
|
||||
/*
|
||||
if (Pointer != 0)
|
||||
{
|
||||
|
@ -265,7 +238,7 @@ namespace Bind.Structures
|
|||
*/
|
||||
//return compliant && (!Pointer || CurrentType.Contains("IntPtr"));
|
||||
//return compliant && !(Pointer && ((Settings.Compatibility & Settings.Legacy.NoPublicUnsafeFunctions) == Settings.Legacy.None));
|
||||
|
||||
|
||||
/*
|
||||
* return !(
|
||||
(Pointer && ((Settings.Compatibility & Settings.Legacy.NoPublicUnsafeFunctions) == Settings.Legacy.None ) ||
|
||||
|
@ -341,12 +314,12 @@ namespace Bind.Structures
|
|||
#endregion
|
||||
|
||||
#region public override string ToString()
|
||||
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return QualifiedType;
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region public virtual void Translate(XPathNavigator overrides, string category)
|
||||
|
|
292
Source/Bind/XmlSpecReader.cs
Normal file
292
Source/Bind/XmlSpecReader.cs
Normal file
|
@ -0,0 +1,292 @@
|
|||
#region License
|
||||
//
|
||||
// The Open Toolkit Library License
|
||||
//
|
||||
// Copyright (c) 2006 - 2010 the Open Toolkit library.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights to
|
||||
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
// the Software, and to permit persons to whom the Software is furnished to do
|
||||
// so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Xml.XPath;
|
||||
using Bind.Structures;
|
||||
|
||||
namespace Bind
|
||||
{
|
||||
using Delegate = Bind.Structures.Delegate;
|
||||
using Enum = Bind.Structures.Enum;
|
||||
|
||||
class XmlSpecReader : ISpecReader
|
||||
{
|
||||
readonly string functionOverridesFile;
|
||||
|
||||
public XmlSpecReader(string functionOverridesFile)
|
||||
{
|
||||
this.functionOverridesFile = functionOverridesFile;
|
||||
}
|
||||
|
||||
public DelegateCollection ReadDelegates(StreamReader specFile)
|
||||
{
|
||||
DelegateCollection delegates = new DelegateCollection();
|
||||
XPathDocument specs = new XPathDocument(specFile);
|
||||
XPathDocument overrides = new XPathDocument(new StreamReader(
|
||||
Path.Combine(Settings.InputPath, functionOverridesFile)));
|
||||
|
||||
foreach (XPathNavigator nav in new XPathNavigator[] {
|
||||
specs.CreateNavigator().SelectSingleNode("/signatures"),
|
||||
overrides.CreateNavigator().SelectSingleNode("/overrides/add") })
|
||||
{
|
||||
if (nav != null)
|
||||
{
|
||||
foreach (XPathNavigator node in nav.SelectChildren("function", String.Empty))
|
||||
{
|
||||
var name = node.GetAttribute("name", String.Empty);
|
||||
|
||||
// Check whether we are adding to an existing delegate or creating a new one.
|
||||
Delegate d = null;
|
||||
if (delegates.ContainsKey(name))
|
||||
{
|
||||
d = delegates[name];
|
||||
}
|
||||
else
|
||||
{
|
||||
d = new Delegate();
|
||||
d.Name = name;
|
||||
d.Version = node.GetAttribute("version", String.Empty);
|
||||
d.Category = node.GetAttribute("category", String.Empty);
|
||||
d.DeprecatedVersion = node.GetAttribute("deprecated", String.Empty);
|
||||
d.Deprecated = !String.IsNullOrEmpty(d.DeprecatedVersion);
|
||||
}
|
||||
|
||||
foreach (XPathNavigator param in node.SelectChildren(XPathNodeType.Element))
|
||||
{
|
||||
switch (param.Name)
|
||||
{
|
||||
case "returns":
|
||||
d.ReturnType.CurrentType = param.GetAttribute("type", String.Empty);
|
||||
break;
|
||||
|
||||
case "param":
|
||||
Parameter p = new Parameter();
|
||||
p.CurrentType = param.GetAttribute("type", String.Empty);
|
||||
p.Name = param.GetAttribute("name", String.Empty);
|
||||
|
||||
string element_count = param.GetAttribute("elementcount", String.Empty);
|
||||
if (String.IsNullOrEmpty(element_count))
|
||||
element_count = param.GetAttribute("count", String.Empty);
|
||||
if (!String.IsNullOrEmpty(element_count))
|
||||
p.ElementCount = Int32.Parse(element_count);
|
||||
|
||||
p.Flow = Parameter.GetFlowDirection(param.GetAttribute("flow", String.Empty));
|
||||
|
||||
d.Parameters.Add(p);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
delegates.Add(d);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return delegates;
|
||||
}
|
||||
|
||||
public 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 if (words[1] == "const" && words[2] == "GLubyte")
|
||||
{
|
||||
GLTypes.Add(words[0], "String");
|
||||
}
|
||||
else if (words[1] == "struct")
|
||||
{
|
||||
GLTypes.Add(words[0], words[2]);
|
||||
}
|
||||
else
|
||||
{
|
||||
GLTypes.Add(words[0], words[1]);
|
||||
}
|
||||
}
|
||||
while (!specFile.EndOfStream);
|
||||
|
||||
return GLTypes;
|
||||
}
|
||||
|
||||
public 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;
|
||||
}
|
||||
|
||||
public EnumCollection ReadEnums(StreamReader specFile)
|
||||
{
|
||||
// First, read all enum definitions from spec and override file.
|
||||
// Afterwards, read all token/enum overrides from overrides file.
|
||||
// Every single enum is merged into
|
||||
|
||||
EnumCollection enums = new EnumCollection();
|
||||
Enum all = new Enum() { Name = Settings.CompleteEnumName };
|
||||
XPathDocument specs = new XPathDocument(specFile);
|
||||
XPathDocument overrides = new XPathDocument(new StreamReader(Path.Combine(Settings.InputPath, functionOverridesFile)));
|
||||
|
||||
foreach (XPathNavigator nav in new XPathNavigator[] {
|
||||
specs.CreateNavigator().SelectSingleNode("/signatures"),
|
||||
overrides.CreateNavigator().SelectSingleNode("/overrides/add") })
|
||||
{
|
||||
if (nav != null)
|
||||
{
|
||||
foreach (XPathNavigator node in nav.SelectChildren("enum", String.Empty))
|
||||
{
|
||||
Enum e = new Enum()
|
||||
{
|
||||
Name = node.GetAttribute("name", String.Empty),
|
||||
Type = node.GetAttribute("type", String.Empty)
|
||||
};
|
||||
if (String.IsNullOrEmpty(e.Name))
|
||||
throw new InvalidOperationException(String.Format("Empty name for enum element {0}", node.ToString()));
|
||||
|
||||
foreach (XPathNavigator param in node.SelectChildren(XPathNodeType.Element))
|
||||
{
|
||||
Constant c = null;
|
||||
switch (param.Name)
|
||||
{
|
||||
case "token":
|
||||
c = new Constant
|
||||
{
|
||||
Name = param.GetAttribute("name", String.Empty),
|
||||
Value = param.GetAttribute("value", String.Empty)
|
||||
};
|
||||
break;
|
||||
|
||||
case "use":
|
||||
c = new Constant
|
||||
{
|
||||
Name = param.GetAttribute("token", String.Empty),
|
||||
Reference = param.GetAttribute("enum", String.Empty),
|
||||
Value = param.GetAttribute("token", String.Empty),
|
||||
};
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
Utilities.Merge(all, c);
|
||||
try
|
||||
{
|
||||
if (!e.ConstantCollection.ContainsKey(c.Name))
|
||||
{
|
||||
e.ConstantCollection.Add(c.Name, c);
|
||||
}
|
||||
else if (e.ConstantCollection[c.Name].Value != c.Value)
|
||||
{
|
||||
var existing = e.ConstantCollection[c.Name];
|
||||
if (existing.Reference != null && c.Reference == null)
|
||||
{
|
||||
e.ConstantCollection[c.Name] = c;
|
||||
}
|
||||
else if (existing.Reference == null && c.Reference != null)
|
||||
{ } // Keep existing
|
||||
else
|
||||
{
|
||||
Console.WriteLine("[Warning] Conflicting token {0}.{1} with value {2} != {3}",
|
||||
e.Name, c.Name, e.ConstantCollection[c.Name].Value, c.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (ArgumentException ex)
|
||||
{
|
||||
Console.WriteLine("[Warning] Failed to add constant {0} to enum {1}: {2}", c.Name, e.Name, ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
Utilities.Merge(enums, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Utilities.Merge(enums, all);
|
||||
return enums;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue