|
|
|
@@ -0,0 +1,223 @@
|
|
|
|
|
using System;
|
|
|
|
|
using System.IO;
|
|
|
|
|
using System.Collections;
|
|
|
|
|
using System.Diagnostics;
|
|
|
|
|
|
|
|
|
|
using Cpp2Beef;
|
|
|
|
|
using LibClang;
|
|
|
|
|
|
|
|
|
|
namespace Box2D.Setup;
|
|
|
|
|
|
|
|
|
|
class Box2DGenerator : Cpp2BeefGenerator, this(Span<char8*> args)
|
|
|
|
|
{
|
|
|
|
|
protected override Span<char8*> Args => args;
|
|
|
|
|
protected override Flags Flags => .None;
|
|
|
|
|
|
|
|
|
|
Dictionary<String, StreamWriter> writers = new .() ~ DeleteDictionaryAndKeysAndValues!(_);
|
|
|
|
|
|
|
|
|
|
protected override StreamWriter GetWriterForHeader(StringView header)
|
|
|
|
|
{
|
|
|
|
|
if (!header.Contains("include/box2d") && !header.Contains(@"include\box2d"))
|
|
|
|
|
return null;
|
|
|
|
|
let filename = Path.GetFileNameWithoutExtension(header, ..scope .(64));
|
|
|
|
|
if (writers.TryAdd(filename, let keyPtr, let valuePtr))
|
|
|
|
|
{
|
|
|
|
|
*keyPtr = new .(filename);
|
|
|
|
|
String outFilename = scope .(64);
|
|
|
|
|
outFilename.Append("../src/");
|
|
|
|
|
UpperSnakeCase2PascalCase(filename, outFilename);
|
|
|
|
|
outFilename.Append(".bf");
|
|
|
|
|
*valuePtr = new .()..Create(outFilename)..Write("""
|
|
|
|
|
// This file was generated by Cpp2Beef
|
|
|
|
|
|
|
|
|
|
using System;
|
|
|
|
|
using System.Interop;
|
|
|
|
|
|
|
|
|
|
namespace Box2D;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
return *valuePtr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected override Block GetCursorBlock(CXCursor cursor)
|
|
|
|
|
{
|
|
|
|
|
if (cursor.kind == .FunctionDecl && GetCursorSpelling!(cursor).StartsWith("b2"))
|
|
|
|
|
return .CustomBlock("Box2D");
|
|
|
|
|
return base.GetCursorBlock(cursor);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected override void HandleCursor(CXCursor cursor)
|
|
|
|
|
{
|
|
|
|
|
switch (cursor.kind)
|
|
|
|
|
{
|
|
|
|
|
case .StructDecl when GetFilePath!(fileInfo.file).EndsWith("math_functions.h"):
|
|
|
|
|
base.HandleCursor(cursor);
|
|
|
|
|
str.Append("\n\tpublic this(");
|
|
|
|
|
bool comma = false;
|
|
|
|
|
Clang.VisitChildren(cursor, (cursor, parent, client_data) =>
|
|
|
|
|
{
|
|
|
|
|
if (cursor.kind != .FieldDecl) return .Continue;
|
|
|
|
|
(Self self, bool* comma) = *(.)client_data;
|
|
|
|
|
if (*comma) self.str.Append(", ");
|
|
|
|
|
*comma = true;
|
|
|
|
|
self.WriteTypeAndName(cursor, Clang.GetCursorType(cursor));
|
|
|
|
|
return .Continue;
|
|
|
|
|
}, &(this, &comma));
|
|
|
|
|
str.Append(") { ");
|
|
|
|
|
Clang.VisitChildren(cursor, (cursor, parent, client_data) =>
|
|
|
|
|
{
|
|
|
|
|
if (cursor.kind != .FieldDecl) return .Continue;
|
|
|
|
|
Self self = *(.)client_data;
|
|
|
|
|
self.str.Append("this.", GetCursorSpelling!(cursor), " = ", GetCursorSpelling!(cursor), "; ");
|
|
|
|
|
return .Continue;
|
|
|
|
|
}, &(this, default(void)));
|
|
|
|
|
str.Append('}');
|
|
|
|
|
case .MacroDefinition:
|
|
|
|
|
let spelling = GetCursorSpelling!(cursor);
|
|
|
|
|
if (spelling == "B2_BREAKPOINT" || spelling == "B2_API" || spelling == "B2_INLINE" || spelling == "B2_ID_INLINE" || spelling == "B2_ZERO_INIT" || spelling == "B2_NULL_ID")
|
|
|
|
|
return;
|
|
|
|
|
fallthrough;
|
|
|
|
|
default:
|
|
|
|
|
if (_ == .VarDecl && GetCursorSpelling!(cursor) == "b2_emptySimplexCache")
|
|
|
|
|
return;
|
|
|
|
|
base.HandleCursor(cursor);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
List<String> functionNonPtrs = new .(8) ~ DeleteContainerAndItems!(_);
|
|
|
|
|
protected override void TypeAlias(CXCursor cursor)
|
|
|
|
|
{
|
|
|
|
|
if (cursor.kind == .TypedefDecl)
|
|
|
|
|
{
|
|
|
|
|
CXType type = Clang.GetTypedefDeclUnderlyingType(cursor);
|
|
|
|
|
if (type.kind == .FunctionProto || type.kind == .FunctionNoProto)
|
|
|
|
|
{
|
|
|
|
|
functionNonPtrs.Add(new .(GetCursorSpelling!(cursor)));
|
|
|
|
|
WriteCustomAttributes(cursor);
|
|
|
|
|
AccessSpecifier(cursor);
|
|
|
|
|
str.Append("function ");
|
|
|
|
|
WriteTypeAndName(cursor, Clang.GetResultType(type));
|
|
|
|
|
WriteFunctionProtoParams(type, ScopeTokenize!(cursor, unit));
|
|
|
|
|
str.Append(';');
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
base.TypeAlias(cursor);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected override void Type(CXType type, TypeParamMode paramMode = .None)
|
|
|
|
|
{
|
|
|
|
|
if (type.kind == .Pointer)
|
|
|
|
|
{
|
|
|
|
|
let pointee = Clang.GetPointeeType(type);
|
|
|
|
|
if (paramMode == .OutParam) str.Append("out ");
|
|
|
|
|
Type(pointee);
|
|
|
|
|
if (functionNonPtrs.ContainsAlt(GetTypeSpelling!(pointee)))
|
|
|
|
|
return;
|
|
|
|
|
if (paramMode != .OutParam && pointee.kind != .FunctionProto && pointee.kind != .FunctionNoProto)
|
|
|
|
|
str.Append('*');
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
base.Type(type, paramMode);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected override void GetNameInBindings(CXCursor cursor, String outString)
|
|
|
|
|
{
|
|
|
|
|
gnib: switch (cursor.kind)
|
|
|
|
|
{
|
|
|
|
|
case .FunctionDecl:
|
|
|
|
|
StringView spelling = GetCursorSpelling!(cursor);
|
|
|
|
|
if (spelling.StartsWith("b2"))
|
|
|
|
|
spelling.RemoveFromStart(2);
|
|
|
|
|
outString.Append(spelling);
|
|
|
|
|
case .EnumConstantDecl:
|
|
|
|
|
StringView pre, post;
|
|
|
|
|
switch (GetCursorSpelling!(Clang.GetCursorSemanticParent(cursor)))
|
|
|
|
|
{
|
|
|
|
|
case "b2RecQueryType": pre = "b2_recQuery"; post = "";
|
|
|
|
|
case "b2TOIState": pre = "b2_toiState"; post = "";
|
|
|
|
|
case "b2TreeNodeFlags": pre = "b2_"; post = "Node";
|
|
|
|
|
case "b2BodyType": pre = "b2_"; post = "";
|
|
|
|
|
case "b2ShapeType": pre = "b2_"; post = "Shape";
|
|
|
|
|
case "b2JointType": pre = "b2_"; post = "Joint";
|
|
|
|
|
case "b2HexColor": pre = "b2_color"; post = "";
|
|
|
|
|
default: Runtime.FatalError("Unhandled enum");
|
|
|
|
|
}
|
|
|
|
|
StringView spelling = GetCursorSpelling!(cursor);
|
|
|
|
|
if (spelling.StartsWith(pre)) spelling.RemoveFromStart(pre.Length);
|
|
|
|
|
if (spelling.EndsWith (post)) spelling.RemoveFromEnd(post.Length);
|
|
|
|
|
str.Append(spelling[0].ToUpper);
|
|
|
|
|
str.Append(spelling[1...]);
|
|
|
|
|
case .MacroDefinition:
|
|
|
|
|
let spelling = GetCursorSpelling!(cursor);
|
|
|
|
|
switch (spelling)
|
|
|
|
|
{
|
|
|
|
|
case "UINT64_MAX": outString.Append("uint64.MaxValue");
|
|
|
|
|
case "B2_ZERO_INIT", "B2_NULL_ID": outString.Append("default");
|
|
|
|
|
default: fallthrough gnib;
|
|
|
|
|
}
|
|
|
|
|
default:
|
|
|
|
|
base.GetNameInBindings(cursor, outString);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected override void WriteToken(CXToken token)
|
|
|
|
|
{
|
|
|
|
|
if (currentCursor.kind == .VarDecl &&
|
|
|
|
|
fileInfo.prevEnd.int_data > Clang.GetCursorLocation(currentCursor).int_data &&
|
|
|
|
|
Clang.GetTokenKind(token) == .Punctuation)
|
|
|
|
|
{
|
|
|
|
|
switch (GetTokenSpelling!(token))
|
|
|
|
|
{
|
|
|
|
|
case "{": str.Append(".("); return;
|
|
|
|
|
case "}": str.Append( ")"); return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (Clang.GetTokenKind(token) == .Identifier)
|
|
|
|
|
{
|
|
|
|
|
let spelling = GetTokenSpelling!(token);
|
|
|
|
|
bool invoke = spelling.StartsWith("b2");
|
|
|
|
|
if (invoke || spelling == "B2_LINEAR_SLOP")
|
|
|
|
|
str.Replace("const let", "static var");
|
|
|
|
|
if (invoke)
|
|
|
|
|
{
|
|
|
|
|
str.Append("Box2D.", spelling[2...]);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
base.WriteToken(token);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// There are functions you can override, but these are the most common
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class Program
|
|
|
|
|
{
|
|
|
|
|
[CLink] static extern int32 system(char8*);
|
|
|
|
|
|
|
|
|
|
public static int Main(String[] args)
|
|
|
|
|
{
|
|
|
|
|
if (system("git -C .. submodule update") != 0)
|
|
|
|
|
{
|
|
|
|
|
Console.WriteLine("Failed to fetch Box2D, check your internet connection");
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
StreamWriter all = scope .()..Create("b2_all.h");
|
|
|
|
|
for (let file in Directory.EnumerateFiles("../box2d/include/box2d"))
|
|
|
|
|
{
|
|
|
|
|
let filename = file.GetFileName(..scope .(64));
|
|
|
|
|
all.Write("#include <box2d/");
|
|
|
|
|
all.Write(filename);
|
|
|
|
|
all.Write(">\n");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
scope Box2DGenerator(char8*[?]("--language=c", "-I../box2d/include")).Generate("b2_all.h");
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|