using System; using System.IO; using System.Collections; using System.Diagnostics; using Cpp2Beef; using LibClang; namespace KTX.Setup; class ExampleGenerator : Cpp2BeefGenerator, this(Span args) { protected override Span Args => args; protected override Flags Flags => .None; StreamWriter ktxWriter = new .()..Create("../src/KTX.bf")..Write(""" // This file was generated by Cpp2Beef using System; using System.Interop; namespace KTX; """) ~ delete _; StreamWriter ktxVulkanWriter = new .()..Create("../src/KTXVulkan.bf")..Write(""" // This file was generated by Cpp2Beef using System; using System.Interop; namespace KTX; """) ~ delete _; StreamWriter khrDfWriter = new .()..Create("../src/KHR_df.bf")..Write(""" // This file was generated by Cpp2Beef using System; using System.Interop; namespace KTX; """) ~ delete _; protected override StreamWriter GetWriterForHeader(StringView header) { if (header.EndsWith("ktx.h")) return ktxWriter; if (header.EndsWith("ktxvulkan.h")) return ktxVulkanWriter; if (header.EndsWith("khr_df.h")) return khrDfWriter; return null; } Dictionary vtblPfns = new .(24) ~ DeleteDictionaryAndKeys!(_); protected override void HandleCursor(CXCursor cursor) { switch (cursor.kind) { case .TypedefDecl: let spelling = GetCursorSpelling!(cursor); if (spelling == "ktxHashList" || spelling == "ktxHashListEntry" || spelling == "ktxStream") return; case .MacroDefinition: let spelling = GetCursorSpelling!(cursor); if (spelling == "KTXTEXTURECLASSDEFN" || spelling == "KTX_APIENTRYP" || spelling == "KTX_API" || spelling == "KTX_APIENTRY" || spelling == "KTX_error_code") return; if (Clang.Cursor_IsMacroFunctionLike(cursor) == 0 || !spelling.StartsWith("ktx")) break; BeginCursor(cursor); AccessSpecifier(cursor); str.Append("static "); let nameInBindings = spelling[(spelling.IndexOf('_')+1)...]; Runtime.Assert(vtblPfns.TryGetAlt(nameInBindings, ?, let pfnType)); Type(Clang.GetResultType(pfnType)); str.Append(' '); str.Append(nameInBindings); Flush(); let tokens = ScopeTokenize!(cursor, unit); WriteTokens(tokens[1...], Clang.GetRangeEnd(Clang.Cursor_GetSpellingNameRange(cursor, 0, 0)), .Identifier); String buffer = scope .(256)..Append(str); uint32 argI = 0; insert: for (int i = 0; i < buffer.Length; i++) { switch (buffer[i]) { case '(', ',': str.Clear(); Type(Clang.GetArgType(pfnType, argI++)); str.Append(' '); int idx = i+1 + (_ == ',' ? 1 : 0); buffer.Insert(idx, str); case ')': buffer.Insert(i+1, " =>"); break insert; } } buffer.Replace("->", "."); str.Set(buffer); str.Append(';'); return; case .StructDecl: if (Clang.Cursor_IsAnonymous(cursor) != 0) return; if (Clang.GetCursorLexicalParent(cursor).kind == .StructDecl) return; let spelling = GetCursorSpelling!(cursor); if (spelling == "ktxKVListEntry" || (spelling == "ktxStream" && Clang.EqualCursors(cursor, Clang.GetTypeDeclaration(Clang.GetCursorType(cursor))) != 0)) return; BeginCursor(cursor); Record(cursor); return; case .FieldDecl: if (GetCursorSpelling!(Clang.GetCursorSemanticParent(cursor)) == "ktxTexture_vtbl") vtblPfns.Add(new .(GetCursorSpelling!(cursor)), Clang.GetPointeeType(Clang.GetTypedefDeclUnderlyingType(Clang.GetTypeDeclaration(Clang.GetCursorType(cursor)))) ); default: } base.HandleCursor(cursor); if (fileInfo.prevEnd == default) fileInfo.prevEnd = GetCursorAnchor(cursor); } append String blockBuffer; protected override Block GetCursorBlock(CXCursor cursor) { if (cursor.kind == .FunctionDecl || cursor.kind == .MacroDefinition) do { let spelling = GetCursorSpelling!(cursor); if (!spelling.StartsWith("ktx")) break; int index = spelling.IndexOf('_'); if (index < 0) break; blockBuffer.Set(spelling[..