Skip to content

Commit

Permalink
Added preliminary Java wrapper generation. Heavy work-in-progress.
Browse files Browse the repository at this point in the history
git-svn-id: https://opentk.svn.sourceforge.net/svnroot/opentk/trunk@3090 ebc5dd9b-fb1d-0410-b6f8-d24c324e9604
  • Loading branch information
the_fiddler committed Dec 2, 2011
1 parent e7a69d4 commit 4df94d9
Show file tree
Hide file tree
Showing 4 changed files with 346 additions and 2 deletions.
3 changes: 2 additions & 1 deletion Source/Bind/Generator.Bind.csproj
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
<PropertyGroup>
<ProjectType>Local</ProjectType>
Expand Down Expand Up @@ -129,6 +129,7 @@
<Compile Include="IBind.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="JavaSpecWriter.cs" />
<Compile Include="Main.cs">
<SubType>Code</SubType>
</Compile>
Expand Down
314 changes: 314 additions & 0 deletions Source/Bind/JavaSpecWriter.cs
@@ -0,0 +1,314 @@
#region License
//
// The Open Toolkit Library License
//
// Copyright (c) 2006 - 2011 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 JavaSpecWriter : ISpecWriter
{
readonly char[] numbers = "0123456789".ToCharArray();
const string DigitPrefix = "T"; // Prefix for identifiers that start with a digit
const string OutputFileHeader = "GL.java";

BindStreamWriter sw_h = new BindStreamWriter(Path.GetTempFileName());

#region WriteBindings

public void WriteBindings(IBind generator)
{
WriteBindings(generator.Delegates, generator.Wrappers, generator.Enums);
}

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);

// Hack: Fix 3dfx extension category so it doesn't start with a digit
if (wrappers.ContainsKey("3dfx"))
{
var three_dee_fx = wrappers["3dfx"];
wrappers.Remove("3dfx");
wrappers.Add(DigitPrefix + "3dfx", three_dee_fx);
}

Settings.DefaultOutputNamespace = "com.opentk";

using (var sw = sw_h)
{
WriteLicense(sw);

sw.WriteLine("namespace {0}", Settings.OutputNamespace);
sw.WriteLine("{");
sw.Indent();

//WriteGetAddress(sw);
//WriteTypes(sw);
WriteEnums(sw, enums);
WriteDefinitions(sw, enums, wrappers, Type.CSTypes);

sw.Unindent();
sw.WriteLine("}");

sw.Flush();
sw.Close();
}

string output_header = Path.Combine(Settings.OutputPath, OutputFileHeader);
Move(sw_h.File, output_header);
}

void Move(string file, string dest)
{
if (File.Exists(dest))
File.Delete(dest);
File.Move(file, dest);
}

static void WriteWrapper(Function f, BindStreamWriter sw)
{
var parameters = f.WrappedDelegate.Parameters.ToString()
.Replace("[OutAttribute]", String.Empty);
sw.WriteLine("{");
sw.Indent();
WriteMethodBody(sw, f);
sw.Unindent();
sw.WriteLine("}");
}

#endregion

#region WriteDefinitions

void WriteDefinitions(BindStreamWriter sw,
EnumCollection enums, FunctionCollection wrappers,
Dictionary<string, string> CSTypes)
{
sw.WriteLine("namespace {0}", Settings.GLClass);
sw.WriteLine("{");
sw.Indent();

foreach (string extension in wrappers.Keys)
{
if (extension != "Core")
{
sw.WriteLine("namespace {0}", extension);
sw.WriteLine("{");
sw.Indent();
}

// Avoid multiple definitions of the same function
Delegate last_delegate = null;

// Write wrappers
foreach (var f in wrappers[extension])
{
WriteWrapper(f, sw);
}

if (extension != "Core")
{
sw.Unindent();
sw.WriteLine("};");
}
}

sw.Unindent();
sw.WriteLine("};");

sw.Unindent();
sw.WriteLine("}");
}

#endregion

static string GetNamespace(string ext)
{
if (ext == "Core")
return Settings.GLClass;
else
return String.Format("{0}::{1}", Settings.GLClass, Char.IsDigit(ext[0]) ? DigitPrefix + ext : ext);
}

#region WriteEnums

