This commit is contained in:
Rune
2026-03-06 16:05:04 +01:00
commit f61facf4e7
12 changed files with 2553 additions and 0 deletions

3
Setup/.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
build
recovery
BeefSpace_User.toml

66
Setup/BeefProj.toml Normal file
View File

@@ -0,0 +1,66 @@
FileVersion = 1
Dependencies = {corlib = "*", "Cpp2Beef.git" = {Git = "https://git.unicon-gmbh.de/BeefBindings/Cpp2Beef.git"}}
[Project]
Name = "Expat.Setup"
StartupObject = "Expat.Setup.Program"
[Configs.Debug.Win32]
PostBuildCmds = ["cp $(ProjectDir Cpp2Beef.git)/CxxBuilder/dist/CxxBuilderPath.txt $(WorkspaceDir)/../CxxBuilderPath.txt"]
[Configs.Debug.Win64]
PostBuildCmds = ["cp $(ProjectDir Cpp2Beef.git)/CxxBuilder/dist/CxxBuilderPath.txt $(WorkspaceDir)/../CxxBuilderPath.txt"]
[Configs.Debug.Linux32]
PostBuildCmds = ["cp $(ProjectDir Cpp2Beef.git)/CxxBuilder/dist/CxxBuilderPath.txt $(WorkspaceDir)/../CxxBuilderPath.txt"]
[Configs.Debug.Linux64]
PostBuildCmds = ["cp $(ProjectDir Cpp2Beef.git)/CxxBuilder/dist/CxxBuilderPath.txt $(WorkspaceDir)/../CxxBuilderPath.txt"]
[Configs.Debug.macOS]
PostBuildCmds = ["cp $(ProjectDir Cpp2Beef.git)/CxxBuilder/dist/CxxBuilderPath.txt $(WorkspaceDir)/../CxxBuilderPath.txt"]
[Configs.Release.Win32]
PostBuildCmds = ["cp $(ProjectDir Cpp2Beef.git)/CxxBuilder/dist/CxxBuilderPath.txt $(WorkspaceDir)/../CxxBuilderPath.txt"]
[Configs.Release.Win64]
PostBuildCmds = ["cp $(ProjectDir Cpp2Beef.git)/CxxBuilder/dist/CxxBuilderPath.txt $(WorkspaceDir)/../CxxBuilderPath.txt"]
[Configs.Release.Linux32]
PostBuildCmds = ["cp $(ProjectDir Cpp2Beef.git)/CxxBuilder/dist/CxxBuilderPath.txt $(WorkspaceDir)/../CxxBuilderPath.txt"]
[Configs.Release.Linux64]
PostBuildCmds = ["cp $(ProjectDir Cpp2Beef.git)/CxxBuilder/dist/CxxBuilderPath.txt $(WorkspaceDir)/../CxxBuilderPath.txt"]
[Configs.Release.macOS]
PostBuildCmds = ["cp $(ProjectDir Cpp2Beef.git)/CxxBuilder/dist/CxxBuilderPath.txt $(WorkspaceDir)/../CxxBuilderPath.txt"]
[Configs.Paranoid.Win32]
PostBuildCmds = ["cp $(ProjectDir Cpp2Beef.git)/CxxBuilder/dist/CxxBuilderPath.txt $(WorkspaceDir)/../CxxBuilderPath.txt"]
[Configs.Paranoid.Win64]
PostBuildCmds = ["cp $(ProjectDir Cpp2Beef.git)/CxxBuilder/dist/CxxBuilderPath.txt $(WorkspaceDir)/../CxxBuilderPath.txt"]
[Configs.Paranoid.Linux32]
PostBuildCmds = ["cp $(ProjectDir Cpp2Beef.git)/CxxBuilder/dist/CxxBuilderPath.txt $(WorkspaceDir)/../CxxBuilderPath.txt"]
[Configs.Paranoid.Linux64]
PostBuildCmds = ["cp $(ProjectDir Cpp2Beef.git)/CxxBuilder/dist/CxxBuilderPath.txt $(WorkspaceDir)/../CxxBuilderPath.txt"]
[Configs.Paranoid.macOS]
PostBuildCmds = ["cp $(ProjectDir Cpp2Beef.git)/CxxBuilder/dist/CxxBuilderPath.txt $(WorkspaceDir)/../CxxBuilderPath.txt"]
[Configs.Test.Win32]
PostBuildCmds = ["cp $(ProjectDir Cpp2Beef.git)/CxxBuilder/dist/CxxBuilderPath.txt $(WorkspaceDir)/../CxxBuilderPath.txt"]
[Configs.Test.Win64]
PostBuildCmds = ["cp $(ProjectDir Cpp2Beef.git)/CxxBuilder/dist/CxxBuilderPath.txt $(WorkspaceDir)/../CxxBuilderPath.txt"]
[Configs.Test.Linux32]
PostBuildCmds = ["cp $(ProjectDir Cpp2Beef.git)/CxxBuilder/dist/CxxBuilderPath.txt $(WorkspaceDir)/../CxxBuilderPath.txt"]
[Configs.Test.Linux64]
PostBuildCmds = ["cp $(ProjectDir Cpp2Beef.git)/CxxBuilder/dist/CxxBuilderPath.txt $(WorkspaceDir)/../CxxBuilderPath.txt"]
[Configs.Test.macOS]
PostBuildCmds = ["cp $(ProjectDir Cpp2Beef.git)/CxxBuilder/dist/CxxBuilderPath.txt $(WorkspaceDir)/../CxxBuilderPath.txt"]