public void WriteEnums(BindStreamWriter sw, EnumCollection enums)
{
foreach (Enum @enum in enums.Values)
{
sw.WriteLine("public enum {0}", @enum.Name);
sw.WriteLine("{");
sw.Indent();
foreach (var c in @enum.ConstantCollection.Values)
{
// Java doesn't have the concept of "unchecked", so remove this.
if (!c.Unchecked)
sw.WriteLine("{0},", c);
else
sw.WriteLine("{0},", c.ToString().Replace("unchecked", String.Empty));
}
sw.Unindent();
sw.WriteLine("}");
sw.WriteLine();
}
}

#endregion

#region WriteTypes

void WriteTypes(BindStreamWriter sw)
{
//sw.WriteLine(TypeDefinitions);
}

#endregion

#region WriteDelegate

static void WriteDelegate(BindStreamWriter sw, Delegate d, ref Delegate last_delegate)
{
// Avoid multiple definitions of the same function
if (d != last_delegate)
{
last_delegate = d;
var parameters = d.Parameters.ToString()
.Replace("String[]", "String*")
.Replace("[OutAttribute]", String.Empty);
sw.WriteLine("typedef {0} (APIENTRY *p{1}){2};", d.ReturnType, d.Name, parameters);
sw.WriteLine("inline p{0}& {0}()", d.Name);
sw.WriteLine("{");
sw.Indent();
sw.WriteLine("static p{0} address = 0;", d.Name);
sw.WriteLine("return address;");
sw.Unindent();
sw.WriteLine("}");
}
}

#endregion

#region WriteWrappers

static void WriteMethodBody(BindStreamWriter sw, Function f)
{

var callstring = f.Parameters.CallString();
if (f.ReturnType != null && !f.ReturnType.ToString().ToLower().Contains("void"))
sw.WriteLine("return GLES20::{0}(){1};", f.WrappedDelegate.Name, callstring);
else
sw.WriteLine("GLES20::{0}(){1};", f.WrappedDelegate.Name, callstring);
}

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 WriteLicense

public void WriteLicense(BindStreamWriter sw)
{
sw.WriteLine(File.ReadAllText(Path.Combine(Settings.InputPath, Settings.LicenseFile)));
sw.WriteLine();
}

#endregion
}
}
15 changes: 14 additions & 1 deletion Source/Bind/Main.cs
Expand Up @@ -31,7 +31,8 @@ enum GeneratorMode
enum GeneratorLanguage
{
CSharp,
Cpp
Cpp,
Java
}

static class MainClass
Expand Down Expand Up @@ -93,6 +94,14 @@ static void Main(string[] arguments)
Settings.EnumsNamespace = "";
Settings.NamespaceSeparator = "::";
}
else if (arg == "java")
{
Settings.Language = GeneratorLanguage.Java;
Settings.DefaultOutputPath = "gl";
Settings.DefaultOutputNamespace = "com.opentk";
Settings.EnumsNamespace = "";
Settings.NamespaceSeparator = ".";
}
break;
}
case "mode":
Expand Down Expand Up @@ -184,6 +193,10 @@ static void Main(string[] arguments)
writer = new CppSpecWriter();
break;

case GeneratorLanguage.Java:
writer = new JavaSpecWriter();
break;

case GeneratorLanguage.CSharp:
default:
writer = new CSharpSpecWriter();
Expand Down
16 changes: 16 additions & 0 deletions Source/Bind/Utilities.cs
Expand Up @@ -99,6 +99,7 @@ public static List<string> Keywords
{
case GeneratorLanguage.CSharp: return CSharpKeywords;
case GeneratorLanguage.Cpp: return CppKeywords;
case GeneratorLanguage.Java: return JavaKeywords;
default: throw new NotImplementedException();
}
}
Expand Down Expand Up @@ -130,6 +131,21 @@ public static List<string> Keywords
}
);

static readonly List<string> JavaKeywords = new List<string>(
new string[]
{
"abstract", "continue", "for", "new", "switch",
"assert", "default", "goto", "package", "synchronized",
"boolean", "do", "if", "private", "this",
"break", "double", "implements", "protected", "throw",
"byte", "else", "import", "public", "throws",
"case", "enum", "instanceof", "return", "transient",
"catch", "extends", "int", "short", "try",
"char", "final", "interface", "static", "void",
"class", "finally", "long", "strictfp", "volatile",
"const", "float", "native", "super", "while"
});

static readonly List<string> CppKeywords = new List<string>();

#endregion
Expand Down

0 comments on commit 4df94d9

Please sign in to comment.