6
Setup/BeefSpace.toml Normal file
View File

@@ -0,0 +1,6 @@
FileVersion = 1
Projects = {"Expat.Setup" = {Path = "."}, "Cpp2Beef.git" = {Git = "https://git.unicon-gmbh.de/BeefBindings/Cpp2Beef.git"}}
ExtraPlatforms = ["Linux32", "Linux64", "macOS"]
[Workspace]
StartupProject = "Expat.Setup"

11
Setup/BeefSpace_Lock.toml Normal file
View File

@@ -0,0 +1,11 @@
FileVersion = 1
[Locks."Clang-C.git".Git]
URL = "https://git.unicon-gmbh.de/BeefBindings/Clang-C.git"
Tag = ""
Hash = "86db0167f15d08a63a91a19e46f983a5511bac1a"
[Locks."Cpp2Beef.git".Git]
URL = "https://git.unicon-gmbh.de/BeefBindings/Cpp2Beef.git"
Tag = ""
Hash = "3590478b20da32b54f523780b5de819c27b95a47"

315
Setup/src/Program.bf Normal file
View File

@@ -0,0 +1,315 @@
using System;
using System.IO;
using System.Collections;
using System.Diagnostics;
using Cpp2Beef;
using LibClang;
namespace Expat.Setup;
class ExpatGenerator : Cpp2BeefGenerator, this(Span<char8*> args)
{
protected override Span<char8*> Args => args;
protected override Flags Flags => .None;
StreamWriter writter = new .()..Create("../src/Expat.bf")..Write("""
// This file was generated by Cpp2Beef
using System;
using System.Interop;
namespace Expat;
static class XML
{
public typealias Char = c_char;
public typealias LChar = c_char;
public typealias Index = c_long;
public typealias Size = c_ulong;
public struct Bool : c_uchar
{
public static operator bool(Self b) => b != FALSE;
public static operator Self(bool b) => b ? TRUE : FALSE;
}
}
""") ~ delete _;
protected override System.IO.StreamWriter GetWriterForHeader(StringView header)
{
return header.EndsWith("expat.h") ? writter : null;
}
protected override void WriteToken(CXToken token)
{
if (GetTokenSpelling!(token) == "XML_Bool")
str.Append("Bool");
else
base.WriteToken(token);
}
protected override Block GetCursorBlock(CXCursor cursor)
{
return .CustomBlock("XML");
}
protected override void HandleCursor(CXCursor cursor)
{
switch (cursor.kind)
{
case .MacroDefinition:
let spelling = GetCursorSpelling!(cursor);
if (spelling.StartsWith("XML_STATUS_") || spelling.StartsWith("XML_GetError"))
return;
case .TypedefDecl:
let spelling = GetCursorSpelling!(cursor);
if (spelling == "XML_Bool")
return;
if (spelling == "XML_Parser")
{
BeginCursor(cursor);
str.Append("public struct Parser : int {}");
return;
}
default:
}
base.HandleCursor(cursor);
}
protected override void GetNameInBindings(LibClang.CXCursor cursor, String outString)
{
GetNameInBindingsStatic(cursor, outString, scope () => base.GetNameInBindings(cursor, outString));
}
public static void GetNameInBindingsStatic(LibClang.CXCursor cursor, String outString, delegate void() fallback)
{
var spelling = GetCursorSpelling!(cursor);
switch (cursor.kind)
{
case .EnumConstantDecl:
switch (GetCursorSpelling!(Clang.GetCursorSemanticParent(cursor)))
{
case "XML_Status": spelling.RemoveFromStart("XML_STATUS_".Length);
case "XML_Error": spelling.RemoveFromStart("XML_ERROR_".Length);
case "XML_Content_Type": spelling.RemoveFromStart("XML_CTYPE_".Length);
case "XML_Content_Quant": spelling.RemoveFromStart("XML_CQUANT_".Length);
case "XML_ParamEntityParsing": spelling.RemoveFromStart("XML_PARAM_ENTITY_PARSING_".Length);
case "XML_FeatureEnum": spelling.RemoveFromStart("XML_FEATURE_".Length);
}
bool upper = true;
for (let c in spelling)
if (c == '_') upper = true;
else if (upper) { outString.Append(c.ToUpper); upper = false; }
else outString.Append(c.ToLower);
default:
if (!spelling.StartsWith("XML_"))
{
fallback();
return;
}
spelling.RemoveFromStart(4);
outString.Append(spelling);
}
}
}
class ExpatWrapperGenerator : Cpp2BeefGenerator, this(Span<char8*> args)
{
protected override Span<char8*> Args => args;
protected override Flags Flags => .None;
BumpAllocator alloc = new .() ~ delete _;
StreamWriter writer = new:alloc .()..Create("../src/Wrapper.bf")..Write("""
// This file was generated by Expat.Setup
using System;
using System.Interop;
namespace Expat;
class XmlParser
{
private XML.Parser handle ~ XML.ParserFree(_);
public Result<void> ParserInitResult => handle == default ? .Err : .Ok;
""");
List<(StringView name, StringView args, int numArgs)> handlers = new:alloc .(16);
protected override StreamWriter GetWriterForHeader(StringView header)
{
return header.EndsWith("expat.h") ? writer : null;
}
protected override Block GetCursorBlock(CXCursor cursor)
{
return .NoBlock;
}
protected override void GetNameInBindings(LibClang.CXCursor cursor, String outString)
{
outString.Append("XML.");
ExpatGenerator.GetNameInBindingsStatic(cursor, outString, scope () =>
{
outString.Length -= 4;
base.GetNameInBindings(cursor, outString);
});
}
protected override void HandleCursor(CXCursor cursor)
{
switch (cursor.kind)
{
case .FunctionDecl:
var spelling = GetCursorSpelling!(cursor);
if (spelling.StartsWith("XML_") && spelling != "XML_ParserFree")
spelling.RemoveFromStart(4);
else
return;
void WriteArgList(uint32 start)
{
uint32 i = start;
for (; i < (.)Clang.Cursor_GetNumArguments(cursor); i++)
{
if (i > start) str.Append(", ");
Compiler.Identifier.GetSourceName(GetCursorSpelling!(Clang.Cursor_GetArgument(cursor, i)), str);
}
}
if (spelling.StartsWith("ParserCreate"))
{
BeginCursor(cursor);
str.Append("[Inline] public this(");
Method_Parameters(cursor);
str.Append(") { handle = XML.", spelling, "(");
WriteArgList(0);
str.Append("); InitHandlers(); }");
return;
}
if (Clang.Cursor_GetNumArguments(cursor) < 1 || GetTypeSpelling!(Clang.GetCursorType(Clang.Cursor_GetArgument(cursor, 0))) != "XML_Parser")
return;
BeginCursor(cursor);
str.Append("[Inline] public ");
Type(Clang.GetCursorResultType(cursor));
str.Append(' ');
if (spelling.Contains("Parser"))
{
Flush();
str.Append(spelling);
str.Replace("Parser", "");
}
else
str.Append(spelling);
str.Append('(');
int index = str.Length;
Method_Parameters(cursor);
int length = str.IndexOf(',');
if (length >= 0)
str.Remove(index, length - index + 2);
else
str.RemoveToEnd(index);
str.Append(") => XML.", spelling, "(handle");
if (length >= 0) str.Append(", ");
WriteArgList(1);
str.Append(");");
case .TypedefDecl:
var spelling = GetCursorSpelling!(cursor);
let type = Clang.GetTypedefDeclUnderlyingType(cursor);
let proto = Clang.GetPointeeType(type);
if (spelling.StartsWith("XML_") && type.kind == .Pointer && (proto.kind == .FunctionProto || proto.kind == .FunctionNoProto))
spelling.RemoveFromStart(4);
else
return;
Flush();
WriteFunctionProtoParams(proto, ScopeTokenize!(cursor, unit));
StringView args;
{
args = scope String(str);
str.Clear();
if (!args.StartsWith("(void* userData"))
return;
args.RemoveFromStart("(void* userData".Length);
if (args.StartsWith(','))
args.RemoveFromStart(", ".Length);
args = new:alloc String(args);
}
handlers.Add((new:alloc String(spelling), args, Clang.GetNumArgTypes(proto) - 1));
BeginCursor(cursor);
str.Append("public virtual ");
let result = Clang.GetResultType(proto);
Type(result);
str.Append(" ", spelling, "(", args, result.kind == .Void ? " {}" : " => default;");
default:
}
}
protected override void PostGeneration()
{
str.Append("""
private void InitHandlers()
{
SetUserData(Internal.UnsafeCastToPtr(this));
""");
for (let handler in handlers)
{
str.Append("\t\tSet", handler.name, "((userData");
for (let i < handler.numArgs)
{
str.Append(", ");
str.Append('a' + i);
}
str.Append(") => ((Self)Internal.UnsafeCastToObject(userData)).", handler.name, "(");
for (let i < handler.numArgs)
{
if (i != 0) str.Append(", ");
str.Append('a' + i);
}
str.Append("));\n");
}
str.Append("""
}
}
""");
Flush();
}
}
class Program
{
[CLink] static extern int32 system(char8*);
static mixin RunCommand(char8* cmd)
{
Console.WriteLine($"> {StringView(cmd)}");
int32 rcode = system(cmd);
if (rcode != 0)
return rcode;
}
public static int Main(String[] args)
{
RunCommand!("git -C .. submodule update");
char8*[?] clangArgs = .("--language=c", "-I../libexpat/expat/lib", "-DXMLCALL=");
{ scope ExpatGenerator(clangArgs).Generate("../libexpat/expat/lib/expat.h", null); }
{ scope ExpatWrapperGenerator(clangArgs).Generate("../libexpat/expat/lib/expat.h", null); }
Directory.CreateDirectory("../expat_config");
RunCommand!("cmake -S ../libexpat/expat -B ../expat_config -GNinja");
return 0;
}
}