diff --git a/build.bat b/build.bat deleted file mode 100644 index 744cfad..0000000 --- a/build.bat +++ /dev/null @@ -1,12 +0,0 @@ -@echo off - -cd /D "%~dp0" rem cd into script dir - -if not exist build\build_tool.exe ( - mkdir build - cd build - cl -Fe:build_tool.exe ../src/build_tool/build_tool_main.cpp -FC -WX -W3 -wd4200 -wd4244 -diagnostics:column -nologo -Zi - cd .. -) - -build\build_tool.exe \ No newline at end of file diff --git a/build_file.cpp b/build_file.cpp deleted file mode 100644 index db5ea29..0000000 --- a/build_file.cpp +++ /dev/null @@ -1,403 +0,0 @@ -#include "src/build_tool/library.cpp" - -enum { - PROFILE_DEBUG, - PROFILE_RELEASE, -}; -int Profile = PROFILE_DEBUG; -#if OS_WINDOWS -S8_String Compiler = "cl.exe"; -#else -S8_String Compiler = "clang"; -#endif - -void AddCommonFlags(Array *cmd) { - if (Compiler == "clang") { - cmd->add("-g"); - cmd->add("-Wno-writable-strings"); - cmd->add("-fdiagnostics-absolute-paths"); - cmd->add("-nostdlib++"); - cmd->add("-fno-exceptions"); - } else { - if (Compiler == "cl.exe") { - cmd->add("/MP"); - } - cmd->add("/Zi /FC /nologo"); - cmd->add("/WX /W3 /wd4200 /diagnostics:column"); - if (Compiler == "clang-cl.exe") { - cmd->add("-fdiagnostics-absolute-paths"); - cmd->add("-Wno-missing-braces"); - cmd->add("-Wno-writable-strings"); - cmd->add("-Wno-unused-function"); - } - cmd->add("/Oi"); - cmd->add("-D_CRT_SECURE_NO_WARNINGS"); - if (Profile == PROFILE_DEBUG) { - cmd->add("-DDEBUG_BUILD=1"); - cmd->add("-DRELEASE_BUILD=0"); - // cmd->add("-fsanitize=address"); - // cmd->add("-DUSE_ADDRESS_SANITIZER"); - // cmd->add("/MDd"); - } else { - cmd->add("-DDEBUG_BUILD=0"); - cmd->add("-DRELEASE_BUILD=1"); - cmd->add("/O2 /MT /DNDEBUG /GL"); - } - } -} - -struct Library { - Array sources; - Array objects; - Array include_paths; - Array defines; - Array link; -}; - -Library PrepareSDL() { - Library l = {}; - l.include_paths.add("../src/external/SDL/include"); - l.objects.add("../src/external/SDL/VisualC/static_x64/Release/SDL3.lib"); - l.link.add("/SUBSYSTEM:WINDOWS"); - l.link.add("opengl32.lib"); - l.link.add("imm32.lib"); - l.link.add("gdi32.lib"); - l.link.add("winmm.lib"); - l.link.add("shell32.lib"); - l.link.add("user32.lib"); - l.link.add("advapi32.lib"); - l.link.add("Setupapi.lib"); - l.link.add("ole32.lib"); - l.link.add("oleaut32.lib"); - l.link.add("Version.lib"); - return l; -} - -Library PrepareSDLDynamic() { - Library l = {}; - l.include_paths.add("../src/external/SDL/include"); - l.objects.add("../src/external/SDL/VisualC/x64/Release/SDL3.lib"); - l.link.add("/SUBSYSTEM:WINDOWS"); - OS_CopyFile("../src/external/SDL/VisualC/x64/Release/SDL3.dll", "./SDL3.dll", false); - return l; -} - -Library PrepareLua() { - Library l = {}; - l.include_paths.add("../src/external/lua/src"); - - MA_Scratch scratch; - for (OS_FileIter it = OS_IterateFiles(scratch, "../src/external/lua/src"); OS_IsValid(it); OS_Advance(&it)) { - if (it.filename == "luac.c") continue; - if (it.filename == "lua.c") continue; - if (S8_EndsWith(it.filename, ".c", true)) { - l.sources.add(it.absolute_path); - S8_String file = S8_ChopLastPeriod(it.filename); - l.objects.add(Fmt("%.*s" IF_WINDOWS_ELSE(".obj", ".o"), S8_Expand(file))); - } - } - - if (!OS_FileExists(l.objects[0])) { - Array cmd = {}; - cmd.add(Compiler); - cmd.add("-c"); - AddCommonFlags(&cmd); - For(l.include_paths) cmd.add(S8_Format(Perm, "-I %.*s ", S8_Expand(it))); - cmd += l.sources; - Run(cmd); - } - return l; -} - -Library PrepareGlad() { - Library l = {}; - l.sources.add("../src/external/glad/glad.c"); - l.include_paths.add("../src/external/glad/"); -#if OS_WINDOWS - l.objects.add("glad.obj"); -#else - l.objects.add("glad.o"); -#endif - if (!OS_FileExists(l.objects[0])) { - Array cmd = {}; - cmd.add(Compiler); - cmd.add("-c"); - AddCommonFlags(&cmd); - For(l.include_paths) cmd.add(S8_Format(Perm, "-I %.*s ", S8_Expand(it))); - cmd += l.sources; - Run(cmd); - } - return l; -} - -int CompileTextEditorLinux() { - Array cmd = {}; - - Array libs = {}; - libs.add(PrepareLua()); - libs.add(PrepareGlad()); - - cmd.add("clang"); - cmd.add("../src/text_editor/text_editor.cpp"); - cmd.add("../src/basic/unix.cpp"); - cmd.add("-o te_linux.exe"); - cmd.add("-I../src"); - // cmd.add("-Wall"); - AddCommonFlags(&cmd); - For2(lib, libs) For(lib.include_paths) cmd.add(Fmt("-I %.*s", S8_Expand(it))); - For2(lib, libs) For(lib.defines) cmd.add(it); - // cmd.add("-L../src/external/SDL/build/"); - cmd.add("-I../src/external/SDL/include"); - cmd.add("-lm"); - cmd.add("../src/external/SDL/build/libSDL3.a"); - For2(lib, libs) For(lib.link) cmd.add(it); - For(libs) For2(o, it.objects) cmd.add(o); - - int result = Run(cmd); - return result; -} - -int CompileTextEditor() { - int result = 0; - - Array libs = {}; - // if (Profile == PROFILE_DEBUG) libs.add(PrepareSDLDynamic()); - // else - libs.add(PrepareSDL()); - libs.add(PrepareLua()); - libs.add(PrepareGlad()); - - Array cmd = {}; - cmd.add(Compiler); - cmd.add("-Fe:te.exe"); - cmd.add("-Fd:te.pdb"); - cmd.add("-I ../src"); - AddCommonFlags(&cmd); - For2(lib, libs) For(lib.defines) cmd.add(it); - - cmd.add("../src/text_editor/text_editor.cpp"); - cmd.add("../src/basic/win32.cpp"); - - For2(lib, libs) For(lib.include_paths) cmd.add(Fmt("-I %.*s", S8_Expand(it))); - - cmd.add("/link"); - cmd.add("/incremental:no"); - // cmd.add("/SUBSYSTEM:WINDOWS"); - // cmd.add("opengl32.lib gdi32.lib winmm.lib shell32.lib user32.lib msvcrt.lib /NODEFAULTLIB:LIBCMT"); - For2(lib, libs) For(lib.link) cmd.add(it); - For(libs) For2(o, it.objects) cmd.add(o); - cmd.add("icon.res"); - - OS_DeleteFile("te.pdb"); - // For(cmd) IO_Printf("%.*s\n", S8_Expand(it)); - if (!OS_FileExists("icon.res")) { - OS_CopyFile("../data/icon.ico", "icon.ico", true); - OS_CopyFile("../data/icon.rc", "icon.rc", true); - Run("rc icon.rc"); - } - result += Run(cmd); - if (result == 0) { - OS_MakeDir("../package"); - OS_CopyFile("../build/te.exe", "../package/te.exe", true); - OS_CopyFile("../build/te.pdb", "../package/te.pdb", true); - } - - return result; -} - -char *C(const char *value) { - if (value[0] == '0' && value[1] == 'x') { - S8_String f = Fmt("{0x%.*s, 0x%.*s, 0x%.*s, 0x%.*s}", 2, value + 2, 2, value + 4, 2, value + 6, 2, value + 8); - return f.str; - } else { - return (char *)value; - } -} - -void GenerateConfig() { - struct Var { - const char *name; - const char *value; - }; - - Array gruvbox = {}; - gruvbox.add({"GruvboxDark0Hard", "0x1d2021ff"}); - gruvbox.add({"GruvboxDark0", "0x282828ff"}); - gruvbox.add({"GruvboxDark0Soft", "0x32302fff"}); - gruvbox.add({"GruvboxDark1", "0x3c3836ff"}); - gruvbox.add({"GruvboxDark2", "0x504945ff"}); - gruvbox.add({"GruvboxDark3", "0x665c54ff"}); - gruvbox.add({"GruvboxDark4", "0x7c6f64ff"}); - gruvbox.add({"GruvboxGray245", "0x928374ff"}); - gruvbox.add({"GruvboxGray244", "0x928374ff"}); - gruvbox.add({"GruvboxLight0Hard", "0xf9f5d7ff"}); - gruvbox.add({"GruvboxLight0", "0xfbf1c7ff"}); - gruvbox.add({"GruvboxLight0Soft", "0xf2e5bcff"}); - gruvbox.add({"GruvboxLight1", "0xebdbb2ff"}); - gruvbox.add({"GruvboxLight2", "0xd5c4a1ff"}); - gruvbox.add({"GruvboxLight3", "0xbdae93ff"}); - gruvbox.add({"GruvboxLight4", "0xa89984ff"}); - gruvbox.add({"GruvboxBrightRed", "0xfb4934ff"}); - gruvbox.add({"GruvboxBrightGreen", "0xb8bb26ff"}); - gruvbox.add({"GruvboxBrightYellow", "0xfabd2fff"}); - gruvbox.add({"GruvboxBrightBlue", "0x83a598ff"}); - gruvbox.add({"GruvboxBrightPurple", "0xd3869bff"}); - gruvbox.add({"GruvboxBrightAqua", "0x8ec07cff"}); - gruvbox.add({"GruvboxBrightOrange", "0xfe8019ff"}); - gruvbox.add({"GruvboxNeutralRed", "0xcc241dff"}); - gruvbox.add({"GruvboxNeutralGreen", "0x98971aff"}); - gruvbox.add({"GruvboxNeutralYellow", "0xd79921ff"}); - gruvbox.add({"GruvboxNeutralBlue", "0x458588ff"}); - gruvbox.add({"GruvboxNeutralPurple", "0xb16286ff"}); - gruvbox.add({"GruvboxNeutralAqua", "0x689d6aff"}); - gruvbox.add({"GruvboxNeutralOrange", "0xd65d0eff"}); - gruvbox.add({"GruvboxFadedRed", "0x9d0006ff"}); - gruvbox.add({"GruvboxFadedGreen", "0x79740eff"}); - gruvbox.add({"GruvboxFadedYellow", "0xb57614ff"}); - gruvbox.add({"GruvboxFadedBlue", "0x076678ff"}); - gruvbox.add({"GruvboxFadedPurple", "0x8f3f71ff"}); - gruvbox.add({"GruvboxFadedAqua", "0x427b58ff"}); - gruvbox.add({"GruvboxFadedOrange", "0xaf3a03ff"}); - - Array colors = {}; - colors.add({"Text", "GruvboxDark0Hard"}); - colors.add({"LoadTextHighlight", "0x0000000F"}); - colors.add({"Background", "GruvboxLight0Hard"}); - colors.add({"InactiveWindow", "0x0000000F"}); - colors.add({"TextLineNumbers", "GruvboxDark4"}); - colors.add({"LineHighlight", "GruvboxLight0Soft"}); - colors.add({"MainCaret", "GruvboxDark0Hard"}); - colors.add({"SubCaret", "GruvboxGray245"}); - colors.add({"Selection", "GruvboxLight1"}); - colors.add({"WhitespaceDuringSelection", "GruvboxLight4"}); - colors.add({"MouseUnderline", "GruvboxDark0Hard"}); - colors.add({"CaretUnderline", "GruvboxGray245"}); - - colors.add({"FuzzySearchLineHighlight", "GruvboxDark0"}); - - colors.add({"ScrollbarBackground", "GruvboxLight2"}); - colors.add({"ScrollbarScroller", "GruvboxLight1"}); - colors.add({"ScrollbarScrollerSelected", "GruvboxLight0Hard"}); - - colors.add({"TitleBarText", "GruvboxDark2"}); - colors.add({"TitleBarBackground", "GruvboxLight1"}); - colors.add({"TitleBarActiveBackground", "0xfefefefe"}); - colors.add({"TitleBarSelection", "GruvboxLight3"}); - - colors.add({"ResizerBackground", "GruvboxLight0Hard"}); - colors.add({"ResizerOutline", "GruvboxLight3"}); - - Array style = {}; - style.add({"WaitForEvents", "1"}); - style.add({"DrawLineNumbers", "1"}); - style.add({"DrawScrollbar", "1"}); - style.add({"IndentSize", "4"}); - style.add({"FontSize", "15"}); - style.add({"FontFilter", "0"}); // nearest = 0, linear = 1 - seems like nearest always better? - style.add({"Font", "/home/krz/text_editor/package/CascadiaMono.ttf"}); - style.add({"VCVarsall", "C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Auxiliary/Build/vcvars64.bat"}); - - { - MA_Scratch scratch; - Array sb = {MA_GetAllocator(scratch)}; - { - For(gruvbox) sb.add(Fmt("Color %s = %s;", it.name, C(it.value))); - For(colors) sb.add(Fmt("Color Color%s = %s;", it.name, C(it.value))); - For(style) { - if (CHAR_IsDigit(it.value[0])) { - sb.add(Fmt("Int Style%s = %s;", it.name, it.value)); - } else { - sb.add(Fmt("String Style%s = \"%s\";", it.name, it.value)); - } - } - } - S8_String string = Merge(scratch, sb, "\n"); - OS_WriteFile("../src/text_editor/generated_variables.cpp", string); - sb = {}; - - sb.add("String BaseLuaConfig = R\"==("); - { - For(gruvbox) sb.add(Fmt("local %s = %s", it.name, it.value)); - - sb.add("Color = {}"); - For(colors) sb.add(Fmt("Color.%s = %s", it.name, it.value)); - - sb.add("Style = {}"); - For(style) { - if (CHAR_IsDigit(it.value[0])) sb.add(Fmt("Style.%s = %s", it.name, it.value)); - else sb.add(Fmt("Style.%s = \"%s\"", it.name, it.value)); - } - - S8_String init_file = OS_ReadFile(scratch, "../data/init.lua"); - sb.add(init_file); - } - sb.add(")==\";"); - - sb.add("void ReloadStyle() {"); - { - For(colors) sb.add(Fmt(" Color%s = GetColor(\"%s\", Color%s);", it.name, it.name, it.name)); - For(style) { - if (CHAR_IsDigit(it.value[0])) sb.add(Fmt(" Style%s = GetStyleInt(\"%s\", Style%s);", it.name, it.name, it.name)); - else sb.add(Fmt(" Style%s = GetStyleString(\"%s\", Style%s);", it.name, it.name, it.name)); - } - } - sb.add("}"); - - string = Merge(scratch, sb, "\n"); - OS_WriteFile("../src/text_editor/generated.cpp", string); - } -} - -void GenerateLuaApi() { - MA_Scratch scratch; - S8_String file = OS_ReadFile(scratch, "../src/text_editor/lua_api.cpp"); - S8_String file2 = OS_ReadFile(scratch, "../src/text_editor/commands.cpp"); - S8_List list = S8_Split(scratch, file, "\n"); - S8_List list2 = S8_Split(scratch, file2, "\n"); - list = S8_ConcatLists(scratch, list, list2); - - S8_List funcs = {}; - for (S8_Node *it = list.first; it; it = it->next) { - S8_String s = S8_Trim(it->string); - if (S8_StartsWith(s, "int Lua_")) { - s = S8_Skip(s, 4); - S8_Seek(s, "(", 0, &s.len); - S8_Add(scratch, &funcs, s); - } - } - - S8_List sb = {}; - S8_AddF(scratch, &sb, "luaL_Reg LuaFunctions[] = {\n"); - for (S8_Node *it = funcs.first; it; it = it->next) { - S8_String lua_name = S8_Skip(it->string, 4); - S8_AddF(scratch, &sb, " {\"%.*s\", %.*s},\n", S8_Expand(lua_name), S8_Expand(it->string)); - } - S8_AddF(scratch, &sb, " {NULL, NULL},\n"); - S8_AddF(scratch, &sb, "};\n"); - - S8_String output = S8_Merge(scratch, sb); - OS_WriteFile("../src/text_editor/lua_api_generated.cpp", output); -} - -int main() { - MA_InitScratch(); - SRC_InitCache(Perm, "te.cache"); - - GenerateLuaApi(); - GenerateConfig(); - -#if OS_WINDOWS - int result = CompileTextEditor(); -#else - int result = CompileTextEditorLinux(); -#endif - // int result = CompileNewPlatform(); - - if (result != 0) { - OS_DeleteFile("te.cache"); - return result; - } - - SRC_SaveCache(); - return 0; -} diff --git a/src/build_tool/build_tool_main.cpp b/src/build_tool/build_tool_main.cpp deleted file mode 100644 index 84381b3..0000000 --- a/src/build_tool/build_tool_main.cpp +++ /dev/null @@ -1,90 +0,0 @@ -#include "library.cpp" - -int main(int argument_count, char **arguments) { - MA_InitScratch(); - OS_MakeDir(S8_Lit("build")); - OS_SetWorkingDir(S8_Lit("build")); - S8_String working_dir = OS_GetWorkingDir(Perm); - IO_Printf("WORKING DIR: %.*s\n", S8_Expand(working_dir)); - - Array cmd = CMD_Make(arguments, argument_count); - S8_String cc = CMD_Get(cmd, "cc", IF_WINDOWS("cl") IF_MAC("clang") IF_LINUX("clang")); - - // Search for build file in the project directory - S8_String build_file = {}; - { - for (OS_FileIter it = OS_IterateFiles(Perm, S8_Lit("..")); OS_IsValid(it); OS_Advance(&it)) { - if (S8_Seek(it.filename, S8_Lit("build_file.c"), S8_IgnoreCase)) { - build_file = it.absolute_path; - } - } - - if (build_file.str == 0) { - IO_Printf("Couldnt find build file in current dir: %.*s, exiting ... \n", S8_Expand(working_dir)); - IO_Printf("- Proper build file contains 'build_file.c' in it's name\n"); - IO_Printf("- Alternative compiler can be chosen like this: bld cc=clang\n"); - return 0; - } - } - - SRC_InitCache(Perm, "build_tool.cache"); - S8_String name_no_ext = S8_GetNameNoExt(build_file); - S8_String exe_name = S8_Format(Perm, "%.*s.exe", S8_Expand(name_no_ext)); - - // Compile the build file only if code changed - if (SRC_WasModified(build_file, exe_name)) { - double time = OS_GetTime(); - int result = 0; - if (cc == "cl") { - Array flags = {MA_GetAllocator(Perm)}; - flags += "-nologo -Zi"; - flags += "-WX -W3 -wd4200 -diagnostics:column"; - flags += Fmt("/Fe:%.*s /Fd:%.*s.pdb", S8_Expand(exe_name), S8_Expand(exe_name)); - result = Run(cc + build_file + flags); - } else if (cc == "clang") { - Array flags = {MA_GetAllocator(Perm)}; - cc = "clang++"; - - flags += "-std=c++11 -g"; - flags += "-fdiagnostics-absolute-paths"; - flags += "-Wno-writable-strings"; - flags += "-lm"; - flags += Fmt("-o %.*s", S8_Expand(exe_name)); - result = Run(cc + build_file + flags); - } else { - IO_Assert(cc == "gcc"); - cc = "g++"; - - Array flags = {MA_GetAllocator(Perm)}; - flags += "-std=c++11 -g"; - flags += "-Wno-write-strings"; - flags += "-lm"; - flags += Fmt("-o %.*s", S8_Expand(exe_name)); - result = Run(cc + build_file + flags); - } - - if (result != 0) { - IO_Printf("FAILED compilation of the build file!\n"); - OS_DeleteFile("build_tool.cache"); - return 1; - } - time = OS_GetTime() - time; - IO_Printf("TIME Build file compilation: %f\n", time); - } - - // Run the build file - double time = OS_GetTime(); - if (build_file.str) { - exe_name = OS_GetAbsolutePath(Perm, exe_name); - int result = Run(exe_name + cmd); - if (result != 0) { - IO_Printf("FAILED execution of the build file, deleting cache!\n"); - OS_DeleteFile("build_tool.cache"); - return 1; - } - } - - SRC_SaveCache(); - time = OS_GetTime() - time; - IO_Printf("TIME total build file execution: %f\n", time); -} diff --git a/src/build_tool/cache.cpp b/src/build_tool/cache.cpp deleted file mode 100644 index 8cbc0cf..0000000 --- a/src/build_tool/cache.cpp +++ /dev/null @@ -1,135 +0,0 @@ -/* @todo: I guess I'm overcomplicating a little: -https://github.com/Mango0x45/cbs/ - -Seems like you only need to compare timestamps of all files with the artifact timestamp, -if one of the files is newer then the artifact then it needs to be recompiled. Do we -even need to store anything then? Just supply artifact file in code and that's it? - -*/ -#define SRC_CACHE_ENTRY_COUNT 1024 - -struct SRC_CacheEntry { - uint64_t filepath_hash; - uint64_t file_hash; - uint64_t includes_hash; - uint64_t total_hash; -}; - -struct SRC_Cache { - int entry_cap; - int entry_len; - SRC_CacheEntry entries[SRC_CACHE_ENTRY_COUNT]; -}; - -double SRC_Time; -SRC_Cache *SRC_InMemoryCache; -SRC_Cache *SRC_FromFileCache; -S8_String SRC_CacheFilename; -CL_SearchPaths SRC_SearchPaths = {}; // @todo; - -void SRC_InitCache(MA_Arena *arena, S8_String cachefilename) { - SRC_CacheFilename = cachefilename; - - SRC_InMemoryCache = MA_PushStruct(arena, SRC_Cache); - SRC_InMemoryCache->entry_cap = SRC_CACHE_ENTRY_COUNT; - - SRC_FromFileCache = MA_PushStruct(arena, SRC_Cache); - SRC_FromFileCache->entry_cap = SRC_CACHE_ENTRY_COUNT; - - S8_String cache = OS_ReadFile(arena, SRC_CacheFilename); - if (cache.len) MA_MemoryCopy(SRC_FromFileCache, cache.str, cache.len); -} - -void SRC_SaveCache() { - S8_String dump = S8_Make((char *)SRC_InMemoryCache, sizeof(SRC_Cache)); - OS_WriteFile(SRC_CacheFilename, dump); -} - -SRC_CacheEntry *SRC_AddHash(uint64_t filepath, uint64_t file, uint64_t includes) { - IO_Assert(SRC_InMemoryCache->entry_len + 1 < SRC_InMemoryCache->entry_cap); - SRC_CacheEntry *result = SRC_InMemoryCache->entries + SRC_InMemoryCache->entry_len++; - result->filepath_hash = filepath; - result->file_hash = file; - result->includes_hash = includes; - result->total_hash = HashBytes(result, sizeof(uint64_t) * 3); - return result; -} - -SRC_CacheEntry *SRC_FindCache(SRC_Cache *cache, uint64_t filepath_hash) { - for (int cache_i = 0; cache_i < cache->entry_len; cache_i += 1) { - SRC_CacheEntry *it = cache->entries + cache_i; - if (it->filepath_hash == filepath_hash) { - return it; - } - } - return 0; -} - -SRC_CacheEntry *SRC_HashFile(S8_String file, char *parent_file) { - char *resolved_file = CL_ResolveFilepath(Perm, &SRC_SearchPaths, file.str, parent_file, false); - if (!resolved_file) { - IO_Printf("Failed to resolve file: %.*s\n", S8_Expand(file)); - return 0; - } - - uint64_t filepath_hash = HashBytes(resolved_file, S8_Length(resolved_file)); - SRC_CacheEntry *entry = SRC_FindCache(SRC_InMemoryCache, filepath_hash); - if (entry) return entry; - - S8_String filecontent = OS_ReadFile(Perm, S8_MakeFromChar(resolved_file)); - IO_Assert(filecontent.str); - - uint64_t file_hash = HashBytes(filecontent.str, filecontent.len); - uint64_t includes_hash = 13; - - CL_Lexer lexer = CL_Begin(Perm, filecontent.str, resolved_file); - lexer.select_includes = true; - - for (CL_Token token = CL_Next(&lexer); token.kind != CL_EOF; token = CL_Next(&lexer)) { - if (token.is_system_include) continue; - - S8_String file_it = S8_MakeFromChar(token.string_literal); - SRC_CacheEntry *cache = SRC_HashFile(file_it, resolved_file); - if (!cache) { - // error was reported already IO_Printf("Missing cache for: %.*s\n", S8_Expand(file_it)); - continue; - } - - includes_hash = HashMix(includes_hash, cache->total_hash); - } - - SRC_CacheEntry *result = SRC_AddHash(filepath_hash, file_hash, includes_hash); - return result; -} - -bool SRC_WasModified(S8_String file, S8_String artifact_path) { - double time_start = OS_GetTime(); - - if (OS_FileExists(file) == false) { - IO_Printf("FAILED File doesnt exist: %.*s\n", S8_Expand(file)); - exit(0); - } - if (OS_IsAbsolute(file) == false) { - file = OS_GetAbsolutePath(Perm, file); - } - - S8_String without_ext = S8_ChopLastPeriod(file); - S8_String name_only = S8_SkipToLastSlash(without_ext); - - if (artifact_path.len == 0) artifact_path = S8_Format(Perm, "%.*s.%s", S8_Expand(name_only), IF_WINDOWS_ELSE("obj", "o")); - bool modified = OS_FileExists(artifact_path) == false; - - SRC_CacheEntry *in_memory = SRC_HashFile(file, 0); - IO_Assert(in_memory); - - if (modified == false) { - SRC_CacheEntry *from_file = SRC_FindCache(SRC_FromFileCache, in_memory->filepath_hash); - if (from_file == 0 || (in_memory->total_hash != from_file->total_hash)) { - modified = true; - } - } - - SRC_Time = SRC_Time + (OS_GetTime() - time_start); - - return modified; -} \ No newline at end of file diff --git a/src/build_tool/core/allocator.c b/src/build_tool/core/allocator.c deleted file mode 100644 index 6b9cd65..0000000 --- a/src/build_tool/core/allocator.c +++ /dev/null @@ -1,115 +0,0 @@ -#ifndef MA_CMalloc - #include - #define MA_CMalloc(x) malloc(x) - #define MA_CFree(x) free(x) - #define MA_CRealloc(p, size) realloc(p, size) -#endif - -MA_API M_Allocator MA_BootstrapExclusive(void) { - MA_Arena bootstrap_arena = {0}; - MA_Arena *arena = MA_PushStruct(&bootstrap_arena, MA_Arena); - *arena = bootstrap_arena; - arena->base_len = arena->len; - return MA_GetExclusiveAllocator(arena); -} - -MA_API void *M__AllocNonZeroed(M_Allocator allocator, size_t size) { - void *p = allocator.p(allocator.obj, M_AllocatorOp_Allocate, NULL, size, 0); - return p; -} - -MA_API void *M__Alloc(M_Allocator allocator, size_t size) { - void *p = allocator.p(allocator.obj, M_AllocatorOp_Allocate, NULL, size, 0); - MA_MemoryZero(p, size); - return p; -} - -MA_API void *M__AllocCopy(M_Allocator allocator, void *p, size_t size) { - void *copy_buffer = M__AllocNonZeroed(allocator, size); - MA_MemoryCopy(copy_buffer, p, size); - return copy_buffer; -} - -MA_API void M__Dealloc(M_Allocator allocator, void *p) { - allocator.p(allocator.obj, M_AllocatorOp_Deallocate, p, 0, 0); -} - -MA_API void *M__Realloc(M_Allocator allocator, void *p, size_t size, size_t old_size) { - void *result = allocator.p(allocator.obj, M_AllocatorOp_Reallocate, p, size, old_size); - // @todo: add old_size? because we can't zero - return result; -} - -MA_StaticFunc void *M_ClibAllocatorProc(void *allocator, M_AllocatorOp kind, void *p, size_t size, size_t old_size) { - if (kind == M_AllocatorOp_Allocate) { - return MA_CMalloc(size); - } - - if (kind == M_AllocatorOp_Deallocate) { - MA_CFree(p); - return NULL; - } - - if (kind == M_AllocatorOp_Reallocate) { - return MA_CRealloc(p, size); - } - - MA_Assertf(0, "MA_Arena invalid codepath"); - return NULL; -} - -MA_API void *MA_AllocatorProc(void *allocator, M_AllocatorOp kind, void *p, size_t size, size_t old_size) { - if (kind == M_AllocatorOp_Allocate) { - return MA__PushSizeNonZeroed((MA_Arena *)allocator, size); - } - - else if (kind == M_AllocatorOp_Reallocate) { - void *new_p = MA__PushSizeNonZeroed((MA_Arena *)allocator, size); - MA_MemoryCopy(new_p, p, old_size); - return new_p; - } - - else if (kind == M_AllocatorOp_Deallocate) { - return NULL; - } - - MA_Assertf(0, "MA_Arena invalid codepath"); - return NULL; -} - -MA_API void *MA_ExclusiveAllocatorProc(void *allocator, M_AllocatorOp kind, void *p, size_t size, size_t old_size) { - MA_Arena *arena = (MA_Arena *)allocator; - if (kind == M_AllocatorOp_Reallocate) { - if (size > old_size) { - size_t size_to_push = size - old_size; - void *result = MA__PushSizeNonZeroed(arena, size_to_push); - if (!p) p = result; - return p; - } - } - - if (kind == M_AllocatorOp_Deallocate) { - MA_DeallocateArena(arena); - return NULL; - } - - MA_Assertf(0, "MA_Arena invalid codepath"); - return NULL; -} - -MA_API M_Allocator MA_GetExclusiveAllocator(MA_Arena *arena) { - M_Allocator allocator = {(int *)arena, MA_ExclusiveAllocatorProc}; - return allocator; -} - -MA_API M_Allocator MA_GetAllocator(MA_Arena *arena) { - M_Allocator allocator = {(int *)arena, MA_AllocatorProc}; - return allocator; -} - -MA_API M_Allocator M_GetSystemAllocator(void) { - M_Allocator allocator; - allocator.obj = 0; - allocator.p = M_ClibAllocatorProc; - return allocator; -} diff --git a/src/build_tool/core/allocator.h b/src/build_tool/core/allocator.h deleted file mode 100644 index a525b74..0000000 --- a/src/build_tool/core/allocator.h +++ /dev/null @@ -1,44 +0,0 @@ -typedef struct M_Allocator M_Allocator; - -typedef enum M_AllocatorOp { - M_AllocatorOp_Invalid, - M_AllocatorOp_Allocate, - M_AllocatorOp_Deallocate, - M_AllocatorOp_Reallocate, -} M_AllocatorOp; - -typedef void *M_AllocatorProc(void *allocator, M_AllocatorOp kind, void *p, size_t size, size_t old_size); -MA_API void *MA_AllocatorProc(void *allocator, M_AllocatorOp kind, void *p, size_t size, size_t old_size); -MA_API void *MA_ExclusiveAllocatorProc(void *allocator, M_AllocatorOp kind, void *p, size_t size, size_t old_size); - -struct M_Allocator { - // it's int for type safety because C++ somehow allows this: - // struct Array { M_Allocator allocator; } - // Array = {arena}; WTF???!??!? - // without actually passing M_Allocator but just a pointer - int *obj; - M_AllocatorProc *p; -}; - -#define M_AllocStruct(a, T) (T *)M_Alloc((a), sizeof(T)) -#define M_AllocArray(a, T, c) (T *)M_Alloc((a), sizeof(T) * (c)) -#define M_AllocStructNonZeroed(a, T) (T *)M_AllocNonZeroed((a), sizeof(T)) -#define M_AllocArrayNonZeroed(a, T, c) (T *)M_AllocNonZeroed((a), sizeof(T) * (c)) -#define M_AllocStructCopy(a, T, p) (T *)M_PushCopy(a, (p), sizeof(T)) - -#define M_Alloc(a, size) M__Alloc(a, size) -#define M_AllocNonZeroed(a, size) M__AllocNonZeroed(a, size) -#define M_AllocCopy(a, p, size) M__AllocCopy(a, p, size) -#define M_Realloc(a, p, size, old_size) M__Realloc(a, p, size, old_size) -#define M_Dealloc(a, p) M__Dealloc(a, p) - -MA_API void *M__AllocNonZeroed(M_Allocator allocator, size_t size); -MA_API void *M__Alloc(M_Allocator allocator, size_t size); -MA_API void *M__AllocCopy(M_Allocator allocator, void *p, size_t size); -MA_API void *M__Realloc(M_Allocator allocator, void *p, size_t size, size_t old_size); -MA_API void M__Dealloc(M_Allocator allocator, void *p); - -MA_API M_Allocator M_GetSystemAllocator(void); -MA_API M_Allocator MA_GetExclusiveAllocator(MA_Arena *arena); -MA_API M_Allocator MA_GetAllocator(MA_Arena *arena); -MA_API M_Allocator MA_BootstrapExclusive(void); diff --git a/src/build_tool/core/array.hpp b/src/build_tool/core/array.hpp deleted file mode 100644 index 612bcf1..0000000 --- a/src/build_tool/core/array.hpp +++ /dev/null @@ -1,270 +0,0 @@ -// Iterating and removing elements -// -// ForArrayRemovable(array) { -// ForArrayRemovablePrepare(array); -// if (it == 4) ForArrayRemovableDeclare(); -// } -// -#define ForArrayRemovable(a) for (int __i = 0; __i < (a).len; __i += 1) -#define ForArrayRemovablePrepare(a) \ - auto &it = (a)[__i]; \ - bool remove_it = false; \ - defer { \ - if (remove_it) { \ - (a).ordered_remove(it); \ - __i -= 1; \ - } \ - } -#define ForArrayRemovableDeclare() (remove_it = true) -#define For2(it, array) for (auto &it : (array)) -#define For(array) For2(it, array) - -template -struct Array { - M_Allocator allocator; - T *data; - int cap, len; - - T &operator[](int index) { - IO_Assert(index >= 0 && index < len); - return data[index]; - } - - bool is_first(T &item) { return &item == first(); } - bool is_last(T &item) { return &item == last(); } - - bool contains(T &item) { - bool result = &item >= data && &item < data + len; - return result; - } - - int get_index(T &item) { - IO_Assert((data <= &item) && ((data + len) > &item)); - size_t offset = &item - data; - return (int)offset; - } - - void add(const T &item) { - try_growing(); - data[len++] = item; - } - - // Struct needs to have 'value_to_sort_by' field - void sorted_insert_decreasing(T item) { - int insert_index = -1; - For(*this) { - if (it.value_to_sort_by <= item.value_to_sort_by) { - insert_index = get_index(it); - insert(item, insert_index); - break; - } - } - - if (insert_index == -1) { - add(item); - } - } - - void bounded_add(T item) { - IO_Assert(len + 1 <= cap); - try_growing(); // in case of error - data[len++] = item; - } - - T *alloc(const T &item) { - try_growing(); - T *ref = data + len++; - *ref = item; - return ref; - } - - T *alloc() { - try_growing(); - T *ref = data + len++; - *ref = {}; - return ref; - } - - T *alloc_multiple(int size) { - try_growing_to_fit_item_count(size); - T *result = data + len; - len += size; - return result; - } - - void add_array(T *items, int item_count) { - for (int i = 0; i < item_count; i += 1) { - add(items[i]); - } - } - - void add_array(Array items) { - add_array(items.data, items.len); - } - - void reserve(int size) { - if (size > cap) { - if (!allocator.p) allocator = M_GetSystemAllocator(); - - void *p = M_Realloc(allocator, data, size * sizeof(T), cap * sizeof(T)); - IO_Assert(p); - - data = (T *)p; - cap = size; - } - } - - void init(M_Allocator allocator, int size) { - len = 0; - cap = 0; - data = 0; - this->allocator = allocator; - reserve(size); - } - - void reset() { - len = 0; - } - - T pop() { - IO_Assert(len > 0); - return data[--len]; - } - - void unordered_remove(T &item) { // DONT USE IN LOOPS !!!! - IO_Assert(len > 0); - IO_Assert(&item >= begin() && &item < end()); - item = data[--len]; - } - - void unordered_remove_index(int index) { - IO_Assert(index >= 0 && index < len); - data[index] = data[--len]; - } - - int get_index(const T &item) { - ptrdiff_t index = (ptrdiff_t)(&item - data); - IO_Assert(index >= 0 && index < len); - // IO_Assert(index > INT_MIN && index < INT_MAX); - return (int)index; - } - - void ordered_remove(T &item) { // DONT USE IN LOOPS !!! - IO_Assert(len > 0); - IO_Assert(&item >= begin() && &item < end()); - int index = get_index(item); - ordered_remove_index(index); - } - - void ordered_remove_index(int index) { - IO_Assert(index >= 0 && index < len); - int right_len = len - index - 1; - memmove(data + index, data + index + 1, right_len * sizeof(T)); - len -= 1; - } - - void insert(T item, int index) { - if (index == len) { - add(item); - return; - } - - IO_Assert(index < len); - IO_Assert(index >= 0); - - try_growing(); - int right_len = len - index; - memmove(data + index + 1, data + index, sizeof(T) * right_len); - data[index] = item; - len += 1; - } - - void dealloc() { - if (data) M_Dealloc(allocator, data); - data = 0; - len = cap = 0; - } - - Array copy(M_Allocator allocator) { - Array result = {}; - result.allocator = allocator; - result.reserve(cap); - - memmove(result.data, data, sizeof(T) * len); - result.len = len; - return result; - } - - Array tight_copy(M_Allocator allocator) { - Array result = {}; - result.allocator = allocator; - result.reserve(len); - - memmove(result.data, data, sizeof(T) * len); - result.len = len; - return result; - } - - T *first() { - IO_Assert(len > 0); - return data; - } - T *last() { - IO_Assert(len > 0); - return data + len - 1; - } - T *front() { - IO_Assert(len > 0); - return data; - } - T *back() { - IO_Assert(len > 0); - return data + len - 1; - } - T *begin() { return data; } - T *end() { return data + len; } - - // for (auto it = integers.begin(), end = integers.end(); it != end; ++it) - struct Reverse_Iter { - T *data; - Array *arr; - - Reverse_Iter operator++(int) { - Reverse_Iter ret = *this; - data -= 1; - return ret; - } - Reverse_Iter &operator++() { - data -= 1; - return *this; - } - - T &operator*() { return data[0]; } - T *operator->() { return data; } - - friend bool operator==(const Reverse_Iter &a, const Reverse_Iter &b) { return a.data == b.data; }; - friend bool operator!=(const Reverse_Iter &a, const Reverse_Iter &b) { return a.data != b.data; }; - - Reverse_Iter begin() { return Reverse_Iter{arr->end() - 1, arr}; } - Reverse_Iter end() { return Reverse_Iter{arr->begin() - 1, arr}; } - }; - - Reverse_Iter reverse() { return {end() - 1, this}; } - - void try_growing() { - if (len + 1 > cap) { - int new_size = cap * 2; - if (new_size < 16) new_size = 16; - - reserve(new_size); - } - } - - void try_growing_to_fit_item_count(int item_count) { - if (len + item_count > cap) { - int new_size = (cap + item_count) * 2; - if (new_size < 16) new_size = 16; - reserve(new_size); - } - } -}; diff --git a/src/build_tool/core/cmd.c b/src/build_tool/core/cmd.c deleted file mode 100644 index 6115247..0000000 --- a/src/build_tool/core/cmd.c +++ /dev/null @@ -1,185 +0,0 @@ -CmdParser MakeCmdParser(MA_Arena *arena, int argc, char **argv, const char *custom_help) { - CmdParser result = {argc, argv, arena, custom_help}; - return result; -} - -void AddBool(CmdParser *p, bool *result, const char *name, const char *help) { - CmdDecl *decl = MA_PushStruct(p->arena, CmdDecl); - decl->kind = CmdDeclKind_Bool; - decl->name = S8_MakeFromChar((char *)name); - decl->help = S8_MakeFromChar((char *)help); - decl->bool_result = result; - SLL_QUEUE_ADD(p->fdecl, p->ldecl, decl); -} - -void AddInt(CmdParser *p, int *result, const char *name, const char *help) { - CmdDecl *decl = MA_PushStruct(p->arena, CmdDecl); - decl->kind = CmdDeclKind_Int; - decl->name = S8_MakeFromChar((char *)name); - decl->help = S8_MakeFromChar((char *)help); - decl->int_result = result; - SLL_QUEUE_ADD(p->fdecl, p->ldecl, decl); -} - -void AddList(CmdParser *p, S8_List *result, const char *name, const char *help) { - CmdDecl *decl = MA_PushStruct(p->arena, CmdDecl); - decl->kind = CmdDeclKind_List; - decl->name = S8_MakeFromChar((char *)name); - decl->help = S8_MakeFromChar((char *)help); - decl->list_result = result; - SLL_QUEUE_ADD(p->fdecl, p->ldecl, decl); -} - -void AddEnum(CmdParser *p, int *result, const char *name, const char *help, const char **enum_options, int enum_option_count) { - CmdDecl *decl = MA_PushStruct(p->arena, CmdDecl); - decl->kind = CmdDeclKind_Enum; - decl->name = S8_MakeFromChar((char *)name); - decl->help = S8_MakeFromChar((char *)help); - decl->enum_result = result; - decl->enum_options = enum_options; - decl->enum_option_count = enum_option_count; - SLL_QUEUE_ADD(p->fdecl, p->ldecl, decl); -} - -CmdDecl *FindDecl(CmdParser *p, S8_String name) { - for (CmdDecl *it = p->fdecl; it; it = it->next) { - if (S8_AreEqual(it->name, name, true)) { - return it; - } - } - return NULL; -} - -S8_String StrEnumValues(MA_Arena *arena, CmdDecl *decl) { - S8_List list = {0}; - S8_AddF(arena, &list, "["); - for (int i = 0; i < decl->enum_option_count; i += 1) { - S8_AddF(arena, &list, "%s", decl->enum_options[i]); - if (i != decl->enum_option_count - 1) S8_AddF(arena, &list, "|"); - } - S8_AddF(arena, &list, "]"); - return S8_Merge(arena, list); -} - -void PrintCmdUsage(CmdParser *p) { - IO_Printf("%s\nCommands:\n", p->custom_help); - for (CmdDecl *it = p->fdecl; it; it = it->next) { - IO_Printf(" "); - if (it->kind == CmdDeclKind_List) { - S8_String example = S8_Format(p->arena, "-%.*s a b c", S8_Expand(it->name)); - IO_Printf("%-30.*s %.*s\n", S8_Expand(example), S8_Expand(it->help)); - } else if (it->kind == CmdDeclKind_Bool) { - S8_String example = S8_Format(p->arena, "-%.*s", S8_Expand(it->name)); - IO_Printf("%-30.*s %.*s\n", S8_Expand(example), S8_Expand(it->help)); - } else if (it->kind == CmdDeclKind_Enum) { - S8_String enum_vals = StrEnumValues(p->arena, it); - S8_String example = S8_Format(p->arena, "-%.*s %.*s", S8_Expand(it->name), S8_Expand(enum_vals)); - IO_Printf("%-30.*s %.*s\n", S8_Expand(example), S8_Expand(it->help)); - } else if (it->kind == CmdDeclKind_Int) { - S8_String example = S8_Format(p->arena, "-%.*s 8", S8_Expand(it->name)); - IO_Printf("%-30.*s %.*s\n", S8_Expand(example), S8_Expand(it->help)); - } else IO_Todo(); - } -} - -bool InvalidCmdArg(CmdParser *p, S8_String arg) { - IO_Printf("invalid command line argument: %.*s\n", S8_Expand(arg)); - return false; -} - -bool ParseCmd(MA_Arena *arg_arena, CmdParser *p) { - for (int i = 1; i < p->argc; i += 1) { - S8_String arg = S8_MakeFromChar(p->argv[i]); - - if (S8_AreEqual(arg, S8_Lit("--help"), true) || S8_AreEqual(arg, S8_Lit("-h"), true) || S8_AreEqual(arg, S8_Lit("-help"), true)) { - PrintCmdUsage(p); - return false; - } - - if (arg.str[0] == '-') { - arg = S8_Skip(arg, 1); - if (arg.str[0] == '-') { - arg = S8_Skip(arg, 1); - } - - CmdDecl *decl = FindDecl(p, arg); - if (!decl) return InvalidCmdArg(p, arg); - - if (decl->kind == CmdDeclKind_Bool) { - *decl->bool_result = !*decl->bool_result; - } else if (decl->kind == CmdDeclKind_Int) { - if (i + 1 >= p->argc) { - IO_Printf("expected at least 1 argument after %.*s\n", S8_Expand(arg)); - return false; - } - S8_String num = S8_MakeFromChar(p->argv[++i]); - for (int i = 0; i < num.len; i += 1) { - if (!CHAR_IsDigit(num.str[i])) { - IO_Printf("expected argument to be a number, got instead: %.*s", S8_Expand(num)); - return false; - } - } - int count = atoi(num.str); - decl->int_result[0] = count; - - } else if (decl->kind == CmdDeclKind_Enum) { - if (i + 1 >= p->argc) { - IO_Printf("expected at least 1 argument after %.*s\n", S8_Expand(arg)); - return false; - } - S8_String option_from_cmd = S8_MakeFromChar(p->argv[++i]); - - bool found_option = false; - for (int i = 0; i < decl->enum_option_count; i += 1) { - S8_String option = S8_MakeFromChar((char *)decl->enum_options[i]); - if (S8_AreEqual(option, option_from_cmd, true)) { - *decl->enum_result = i; - found_option = true; - break; - } - } - - if (!found_option) { - IO_Printf("expected one of the enum values: %.*s", S8_Expand(StrEnumValues(p->arena, decl))); - IO_Printf(" got instead: %.*s\n", S8_Expand(option_from_cmd)); - return false; - } - - } else if (decl->kind == CmdDeclKind_List) { - if (i + 1 >= p->argc) { - IO_Printf("expected at least 1 argument after %.*s\n", S8_Expand(arg)); - return false; - } - - i += 1; - for (int counter = 0; i < p->argc; i += 1, counter += 1) { - S8_String arg = S8_MakeFromChar(p->argv[i]); - if (arg.str[0] == '-') { - if (counter == 0) { - IO_Printf("expected at least 1 argument after %.*s\n", S8_Expand(arg)); - return false; - } - i -= 1; - break; - } - - S8_AddNode(arg_arena, decl->list_result, arg); - } - } else IO_Todo(); - - } else { - if (p->require_one_standalone_arg && p->args.node_count == 0) { - S8_AddNode(arg_arena, &p->args, arg); - } else { - return InvalidCmdArg(p, arg); - } - } - } - - if (p->require_one_standalone_arg && p->args.node_count == 0) { - PrintCmdUsage(p); - return false; - } - - return true; -} diff --git a/src/build_tool/core/cmd.h b/src/build_tool/core/cmd.h deleted file mode 100644 index e45c5de..0000000 --- a/src/build_tool/core/cmd.h +++ /dev/null @@ -1,37 +0,0 @@ - -typedef enum { - CmdDeclKind_Bool, - CmdDeclKind_Int, - CmdDeclKind_List, - CmdDeclKind_Enum, -} CmdDeclKind; - -typedef struct CmdDecl CmdDecl; -struct CmdDecl { - CmdDecl *next; - CmdDeclKind kind; - S8_String name; - S8_String help; - - bool *bool_result; - S8_List *list_result; - int *int_result; - - int *enum_result; - const char **enum_options; - int enum_option_count; -}; - -typedef struct CmdParser CmdParser; -struct CmdParser { - int argc; - char **argv; - MA_Arena *arena; - const char *custom_help; - - CmdDecl *fdecl; - CmdDecl *ldecl; - - bool require_one_standalone_arg; - S8_List args; -}; diff --git a/src/build_tool/core/core.c b/src/build_tool/core/core.c deleted file mode 100644 index 237749d..0000000 --- a/src/build_tool/core/core.c +++ /dev/null @@ -1,23 +0,0 @@ -#include "core.h" -#include "../standalone_libraries/stb_sprintf.c" -#define IO_VSNPRINTF stbsp_vsnprintf -#define IO_SNPRINTF stbsp_snprintf -#include "../standalone_libraries/io.c" -#define MA_Assertf(x, ...) IO_Assertf(x, __VA_ARGS__) -#include "../standalone_libraries/arena.c" -#define RE_ASSERT(x) IO_Assert(x) -#include "../standalone_libraries/regex.c" -#include "../standalone_libraries/unicode.c" -#define S8_VSNPRINTF stbsp_vsnprintf -#define S8_ALLOCATE(allocator, size) MA_PushSize(allocator, size) -#define S8_ASSERT(x) IO_Assert(x) -#define S8_MemoryCopy MA_MemoryCopy -#include "../standalone_libraries/string.c" -#define MU_ASSERT IO_Assert -#include "../standalone_libraries/multimedia.h" -#include "../standalone_libraries/hash.c" -#include "../standalone_libraries/load_library.c" -#include "filesystem.c" - -#include "cmd.c" -#include "allocator.c" \ No newline at end of file diff --git a/src/build_tool/core/core.cpp b/src/build_tool/core/core.cpp deleted file mode 100644 index 962f92f..0000000 --- a/src/build_tool/core/core.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "core.c" \ No newline at end of file diff --git a/src/build_tool/core/core.h b/src/build_tool/core/core.h deleted file mode 100644 index b60d7f9..0000000 --- a/src/build_tool/core/core.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef FIRST_CORE_HEADER -#define FIRST_CORE_HEADER - -#include "../standalone_libraries/preproc_env.h" -#include "../standalone_libraries/stb_sprintf.h" -#include "../standalone_libraries/io.h" -#include "../standalone_libraries/arena.h" -#include "../standalone_libraries/unicode.h" -#include "../standalone_libraries/string.h" -#include "../standalone_libraries/hash.h" -#include "../standalone_libraries/linked_list.h" -#include "../standalone_libraries/regex.h" -#include "../standalone_libraries/multimedia.h" -#include "../standalone_libraries/load_library.h" -#include "filesystem.h" -#include "cmd.h" -#include "allocator.h" - -#if LANG_CPP - #include "../standalone_libraries/defer.hpp" - #include "table.hpp" - #include "array.hpp" -#endif - -#endif \ No newline at end of file diff --git a/src/build_tool/core/filesystem.c b/src/build_tool/core/filesystem.c deleted file mode 100644 index d238400..0000000 --- a/src/build_tool/core/filesystem.c +++ /dev/null @@ -1,720 +0,0 @@ -#ifdef _WIN32 - #ifndef NOMINMAX - #define NOMINMAX - #endif - #ifndef WIN32_LEAN_AND_MEAN - #define WIN32_LEAN_AND_MEAN - #endif - #include - #include - #include - -OS_API bool OS_EnableTerminalColors(void) { - // Enable color terminal output - { - // Set output mode to handle virtual terminal sequences - HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE); - if (hOut != INVALID_HANDLE_VALUE) { - DWORD dwMode = 0; - if (GetConsoleMode(hOut, &dwMode)) { - dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING; - if (SetConsoleMode(hOut, dwMode)) { - return true; - } else { - IO_Printf("Failed to enable colored terminal output C\n"); - } - } else { - IO_Printf("Failed to enable colored terminal output B\n"); - } - } else { - IO_Printf("Failed to enable colored terminal output A\n"); - } - } - return false; -} - -OS_API bool OS_IsAbsolute(S8_String path) { - bool result = path.len > 3 && CHAR_IsAlphabetic(path.str[0]) && path.str[1] == ':' && path.str[2] == '/'; - return result; -} - -OS_API S8_String OS_GetExePath(MA_Arena *arena) { - char16_t wbuffer[1024]; - DWORD wsize = GetModuleFileNameW(0, (wchar_t *)wbuffer, MA_Lengthof(wbuffer)); - IO_Assert(wsize != 0); - - S8_String path = S8_FromWidecharEx(arena, wbuffer, wsize); - S8_NormalizePathUnsafe(path); - return path; -} - -OS_API S8_String OS_GetExeDir(MA_Arena *arena) { - MA_Temp scratch = MA_GetScratch(); - S8_String path = OS_GetExePath(scratch.arena); - path = S8_ChopLastSlash(path); - path = S8_Copy(arena, path); - MA_ReleaseScratch(scratch); - return path; -} - -OS_API S8_String OS_GetWorkingDir(MA_Arena *arena) { - char16_t wbuffer[1024]; - DWORD wsize = GetCurrentDirectoryW(MA_Lengthof(wbuffer), (wchar_t *)wbuffer); - IO_Assert(wsize != 0); - IO_Assert(wsize < 1022); - wbuffer[wsize++] = '/'; - wbuffer[wsize] = 0; - - S8_String path = S8_FromWidecharEx(arena, wbuffer, wsize); - S8_NormalizePathUnsafe(path); - return path; -} - -OS_API void OS_SetWorkingDir(S8_String path) { - char16_t wpath[1024]; - UTF_CreateWidecharFromChar(wpath, MA_Lengthof(wpath), path.str, path.len); - SetCurrentDirectoryW((wchar_t *)wpath); -} - -OS_API S8_String OS_GetAbsolutePath(MA_Arena *arena, S8_String relative) { - char16_t wpath[1024]; - UTF_CreateWidecharFromChar(wpath, MA_Lengthof(wpath), relative.str, relative.len); - char16_t wpath_abs[1024]; - DWORD written = GetFullPathNameW((wchar_t *)wpath, MA_Lengthof(wpath_abs), (wchar_t *)wpath_abs, 0); - if (written == 0) - return S8_MakeEmpty(); - S8_String path = S8_FromWidecharEx(arena, wpath_abs, written); - S8_NormalizePathUnsafe(path); - return path; -} - -OS_API bool OS_FileExists(S8_String path) { - char16_t wbuff[1024]; - UTF_CreateWidecharFromChar(wbuff, MA_Lengthof(wbuff), path.str, path.len); - DWORD attribs = GetFileAttributesW((wchar_t *)wbuff); - bool result = attribs == INVALID_FILE_ATTRIBUTES ? false : true; - return result; -} - -OS_API bool OS_IsDir(S8_String path) { - char16_t wbuff[1024]; - UTF_CreateWidecharFromChar(wbuff, MA_Lengthof(wbuff), path.str, path.len); - DWORD dwAttrib = GetFileAttributesW((wchar_t *)wbuff); - return dwAttrib != INVALID_FILE_ATTRIBUTES && (dwAttrib & FILE_ATTRIBUTE_DIRECTORY); -} - -OS_API bool OS_IsFile(S8_String path) { - char16_t wbuff[1024]; - UTF_CreateWidecharFromChar(wbuff, MA_Lengthof(wbuff), path.str, path.len); - DWORD dwAttrib = GetFileAttributesW((wchar_t *)wbuff); - bool is_file = (dwAttrib & FILE_ATTRIBUTE_DIRECTORY) == 0; - return dwAttrib != INVALID_FILE_ATTRIBUTES && is_file; -} - -OS_API double OS_GetTime(void) { - static int64_t counts_per_second; - if (counts_per_second == 0) { - LARGE_INTEGER freq; - QueryPerformanceFrequency(&freq); - counts_per_second = freq.QuadPart; - } - - LARGE_INTEGER time; - QueryPerformanceCounter(&time); - double result = (double)time.QuadPart / (double)counts_per_second; - return result; -} - -/* -User needs to copy particular filename to keep it. - -for (OS_FileIter it = OS_IterateFiles(it); OS_IsValid(iter); OS_Advance(it)) { -} - -*/ - -typedef struct OS_Win32_FileIter { - HANDLE handle; - WIN32_FIND_DATAW data; -} OS_Win32_FileIter; - -OS_API bool OS_IsValid(OS_FileIter it) { - return it.is_valid; -} - -OS_API void OS_Advance(OS_FileIter *it) { - while (FindNextFileW(it->w32->handle, &it->w32->data) != 0) { - WIN32_FIND_DATAW *data = &it->w32->data; - - // Skip '.' and '..' - if (data->cFileName[0] == '.' && data->cFileName[1] == '.' && data->cFileName[2] == 0) continue; - if (data->cFileName[0] == '.' && data->cFileName[1] == 0) continue; - - it->is_directory = data->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY; - it->filename = S8_FromWidecharEx(it->arena, (char16_t *)data->cFileName, S8_WideLength((char16_t *)data->cFileName)); - const char *is_dir = it->is_directory ? "/" : ""; - const char *separator = it->path.str[it->path.len - 1] == '/' ? "" : "/"; - it->relative_path = S8_Format(it->arena, "%.*s%s%.*s%s", S8_Expand(it->path), separator, S8_Expand(it->filename), is_dir); - it->absolute_path = OS_GetAbsolutePath(it->arena, it->relative_path); - it->is_valid = true; - - if (it->is_directory) { - IO_Assert(it->relative_path.str[it->relative_path.len - 1] == '/'); - IO_Assert(it->absolute_path.str[it->absolute_path.len - 1] == '/'); - } - return; - } - - it->is_valid = false; - DWORD error = GetLastError(); - IO_Assert(error == ERROR_NO_MORE_FILES); - FindClose(it->w32->handle); -} - -OS_API OS_FileIter OS_IterateFiles(MA_Arena *scratch_arena, S8_String path) { - OS_FileIter it = {0}; - it.arena = scratch_arena; - it.path = path; - - S8_String modified_path = S8_Format(it.arena, "%.*s\\*", S8_Expand(path)); - char16_t *wbuff = MA_PushArray(it.arena, char16_t, modified_path.len + 1); - int64_t wsize = UTF_CreateWidecharFromChar(wbuff, modified_path.len + 1, modified_path.str, modified_path.len); - IO_Assert(wsize); - - it.w32 = MA_PushStruct(it.arena, OS_Win32_FileIter); - it.w32->handle = FindFirstFileW((wchar_t *)wbuff, &it.w32->data); - if (it.w32->handle == INVALID_HANDLE_VALUE) { - it.is_valid = false; - return it; - } - - IO_Assert(it.w32->data.cFileName[0] == '.' && it.w32->data.cFileName[1] == 0); - OS_Advance(&it); - return it; -} - -OS_API OS_Result OS_MakeDir(S8_String path) { - char16_t wpath[1024]; - UTF_CreateWidecharFromChar(wpath, MA_Lengthof(wpath), path.str, path.len); - BOOL success = CreateDirectoryW((wchar_t *)wpath, NULL); - OS_Result result = OS_SUCCESS; - if (success == 0) { - DWORD error = GetLastError(); - if (error == ERROR_ALREADY_EXISTS) { - result = OS_ALREADY_EXISTS; - } else if (error == ERROR_PATH_NOT_FOUND) { - result = OS_PATH_NOT_FOUND; - } else { - IO_Assert(0); - } - } - return result; -} - -OS_API OS_Result OS_CopyFile(S8_String from, S8_String to, bool overwrite) { - char16_t wfrom[1024]; - UTF_CreateWidecharFromChar(wfrom, MA_Lengthof(wfrom), from.str, from.len); - - char16_t wto[1024]; - UTF_CreateWidecharFromChar(wto, MA_Lengthof(wto), to.str, to.len); - - BOOL fail_if_exists = !overwrite; - BOOL success = CopyFileW((wchar_t *)wfrom, (wchar_t *)wto, fail_if_exists); - - OS_Result result = OS_SUCCESS; - if (success == FALSE) - result = OS_FAILURE; - return result; -} - -OS_API OS_Result OS_DeleteFile(S8_String path) { - char16_t wpath[1024]; - UTF_CreateWidecharFromChar(wpath, MA_Lengthof(wpath), path.str, path.len); - BOOL success = DeleteFileW((wchar_t *)wpath); - OS_Result result = OS_SUCCESS; - if (success == 0) - result = OS_PATH_NOT_FOUND; - return result; -} - -OS_API OS_Result OS_DeleteDir(S8_String path, unsigned flags) { - IO_Todo(); - return OS_FAILURE; - #if 0 - if (flags & OS_RECURSIVE) { - MA_Temp scratch = MA_GetScratch(); - S8_List list = OS_ListDir(scratch.arena, path, OS_RECURSIVE); - S8_Node *dirs_to_remove = 0; - for (S8_Node *it = list.first; it; it = it->next) { - if (!S8_EndsWith(it->string, S8_Lit("/"), S8_IgnoreCase)) { - OS_DeleteFile(it->string); - } - else { - S8_Node *node = S8_CreateNode(scratch.arena, it->string); - SLL_STACK_ADD(dirs_to_remove, node); - } - } - for (S8_Node *it = dirs_to_remove; it; it = it->next) { - OS_DeleteDir(it->string, OS_NO_FLAGS); - } - OS_Result result = OS_DeleteDir(path, OS_NO_FLAGS); - MA_ReleaseScratch(scratch); - return result; - } - else { - wchar_t wpath[1024]; - UTF_CreateWidecharFromChar(wpath, MA_Lengthof(wpath), path.str, path.len); - BOOL success = RemoveDirectoryW(wpath); - OS_Result result = OS_SUCCESS; - if (success == 0) - result = OS_PATH_NOT_FOUND; - return result; - } - #endif -} - -static OS_Result OS__WriteFile(S8_String path, S8_String data, bool append) { - char16_t wpath[1024]; - UTF_CreateWidecharFromChar(wpath, MA_Lengthof(wpath), path.str, path.len); - OS_Result result = OS_FAILURE; - - DWORD access = GENERIC_WRITE; - DWORD creation_disposition = CREATE_ALWAYS; - if (append) { - access = FILE_APPEND_DATA; - creation_disposition = OPEN_ALWAYS; - } - - HANDLE handle = CreateFileW((wchar_t *)wpath, access, 0, NULL, creation_disposition, FILE_ATTRIBUTE_NORMAL, NULL); - if (handle != INVALID_HANDLE_VALUE) { - DWORD bytes_written = 0; - IO_Assert(data.len == (DWORD)data.len); // @Todo: can only read 32 byte size files? - BOOL error = WriteFile(handle, data.str, (DWORD)data.len, &bytes_written, NULL); - if (error == TRUE) { - if (bytes_written == data.len) { - result = OS_SUCCESS; - } - } - CloseHandle(handle); - } else result = OS_PATH_NOT_FOUND; - - return result; -} - -OS_API OS_Result OS_AppendFile(S8_String path, S8_String string) { - return OS__WriteFile(path, string, true); -} - -OS_API OS_Result OS_WriteFile(S8_String path, S8_String string) { - return OS__WriteFile(path, string, false); -} - -OS_API S8_String OS_ReadFile(MA_Arena *arena, S8_String path) { - bool success = false; - S8_String result = S8_MakeEmpty(); - MA_Temp checkpoint = MA_BeginTemp(arena); - - char16_t wpath[1024]; - UTF_CreateWidecharFromChar(wpath, MA_Lengthof(wpath), path.str, path.len); - HANDLE handle = CreateFileW((wchar_t *)wpath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - if (handle != INVALID_HANDLE_VALUE) { - LARGE_INTEGER file_size; - if (GetFileSizeEx(handle, &file_size)) { - if (file_size.QuadPart != 0) { - result.len = (int64_t)file_size.QuadPart; - result.str = (char *)MA_PushSizeNonZeroed(arena, result.len + 1); - DWORD read; - if (ReadFile(handle, result.str, (DWORD)result.len, &read, NULL)) { // @todo: can only read 32 byte size files? - if (read == result.len) { - success = true; - result.str[result.len] = 0; - } - } - } - } - CloseHandle(handle); - } - - if (!success) { - result = S8_MakeEmpty(); - MA_EndTemp(checkpoint); - } - - return result; -} - -OS_API int64_t OS_GetFileModTime(S8_String file) { - FILETIME time = {0}; - WIN32_FIND_DATAW data; - - char16_t wpath[1024]; - UTF_CreateWidecharFromChar(wpath, 1024, file.str, file.len); - HANDLE handle = FindFirstFileW((wchar_t *)wpath, &data); - if (handle != INVALID_HANDLE_VALUE) { - FindClose(handle); - time = data.ftLastWriteTime; - } else { - return -1; - } - int64_t result = (int64_t)time.dwHighDateTime << 32 | time.dwLowDateTime; - return result; -} - -OS_API OS_Date OS_GetDate(void) { - SYSTEMTIME local; - GetLocalTime(&local); - - OS_Date result = {0}; - result.year = local.wYear; - result.month = local.wMonth; - result.day = local.wDay; - result.hour = local.wHour; - result.second = local.wSecond; - // result.milliseconds = local.wMilliseconds; - return result; -} - -#elif __linux__ || __APPLE__ || __unix__ - #include - #include - #include - #include - #include - - #if OS_MAC - #include - -OS_API S8_String OS_GetExePath(MA_Arena *arena) { - char buf[PATH_MAX]; - uint32_t bufsize = PATH_MAX; - if (_NSGetExecutablePath(buf, &bufsize)) { - return S8_MakeEmpty(); - } - - S8_String result = S8_Copy(arena, S8_MakeFromChar(buf)); - return result; -} - - #else - -OS_API S8_String OS_GetExePath(MA_Arena *arena) { - char buffer[PATH_MAX] = {}; - if (readlink("/proc/self/exe", buffer, PATH_MAX) == -1) { - return S8_MakeEmpty(); - } - S8_String result = S8_Copy(arena, S8_MakeFromChar(buffer)); - return result; -} - - #endif - -OS_API bool OS_EnableTerminalColors(void) { return true; } - -OS_API bool OS_IsAbsolute(S8_String path) { - bool result = path.len >= 1 && path.str[0] == '/'; - return result; -} - -OS_API S8_String OS_GetExeDir(MA_Arena *arena) { - MA_Temp scratch = MA_GetScratch(); - S8_String path = OS_GetExePath(scratch.arena); - S8_String dir = S8_ChopLastSlash(path); - S8_String copy = S8_Copy(arena, dir); - MA_ReleaseScratch(scratch); - return copy; -} - -OS_API S8_String OS_GetWorkingDir(MA_Arena *arena) { - char *buffer = (char *)MA_PushSizeNonZeroed(arena, PATH_MAX); - char *cwd = getcwd(buffer, PATH_MAX); - S8_String result = S8_MakeFromChar(cwd); - return result; -} - -OS_API void OS_SetWorkingDir(S8_String path) { - MA_Temp scratch = MA_GetScratch(); - S8_String copy = S8_Copy(scratch.arena, path); - chdir(copy.str); - MA_ReleaseScratch(scratch); -} - -OS_API S8_String OS_GetAbsolutePath(MA_Arena *arena, S8_String relative) { - MA_Temp scratch = MA_GetScratch1(arena); - S8_String copy = S8_Copy(scratch.arena, relative); - - char *buffer = (char *)MA_PushSizeNonZeroed(arena, PATH_MAX); - realpath((char *)copy.str, buffer); - S8_String result = S8_MakeFromChar(buffer); - - MA_ReleaseScratch(scratch); - return result; -} - -OS_API bool OS_FileExists(S8_String path) { - MA_Temp scratch = MA_GetScratch(); - S8_String copy = S8_Copy(scratch.arena, path); - - bool result = false; - if (access((char *)copy.str, F_OK) == 0) { - result = true; - } - - MA_ReleaseScratch(scratch); - return result; -} - -OS_API bool OS_IsDir(S8_String path) { - MA_Temp scratch = MA_GetScratch(); - S8_String copy = S8_Copy(scratch.arena, path); - - struct stat s; - if (stat(copy.str, &s) != 0) - return false; - - bool result = S_ISDIR(s.st_mode); - MA_ReleaseScratch(scratch); - return result; -} - -OS_API bool OS_IsFile(S8_String path) { - MA_Temp scratch = MA_GetScratch(); - S8_String copy = S8_Copy(scratch.arena, path); - - struct stat s; - if (stat(copy.str, &s) != 0) - return false; - bool result = S_ISREG(s.st_mode); - MA_ReleaseScratch(scratch); - return result; -} - -OS_API double OS_GetTime(void) { - struct timespec ts; - clock_gettime(CLOCK_MONOTONIC, &ts); - uint64_t timeu64 = (((uint64_t)ts.tv_sec) * 1000000ull) + ((uint64_t)ts.tv_nsec) / 1000ull; - double timef = (double)timeu64; - double result = timef / 1000000.0; // Microseconds to seconds - return result; -} - -OS_API bool OS_IsValid(OS_FileIter it) { - return it.is_valid; -} - -OS_API void OS_Advance(OS_FileIter *it) { - struct dirent *file = 0; - while ((file = readdir((DIR *)it->dir)) != NULL) { - if (file->d_name[0] == '.' && file->d_name[1] == '.' && file->d_name[2] == 0) continue; - if (file->d_name[0] == '.' && file->d_name[1] == 0) continue; - - it->is_directory = file->d_type == DT_DIR; - it->filename = S8_CopyChar(it->arena, file->d_name); - - const char *dir_char_ending = it->is_directory ? "/" : ""; - const char *separator = it->path.str[it->path.len - 1] == '/' ? "" : "/"; - it->relative_path = S8_Format(it->arena, "%.*s%s%s%s", S8_Expand(it->path), separator, file->d_name, dir_char_ending); - it->absolute_path = OS_GetAbsolutePath(it->arena, it->relative_path); - if (it->is_directory) it->absolute_path = S8_Format(it->arena, "%.*s/", S8_Expand(it->absolute_path)); - it->is_valid = true; - return; - } - it->is_valid = false; - closedir((DIR *)it->dir); -} - -OS_API OS_FileIter OS_IterateFiles(MA_Arena *arena, S8_String path) { - OS_FileIter it = {0}; - it.arena = arena; - it.path = path = S8_Copy(arena, path); - it.dir = (void *)opendir((char *)path.str); - if (!it.dir) return it; - - OS_Advance(&it); - return it; -} - -OS_API OS_Result OS_MakeDir(S8_String path) { - MA_Temp scratch = MA_GetScratch(); - path = S8_Copy(scratch.arena, path); - int error = mkdir(path.str, 0755); - MA_ReleaseScratch(scratch); - return error == 0 ? OS_SUCCESS : OS_FAILURE; -} - -OS_API OS_Result OS_CopyFile(S8_String from, S8_String to, bool overwrite) { - const char *ow = overwrite ? "-n" : ""; - int result = OS_SystemF("cp %s %.*s %.*s", ow, S8_Expand(from), S8_Expand(to)); - return result == 0 ? OS_SUCCESS : OS_FAILURE; -} - -OS_API OS_Result OS_DeleteFile(S8_String path) { - int result = OS_SystemF("rm %.*s", S8_Expand(path)); - return result == 0 ? OS_SUCCESS : OS_FAILURE; -} - -OS_API OS_Result OS_DeleteDir(S8_String path, unsigned flags) { - IO_Assert(flags & OS_RECURSIVE); - int result = OS_SystemF("rm -r %.*s", S8_Expand(path)); - return result == 0 ? OS_SUCCESS : OS_FAILURE; -} - -OS_API int64_t OS_GetFileModTime(S8_String file) { - MA_Temp scratch = MA_GetScratch(); - file = S8_Copy(scratch.arena, file); - - struct stat attrib = {}; - stat(file.str, &attrib); - struct timespec ts = attrib.IF_LINUX_ELSE(st_mtim, st_mtimespec); - int64_t result = (((int64_t)ts.tv_sec) * 1000000ll) + ((int64_t)ts.tv_nsec) / 1000ll; - - MA_ReleaseScratch(scratch); - return result; -} - -OS_API OS_Date OS_GetDate(void) { - time_t t = time(NULL); - struct tm date = *localtime(&t); - - OS_Date s = {0}; - s.second = date.tm_sec; - s.year = date.tm_year; - s.month = date.tm_mon; - s.day = date.tm_mday; - s.hour = date.tm_hour; - s.minute = date.tm_min; - - return s; -} - -OS_API OS_Result OS_AppendFile(S8_String path, S8_String string) { - MA_Temp scratch = MA_GetScratch(); - path = S8_Copy(scratch.arena, path); - - OS_Result result = OS_FAILURE; - FILE *f = fopen((const char *)path.str, "a"); - if (f) { - result = OS_SUCCESS; - - size_t written = fwrite(string.str, 1, string.len, f); - if (written < string.len) { - result = OS_FAILURE; - } - - int error = fclose(f); - if (error != 0) { - result = OS_FAILURE; - } - } - - MA_ReleaseScratch(scratch); - return result; -} - -OS_API S8_String OS_ReadFile(MA_Arena *arena, S8_String path) { - S8_String result = {}; - - // ftell returns insane size if file is - // a directory **on some machines** KEKW - if (OS_IsDir(path)) { - return result; - } - - MA_Temp scratch = MA_GetScratch1(arena); - path = S8_Copy(scratch.arena, path); - - FILE *f = fopen(path.str, "rb"); - if (f) { - fseek(f, 0, SEEK_END); - result.len = ftell(f); - fseek(f, 0, SEEK_SET); - - result.str = (char *)MA_PushSizeNonZeroed(arena, result.len + 1); - fread(result.str, result.len, 1, f); - result.str[result.len] = 0; - - fclose(f); - } - - MA_ReleaseScratch(scratch); - return result; -} - -OS_API OS_Result OS_WriteFile(S8_String path, S8_String string) { - MA_Temp scratch = MA_GetScratch(); - path = S8_Copy(scratch.arena, path); - - OS_Result result = OS_FAILURE; - FILE *f = fopen((const char *)path.str, "w"); - if (f) { - result = OS_SUCCESS; - - size_t written = fwrite(string.str, 1, string.len, f); - if (written < string.len) { - result = OS_FAILURE; - } - - int error = fclose(f); - if (error != 0) { - result = OS_FAILURE; - } - } - - MA_ReleaseScratch(scratch); - return result; -} -#endif - -#if _WIN32 || __linux__ || __APPLE__ || __unix__ -OS_API int OS_SystemF(const char *string, ...) { - MA_Temp scratch = MA_GetScratch(); - S8_FORMAT(scratch.arena, string, result); - IO_Printf("Executing: %.*s\n", S8_Expand(result)); - fflush(stdout); - int error_code = system(result.str); - MA_ReleaseScratch(scratch); - return error_code; -} - -OS_API bool OS_ExpandIncludesList(MA_Arena *arena, S8_List *out, S8_String filepath) { - S8_String c = OS_ReadFile(arena, filepath); - if (c.str == 0) return false; - S8_String path = S8_ChopLastSlash(filepath); - S8_String include = S8_Lit("#include \""); - for (;;) { - int64_t idx = -1; - if (S8_Seek(c, include, 0, &idx)) { - S8_String str_to_add = S8_GetPrefix(c, idx); - S8_AddNode(arena, out, str_to_add); - S8_String save = c; - c = S8_Skip(c, idx + include.len); - - S8_String filename = c; - filename.len = 0; - while (filename.str[filename.len] != '"' && filename.len < c.len) { - filename.len += 1; - } - - c = S8_Skip(c, filename.len + 1); - S8_String inc_path = S8_Format(arena, "%.*s/%.*s", S8_Expand(path), S8_Expand(filename)); - if (!OS_ExpandIncludesList(arena, out, inc_path)) { - S8_String s = S8_GetPrefix(save, save.len - c.len); - S8_AddNode(arena, out, s); - } - } else { - S8_AddNode(arena, out, c); - break; - } - } - return true; -} - -OS_API S8_String OS_ExpandIncludes(MA_Arena *arena, S8_String filepath) { - S8_List out = S8_MakeEmptyList(); - S8_String result = S8_MakeEmpty(); - MA_ScratchScope(s) { - OS_ExpandIncludesList(s.arena, &out, filepath); - result = S8_Merge(arena, out); - } - return result; -} -#endif \ No newline at end of file diff --git a/src/build_tool/core/filesystem.h b/src/build_tool/core/filesystem.h deleted file mode 100644 index b1c158a..0000000 --- a/src/build_tool/core/filesystem.h +++ /dev/null @@ -1,73 +0,0 @@ -// Quick and dirty filesystem operations - -#ifndef OS_API - #define OS_API -#endif - -typedef enum OS_Result { - OS_SUCCESS, - OS_ALREADY_EXISTS, - OS_PATH_NOT_FOUND, - OS_FAILURE, -} OS_Result; - -enum { - OS_NO_FLAGS = 0, - OS_RECURSIVE = 1, - OS_RELATIVE_PATHS = 2, -}; - -typedef struct OS_Date OS_Date; -struct OS_Date { - uint32_t year; - uint32_t month; - uint32_t day; - uint32_t hour; - uint32_t minute; - uint32_t second; -}; - -typedef struct OS_FileIter OS_FileIter; -struct OS_FileIter { - bool is_valid; - bool is_directory; - S8_String absolute_path; - S8_String relative_path; - S8_String filename; - - S8_String path; - MA_Arena *arena; - union { - struct OS_Win32_FileIter *w32; - void *dir; - }; -}; - -OS_API bool OS_IsAbsolute(S8_String path); -OS_API S8_String OS_GetExePath(MA_Arena *arena); -OS_API S8_String OS_GetExeDir(MA_Arena *arena); -OS_API S8_String OS_GetWorkingDir(MA_Arena *arena); -OS_API void OS_SetWorkingDir(S8_String path); -OS_API S8_String OS_GetAbsolutePath(MA_Arena *arena, S8_String relative); -OS_API bool OS_FileExists(S8_String path); -OS_API bool OS_IsDir(S8_String path); -OS_API bool OS_IsFile(S8_String path); -OS_API double OS_GetTime(void); -OS_API OS_Result OS_MakeDir(S8_String path); -OS_API OS_Result OS_CopyFile(S8_String from, S8_String to, bool overwrite); -OS_API OS_Result OS_DeleteFile(S8_String path); -OS_API OS_Result OS_DeleteDir(S8_String path, unsigned flags); -OS_API OS_Result OS_AppendFile(S8_String path, S8_String string); -OS_API OS_Result OS_WriteFile(S8_String path, S8_String string); -OS_API S8_String OS_ReadFile(MA_Arena *arena, S8_String path); -OS_API int OS_SystemF(const char *string, ...); -OS_API int64_t OS_GetFileModTime(S8_String file); -OS_API OS_Date OS_GetDate(void); -OS_API S8_String UTF_CreateStringFromWidechar(MA_Arena *arena, wchar_t *wstr, int64_t wsize); -OS_API bool OS_ExpandIncludesList(MA_Arena *arena, S8_List *out, S8_String filepath); -OS_API S8_String OS_ExpandIncludes(MA_Arena *arena, S8_String filepath); -OS_API bool OS_EnableTerminalColors(void); - -OS_API bool OS_IsValid(OS_FileIter it); -OS_API void OS_Advance(OS_FileIter *it); -OS_API OS_FileIter OS_IterateFiles(MA_Arena *scratch_arena, S8_String path); \ No newline at end of file diff --git a/src/build_tool/core/table.hpp b/src/build_tool/core/table.hpp deleted file mode 100644 index 374a803..0000000 --- a/src/build_tool/core/table.hpp +++ /dev/null @@ -1,204 +0,0 @@ -/* - Hash table implementation: - Pointers to values - Open adressing - Linear Probing - Power of 2 - Robin Hood hashing - Resizes on high probe count (min max load factor) - - Hash 0 is reserved for empty hash table entry -*/ - -template -struct Table { - struct Entry { - uint64_t hash; - uint64_t key; - size_t distance; - Value value; - }; - - M_Allocator allocator; - size_t len, cap; - Entry *values; - - static const size_t max_load_factor = 80; - static const size_t min_load_factor = 50; - static const size_t significant_distance = 8; - - // load factor calculation was rearranged - // to get rid of division: - //> 100 * len / cap = load_factor - //> len * 100 = load_factor * cap - inline bool reached_load_factor(size_t lfactor) { - return (len + 1) * 100 >= lfactor * cap; - } - - inline bool is_empty(Entry *entry) { return entry->hash == 0; } - inline bool is_occupied(Entry *entry) { return entry->hash != 0; } - - void reserve(size_t size) { - IO_Assert(size > cap && "New size is smaller then original size"); - IO_Assert(MA_IS_POW2(size)); - if (!allocator.p) allocator = M_GetSystemAllocator(); - - Entry *old_values = values; - size_t old_cap = cap; - - values = (Entry *)M_Alloc(allocator, sizeof(Entry) * size); - for (int i = 0; i < size; i += 1) values[i] = {}; - cap = size; - - IO_Assert(!(old_values == 0 && len != 0)); - if (len == 0) { - if (old_values) M_Dealloc(allocator, old_values); - return; - } - - len = 0; - for (size_t i = 0; i < old_cap; i += 1) { - Entry *it = old_values + i; - if (is_occupied(it)) { - insert(it->key, it->value); - } - } - M_Dealloc(allocator, old_values); - } - - Entry *get_table_entry(uint64_t key) { - if (len == 0) return 0; - uint64_t hash = HashBytes(&key, sizeof(key)); - if (hash == 0) hash += 1; - uint64_t index = WRAP_AROUND_POWER_OF_2(hash, cap); - uint64_t i = index; - uint64_t distance = 0; - for (;;) { - Entry *it = values + i; - if (distance > it->distance) { - return 0; - } - - if (it->hash == hash && it->key == key) { - return it; - } - - distance += 1; - i = WRAP_AROUND_POWER_OF_2(i + 1, cap); - if (i == index) return 0; - } - IO_Assert(!"Invalid codepath"); - } - - void insert(uint64_t key, const Value &value) { - if (reached_load_factor(max_load_factor)) { - if (cap == 0) cap = 16; // 32 cause cap*2 - reserve(cap * 2); - } - - uint64_t hash = HashBytes(&key, sizeof(key)); - if (hash == 0) hash += 1; - uint64_t index = WRAP_AROUND_POWER_OF_2(hash, cap); - uint64_t i = index; - Entry to_insert = {hash, key, 0, value}; - for (;;) { - Entry *it = values + i; - if (is_empty(it)) { - *it = to_insert; - len += 1; - // If we have more then 8 consecutive items we try to resize - if (to_insert.distance > 8 && reached_load_factor(min_load_factor)) { - reserve(cap * 2); - } - return; - } - if (it->hash == hash && it->key == key) { - *it = to_insert; - // If we have more then 8 consecutive items we try to resize - if (to_insert.distance > 8 && reached_load_factor(min_load_factor)) { - reserve(cap * 2); - } - return; - } - - // Robin hood hashing - if (to_insert.distance > it->distance) { - Entry temp = to_insert; - to_insert = *it; - *it = temp; - } - - to_insert.distance += 1; - i = WRAP_AROUND_POWER_OF_2(i + 1, cap); - IO_Assert(i != index && "Did a full 360 through a hash table, no good :( that shouldnt be possible"); - } - IO_Assert(!"Invalid codepath"); - } - - void remove(uint64_t key) { - Entry *entry = get_table_entry(key); - entry->hash = 0; - entry->distance = 0; - len -= 1; - } - - Value *get(uint64_t key) { - Entry *v = get_table_entry(key); - if (!v) return 0; - return &v->value; - } - - Value get(uint64_t key, Value default_value) { - Entry *v = get_table_entry(key); - if (!v) return default_value; - return v->value; - } - - Value *gets(char *str) { - int len = S8_Length(str); - uint64_t hash = HashBytes(str, len); - return get(hash); - } - - Value gets(char *str, Value default_value) { - int len = S8_Length(str); - uint64_t hash = HashBytes(str, len); - return get(hash, default_value); - } - - Value *get(S8_String s) { - uint64_t hash = HashBytes(s.str, (unsigned)s.len); - return get(hash); - } - - Value get(S8_String s, Value default_value) { - uint64_t hash = HashBytes(s.str, (unsigned)s.len); - return get(hash, default_value); - } - - void put(S8_String s, const Value &value) { - uint64_t hash = HashBytes(s.str, (unsigned)s.len); - insert(hash, value); - } - - void puts(char *str, const Value &value) { - int len = S8_Length(str); - uint64_t hash = HashBytes(str, len); - insert(hash, value); - } - - void reset() { - len = 0; - for (size_t i = 0; i < cap; i += 1) { - Entry *it = values + i; - it->hash = 0; - } - } - - void dealloc() { - M_Dealloc(allocator, values); - len = 0; - cap = 0; - values = 0; - } -}; diff --git a/src/build_tool/easy_strings.cpp b/src/build_tool/easy_strings.cpp deleted file mode 100644 index 12a698e..0000000 --- a/src/build_tool/easy_strings.cpp +++ /dev/null @@ -1,116 +0,0 @@ -S8_String Fmt(const char *str, ...) S8__PrintfFormat(1, 2); - -Array operator+(Array a, Array b) { - Array c = a.copy(MA_GetAllocator(Perm)); - c.add_array(b); - return c; -} - -Array operator+(Array a, S8_String b) { - Array c = a.copy(MA_GetAllocator(Perm)); - c.add(b); - return c; -} - -Array operator+(S8_String a, Array b) { - Array c = b.copy(MA_GetAllocator(Perm)); - c.insert(a, 0); - return c; -} - -Array operator+(S8_String a, S8_String b) { - Array c = {MA_GetAllocator(Perm)}; - c.add(a); - c.add(b); - return c; -} - -Array &operator+=(Array &a, Array b) { - a.add_array(b); - return a; -} - -Array &operator+=(Array &a, S8_String s) { - a.add(s); - return a; -} - -//@todo: split on any whitespace instead! -Array Split(S8_String s, S8_String sep = " ") { - S8_List list = S8_Split(Perm, s, sep, 0); - Array result = {MA_GetAllocator(Perm)}; - S8_For(it, list) result.add(it->string); - return result; -} - -S8_String Merge(MA_Arena *arena, Array list, S8_String separator = " "_s) { - int64_t char_count = 0; - For(list) char_count += it.len; - if (char_count == 0) return {}; - int64_t node_count = list.len; - - int64_t base_size = (char_count + 1); - int64_t sep_size = (node_count - 1) * separator.len; - int64_t size = base_size + sep_size; - char *buff = (char *)MA_PushSize(arena, sizeof(char) * (size + 1)); - S8_String string = S8_Make(buff, 0); - For(list) { - IO_Assert(string.len + it.len <= size); - MA_MemoryCopy(string.str + string.len, it.str, it.len); - string.len += it.len; - if (!list.is_last(it)) { - MA_MemoryCopy(string.str + string.len, separator.str, separator.len); - string.len += separator.len; - } - } - IO_Assert(string.len == size - 1); - string.str[size] = 0; - return string; -} - -S8_String Merge(Array list, S8_String separator = " ") { - return Merge(Perm, list, separator); -} - -S8_String Fmt(const char *str, ...) { - S8_FORMAT(Perm, str, str_fmt); - return str_fmt; -} - -Array ListDir(char *dir) { - Array result = {MA_GetAllocator(Perm)}; - for (OS_FileIter it = OS_IterateFiles(Perm, S8_MakeFromChar(dir)); OS_IsValid(it); OS_Advance(&it)) { - result.add(S8_Copy(Perm, it.absolute_path)); - } - return result; -} - -Array CMD_Make(char **argv, int argc) { - Array result = {MA_GetAllocator(Perm)}; - for (int i = 1; i < argc; i += 1) { - S8_String it = S8_MakeFromChar(argv[i]); - result.add(it); - } - return result; -} - -S8_String CMD_Get(Array &cmd, S8_String name, S8_String default_value = "") { - For(cmd) { - int64_t idx = 0; - if (S8_Seek(it, "="_s, 0, &idx)) { - S8_String key = S8_GetPrefix(it, idx); - S8_String value = S8_Skip(it, idx + 1); - if (key == name) { - return value; - } - } - } - return default_value; -} - -bool CMD_Match(Array &cmd, S8_String name) { - For(cmd) { - if (it == name) return true; - } - return false; -} \ No newline at end of file diff --git a/src/build_tool/library.cpp b/src/build_tool/library.cpp deleted file mode 100644 index 2fedbd3..0000000 --- a/src/build_tool/library.cpp +++ /dev/null @@ -1,55 +0,0 @@ -#ifndef _CRT_SECURE_NO_WARNINGS - #define _CRT_SECURE_NO_WARNINGS -#endif - -#include "core/core.c" - -#define CL_Allocator MA_Arena * -#define CL_Allocate(a, s) MA_PushSizeNonZeroed(a, s) -#define CL_ASSERT IO_Assert -#define CL_VSNPRINTF stbsp_vsnprintf -#define CL_SNPRINTF stbsp_snprintf -#define AND_CL_STRING_TERMINATE_ON_NEW_LINE -#include "standalone_libraries/clexer.c" - -thread_local MA_Arena PernamentArena; -thread_local MA_Arena *Perm = &PernamentArena; - -#include "cache.cpp" -#include "easy_strings.cpp" -#include "process.cpp" - -S8_String CL_Flags = "/MP /Zi /FC /WX /W3 /wd4200 /diagnostics:column /nologo -D_CRT_SECURE_NO_WARNINGS /GF /Gm- /Oi"; -S8_String CL_Link = "/link /incremental:no"; -S8_String CL_StdOff = "/GR- /EHa-"; -S8_String CL_StdOn = "/EHsc"; -S8_String CL_Debug = "-Od -D_DEBUG -fsanitize=address -RTC1"; -S8_String CL_Release = "-O2 -MT -DNDEBUG -GL"; -S8_String CL_ReleaseLink = "-opt:ref -opt:icf"; -/* -/FC = Print full paths in diagnostics -/Gm- = Old feature, 'minimal compilation', in case it's not off by default -/GF = Pools strings as read-only. If you try to modify strings under /GF, an application error occurs. -/Oi = Replaces some function calls with intrinsic -/MP = Multithreaded compilation -/GR- = Disable runtime type information -/EHa- = Disable exceptions -/EHsc = Enable exceptions -/MT = Link static libc. The 'd' means debug version -/MD = Link dynamic libc. The 'd' means debug version -/GL = Whole program optimization -/RTC1 = runtime error checks -/opt:ref = eliminates functions and data that are never referenced -/opt:icf = eliminates redundant 'COMDAT's -*/ - -S8_String Clang_Flags = "-fdiagnostics-absolute-paths -Wno-writable-strings"; -S8_String Clang_NoStd = "-fno-exceptions"; -S8_String Clang_Debug = "-fsanitize=address -g"; -/* --std=c++11 - */ - -S8_String GCC_Flags = "-Wno-write-strings"; -S8_String GCC_NoStd = "-fno-exceptions"; -S8_String GCC_Debug = "-fsanitize=address -g"; diff --git a/src/build_tool/process.cpp b/src/build_tool/process.cpp deleted file mode 100644 index 6a1edb1..0000000 --- a/src/build_tool/process.cpp +++ /dev/null @@ -1,153 +0,0 @@ -struct Process { - bool is_valid; - char platform[32]; -}; - -#if OS_WINDOWS -Process RunEx(S8_String in_cmd) { - MA_Scratch scratch; - wchar_t *application_name = NULL; - wchar_t *cmd = (wchar_t *)S8_ToWidechar(scratch, in_cmd); - BOOL inherit_handles = FALSE; - DWORD creation_flags = 0; - void *enviroment = NULL; - wchar_t *working_dir = NULL; - STARTUPINFOW startup_info = {}; - startup_info.cb = sizeof(STARTUPINFOW); - Process result = {}; - IO_Assert(sizeof(result.platform) >= sizeof(PROCESS_INFORMATION)); - PROCESS_INFORMATION *process_info = (PROCESS_INFORMATION *)result.platform; - BOOL success = CreateProcessW(application_name, cmd, NULL, NULL, inherit_handles, creation_flags, enviroment, working_dir, &startup_info, process_info); - result.is_valid = true; - if (!success) { - result.is_valid = false; - - LPVOID lpMsgBuf; - DWORD dw = GetLastError(); - FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&lpMsgBuf, 0, NULL); - LocalFree(lpMsgBuf); - - IO_FatalErrorf("Failed to create process \ncmd: %.*s\nwindows_message: %s", S8_Expand(in_cmd), lpMsgBuf); - } - return result; -} - -int Wait(Process *process) { - IO_Assert(process->is_valid); - PROCESS_INFORMATION *pi = (PROCESS_INFORMATION *)process->platform; - WaitForSingleObject(pi->hProcess, INFINITE); - - DWORD exit_code; - BOOL err = GetExitCodeProcess(pi->hProcess, &exit_code); - IO_Assert(err != 0); - - CloseHandle(pi->hProcess); - CloseHandle(pi->hThread); - process[0] = {}; - return (int)exit_code; -} -#else - #include - #include - -struct TH_UnixProcess { - pid_t pid; -}; - -extern char **environ; - -Process RunEx(S8_String cmd) { - MA_Scratch scratch; - Process result = {}; - IO_Assert(sizeof(result.platform) >= sizeof(TH_UnixProcess)); - TH_UnixProcess *u = (TH_UnixProcess *)result.platform; - - S8_String exec_file = cmd; - S8_String argv = ""; - int64_t pos; - if (S8_Seek(cmd, S8_Lit(" "), 0, &pos)) { - exec_file = S8_GetPrefix(cmd, pos); - argv = S8_Skip(cmd, pos + 1); - } - - exec_file = S8_Copy(scratch, exec_file); - - // Split string on whitespace and conform with argv format - Array args = {MA_GetAllocator(scratch)}; - { - args.add(exec_file.str); - for (int64_t i = 0; i < argv.len;) { - while (i < argv.len && CHAR_IsWhitespace(argv.str[i])) { - i += 1; - } - - S8_String word = {argv.str + i, 0}; - while (i < argv.len && !CHAR_IsWhitespace(argv.str[i])) { - word.len += 1; - i += 1; - } - word = S8_Copy(scratch, word); - args.add(word.str); - } - args.add(NULL); - } - - int err = posix_spawnp(&u->pid, exec_file.str, NULL, NULL, args.data, environ); - if (err == 0) { - result.is_valid = true; - } else { - perror("posix_spawnp error"); - IO_FatalErrorf("Failed to create process, cmd: %.*s", S8_Expand(cmd)); - } - - return result; -} - -int Wait(Process *process) { - if (!process->is_valid) return 1; - TH_UnixProcess *u = (TH_UnixProcess *)process->platform; - - int status = 0; - int pid = waitpid(u->pid, &status, 0); - IO_Assert(pid != -1); - - int result = 0; - if (WIFEXITED(status)) { - result = WEXITSTATUS(status); - } else { - result = 1; - } - - process[0] = {}; - return result; -} -#endif - -Process RunEx(Array s) { - S8_String cmd = Merge(s); - Process proc = RunEx(cmd); - return proc; -} - -Process RunEx(Array s, S8_String process_start_dir) { - OS_MakeDir(process_start_dir); - S8_String working_dir = OS_GetWorkingDir(Perm); - OS_SetWorkingDir(process_start_dir); - S8_String cmd = Merge(s); - Process proc = RunEx(cmd); - OS_SetWorkingDir(working_dir); - return proc; -} - -int Run(S8_String cmd) { - Process process = RunEx(cmd); - int result = Wait(&process); - return result; -} - -int Run(Array cmd) { - S8_String cmds = Merge(cmd); - int result = Run(cmds); - return result; -} diff --git a/src/build_tool/standalone_libraries/arena.c b/src/build_tool/standalone_libraries/arena.c deleted file mode 100644 index 2a1db92..0000000 --- a/src/build_tool/standalone_libraries/arena.c +++ /dev/null @@ -1,366 +0,0 @@ -#include "arena.h" -#ifndef MA_Assertf - #include - #define MA_Assertf(x, ...) assert(x) -#endif - -#ifndef MA_StaticFunc - #if defined(__GNUC__) || defined(__clang__) - #define MA_StaticFunc __attribute__((unused)) static - #else - #define MA_StaticFunc static - #endif -#endif - -#if defined(MA_USE_ADDRESS_SANITIZER) - #include -#endif - -#if !defined(ASAN_POISON_MEMORY_REGION) - #define MA_ASAN_POISON_MEMORY_REGION(addr, size) ((void)(addr), (void)(size)) - #define MA_ASAN_UNPOISON_MEMORY_REGION(addr, size) ((void)(addr), (void)(size)) -#else - #define MA_ASAN_POISON_MEMORY_REGION(addr, size) ASAN_POISON_MEMORY_REGION(addr, size) - #define MA_ASAN_UNPOISON_MEMORY_REGION(addr, size) ASAN_UNPOISON_MEMORY_REGION(addr, size) -#endif - -MA_THREAD_LOCAL MA_SourceLoc MA_SavedSourceLoc; -MA_API void MA_SaveSourceLocEx(const char *file, int line) { - MA_SavedSourceLoc.file = file; - MA_SavedSourceLoc.line = line; -} - -MA_API size_t MA_GetAlignOffset(size_t size, size_t align) { - size_t mask = align - 1; - size_t val = size & mask; - if (val) { - val = align - val; - } - return val; -} - -MA_API size_t MA_AlignUp(size_t size, size_t align) { - size_t result = size + MA_GetAlignOffset(size, align); - return result; -} - -MA_API size_t MA_AlignDown(size_t size, size_t align) { - size += 1; // Make sure when align is 8 doesn't get rounded down to 0 - size_t result = size - (align - MA_GetAlignOffset(size, align)); - return result; -} - -MA_StaticFunc uint8_t *MV__AdvanceCommit(MV_Memory *m, size_t *commit_size, size_t page_size) { - size_t aligned_up_commit = MA_AlignUp(*commit_size, page_size); - size_t to_be_total_commited_size = aligned_up_commit + m->commit; - size_t to_be_total_commited_size_clamped_to_reserve = MA_CLAMP_TOP(to_be_total_commited_size, m->reserve); - size_t adjusted_to_boundary_commit = to_be_total_commited_size_clamped_to_reserve - m->commit; - MA_Assertf(adjusted_to_boundary_commit, "Reached the virtual memory reserved boundary"); - *commit_size = adjusted_to_boundary_commit; - - if (adjusted_to_boundary_commit == 0) { - return 0; - } - uint8_t *result = m->data + m->commit; - return result; -} - -MA_API void MA_PopToPos(MA_Arena *arena, size_t pos) { - MA_Assertf(arena->len >= arena->base_len, "Bug: arena->len shouldn't ever be smaller then arena->base_len"); - pos = MA_CLAMP(pos, arena->base_len, arena->len); - size_t size = arena->len - pos; - arena->len = pos; - MA_ASAN_POISON_MEMORY_REGION(arena->memory.data + arena->len, size); -} - -MA_API void MA_PopSize(MA_Arena *arena, size_t size) { - MA_PopToPos(arena, arena->len - size); -} - -MA_API void MA_DeallocateArena(MA_Arena *arena) { - MV_Deallocate(&arena->memory); -} - -MA_API void MA_Reset(MA_Arena *arena) { - MA_PopToPos(arena, 0); -} - -MA_StaticFunc size_t MA__AlignLen(MA_Arena *a) { - size_t align_offset = a->alignment ? MA_GetAlignOffset((uintptr_t)a->memory.data + (uintptr_t)a->len, a->alignment) : 0; - size_t aligned = a->len + align_offset; - return aligned; -} - -MA_API void MA_SetAlignment(MA_Arena *arena, int alignment) { - arena->alignment = alignment; -} - -MA_API uint8_t *MA_GetTop(MA_Arena *a) { - MA_Assertf(a->memory.data, "Arena needs to be inited, there is no top to get!"); - return a->memory.data + a->len; -} - -MA_API void *MA__PushSizeNonZeroed(MA_Arena *a, size_t size) { - size_t align_offset = a->alignment ? MA_GetAlignOffset((uintptr_t)a->memory.data + (uintptr_t)a->len, a->alignment) : 0; - size_t aligned_len = a->len + align_offset; - size_t size_with_alignment = size + align_offset; - - if (a->len + size_with_alignment > a->memory.commit) { - if (a->memory.reserve == 0) { -#if MA_ZERO_IS_INITIALIZATION - MA_Init(a); -#else - MA_Assertf(0, "Pushing on uninitialized arena with zero initialization turned off"); -#endif - } - bool result = MV_Commit(&a->memory, size_with_alignment + MA_COMMIT_ADD_SIZE); - MA_Assertf(result, "%s(%d): Failed to commit memory more memory! reserve: %zu commit: %zu len: %zu size_with_alignment: %zu", MA_SavedSourceLoc.file, MA_SavedSourceLoc.line, a->memory.reserve, a->memory.commit, a->len, size_with_alignment); - (void)result; - } - - uint8_t *result = a->memory.data + aligned_len; - a->len += size_with_alignment; - MA_Assertf(a->len <= a->memory.commit, "%s(%d): Reached commit boundary! reserve: %zu commit: %zu len: %zu base_len: %zu alignment: %d size_with_alignment: %zu", MA_SavedSourceLoc.file, MA_SavedSourceLoc.line, a->memory.reserve, a->memory.commit, a->len, a->base_len, a->alignment, size_with_alignment); - MA_ASAN_UNPOISON_MEMORY_REGION(result, size); - return (void *)result; -} - -MA_API void *MA__PushSize(MA_Arena *arena, size_t size) { - void *result = MA__PushSizeNonZeroed(arena, size); - MA_MemoryZero(result, size); - return result; -} - -MA_API char *MA__PushStringCopy(MA_Arena *arena, char *p, size_t size) { - char *copy_buffer = (char *)MA__PushSizeNonZeroed(arena, size + 1); - MA_MemoryCopy(copy_buffer, p, size); - copy_buffer[size] = 0; - return copy_buffer; -} - -MA_API void *MA__PushCopy(MA_Arena *arena, void *p, size_t size) { - void *copy_buffer = MA__PushSizeNonZeroed(arena, size); - MA_MemoryCopy(copy_buffer, p, size); - return copy_buffer; -} - -MA_API MA_Arena MA_PushArena(MA_Arena *arena, size_t size) { - MA_Arena result; - MA_MemoryZero(&result, sizeof(result)); - result.memory.data = MA_PushArrayNonZeroed(arena, uint8_t, size); - result.memory.commit = size; - result.memory.reserve = size; - result.alignment = arena->alignment; - return result; -} - -MA_API MA_Arena *MA_PushArenaP(MA_Arena *arena, size_t size) { - MA_Arena *result = MA_PushStruct(arena, MA_Arena); - *result = MA_PushArena(arena, size); - return result; -} - -MA_API void MA_InitEx(MA_Arena *a, size_t reserve) { - a->memory = MV_Reserve(reserve); - MA_ASAN_POISON_MEMORY_REGION(a->memory.data, a->memory.reserve); - a->alignment = MA_DEFAULT_ALIGNMENT; -} - -MA_API void MA_Init(MA_Arena *a) { - MA_InitEx(a, MA_DEFAULT_RESERVE_SIZE); -} - -MA_API void MA_MakeSureInitialized(MA_Arena *a) { - if (a->memory.data == 0) { - MA_Init(a); - } -} - -MA_API MA_Arena *MA_Bootstrap(void) { - MA_Arena bootstrap_arena = {0}; - MA_Arena *arena = MA_PushStruct(&bootstrap_arena, MA_Arena); - *arena = bootstrap_arena; - arena->base_len = arena->len; - return arena; -} - -MA_API void MA_InitFromBuffer(MA_Arena *arena, void *buffer, size_t size) { - arena->memory.data = (uint8_t *)buffer; - arena->memory.commit = size; - arena->memory.reserve = size; - arena->alignment = MA_DEFAULT_ALIGNMENT; - MA_ASAN_POISON_MEMORY_REGION(arena->memory.data, arena->memory.reserve); -} - -MA_API MA_Arena MA_MakeFromBuffer(void *buffer, size_t size) { - MA_Arena arena; - MA_MemoryZero(&arena, sizeof(arena)); - MA_InitFromBuffer(&arena, buffer, size); - return arena; -} - -MA_API MA_Arena MA_Create() { - MA_Arena arena = {0}; - MA_Init(&arena); - return arena; -} - -MA_API bool MA_IsPointerInside(MA_Arena *arena, void *p) { - uintptr_t pointer = (uintptr_t)p; - uintptr_t start = (uintptr_t)arena->memory.data; - uintptr_t stop = start + (uintptr_t)arena->len; - bool result = pointer >= start && pointer < stop; - return result; -} - -MA_API MA_Temp MA_BeginTemp(MA_Arena *arena) { - MA_Temp result; - result.pos = arena->len; - result.arena = arena; - return result; -} - -MA_API void MA_EndTemp(MA_Temp checkpoint) { - MA_PopToPos(checkpoint.arena, checkpoint.pos); -} - -MA_THREAD_LOCAL MA_Arena *MA_ScratchArenaPool[4]; - -MA_API void MA_InitScratch(void) { - for (int i = 0; i < MA_Lengthof(MA_ScratchArenaPool); i += 1) { - MA_ScratchArenaPool[i] = MA_Bootstrap(); - } -} - -MA_API MA_Temp MA_GetScratchEx(MA_Arena **conflicts, int conflict_count) { - MA_Arena *unoccupied = 0; - for (int i = 0; i < MA_Lengthof(MA_ScratchArenaPool); i += 1) { - MA_Arena *from_pool = MA_ScratchArenaPool[i]; - unoccupied = from_pool; - for (int conflict_i = 0; conflict_i < conflict_count; conflict_i += 1) { - MA_Arena *from_conflict = conflicts[conflict_i]; - if (from_pool == from_conflict) { - unoccupied = 0; - break; - } - } - - if (unoccupied) { - break; - } - } - - MA_Assertf(unoccupied, "Failed to get free scratch memory, this is a fatal error, this shouldnt happen"); - MA_Temp result = MA_BeginTemp(unoccupied); - return result; -} - -MA_API MA_Temp MA_GetScratch(void) { - MA_Temp result = MA_BeginTemp(MA_ScratchArenaPool[0]); - return result; -} - -MA_API MA_Temp MA_GetScratch1(MA_Arena *conflict) { - MA_Arena *conflicts[] = {conflict}; - return MA_GetScratchEx(conflicts, 1); -} - -#ifdef _WIN32 - #ifndef NOMINMAX - #define NOMINMAX - #endif - #ifndef WIN32_LEAN_AND_MEAN - #define WIN32_LEAN_AND_MEAN - #endif - #include - -const size_t MV__WIN32_PAGE_SIZE = 4096; - -MA_API MV_Memory MV_Reserve(size_t size) { - MV_Memory result; - MA_MemoryZero(&result, sizeof(result)); - size_t adjusted_size = MA_AlignUp(size, MV__WIN32_PAGE_SIZE); - result.data = (uint8_t *)VirtualAlloc(0, adjusted_size, MEM_RESERVE, PAGE_READWRITE); - MA_Assertf(result.data, "Failed to reserve virtual memory"); - result.reserve = adjusted_size; - return result; -} - -MA_API bool MV_Commit(MV_Memory *m, size_t commit) { - uint8_t *pointer = MV__AdvanceCommit(m, &commit, MV__WIN32_PAGE_SIZE); - if (pointer) { - void *result = VirtualAlloc(pointer, commit, MEM_COMMIT, PAGE_READWRITE); - MA_Assertf(result, "Failed to commit more memory"); - if (result) { - m->commit += commit; - return true; - } - } - return false; -} - -MA_API void MV_Deallocate(MV_Memory *m) { - BOOL result = VirtualFree(m->data, 0, MEM_RELEASE); - MA_Assertf(result != 0, "Failed to release MV_Memory"); -} - -MA_API bool MV_DecommitPos(MV_Memory *m, size_t pos) { - size_t aligned = MA_AlignDown(pos, MV__WIN32_PAGE_SIZE); - size_t adjusted_pos = MA_CLAMP_TOP(aligned, m->commit); - size_t size_to_decommit = m->commit - adjusted_pos; - if (size_to_decommit) { - uint8_t *base_address = m->data + adjusted_pos; - BOOL result = VirtualFree(base_address, size_to_decommit, MEM_DECOMMIT); - if (result) { - m->commit -= size_to_decommit; - return true; - } - } - return false; -} - -#elif __unix__ || __linux__ || __APPLE__ - #include - #define MV__UNIX_PAGE_SIZE 4096 -MA_API MV_Memory MV_Reserve(size_t size) { - MV_Memory result = {}; - size_t size_aligned = MA_AlignUp(size, MV__UNIX_PAGE_SIZE); - result.data = (uint8_t *)mmap(0, size_aligned, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); - MA_Assertf(result.data, "Failed to reserve memory using mmap!!"); - if (result.data) { - result.reserve = size_aligned; - } - return result; -} - -MA_API bool MV_Commit(MV_Memory *m, size_t commit) { - uint8_t *pointer = MV__AdvanceCommit(m, &commit, MV__UNIX_PAGE_SIZE); - if (pointer) { - int mprotect_result = mprotect(pointer, commit, PROT_READ | PROT_WRITE); - MA_Assertf(mprotect_result == 0, "Failed to commit more memory using mmap"); - if (mprotect_result == 0) { - m->commit += commit; - return true; - } - } - return false; -} - -MA_API void MV_Deallocate(MV_Memory *m) { - int result = munmap(m->data, m->reserve); - MA_Assertf(result == 0, "Failed to release virtual memory using munmap"); -} -#else -MA_API MV_Memory MV_Reserve(size_t size) { - MV_Memory result = {0}; - return result; -} - -MA_API bool MV_Commit(MV_Memory *m, size_t commit) { - return false; -} - -MA_API void MV_Deallocate(MV_Memory *m) { -} - -#endif \ No newline at end of file diff --git a/src/build_tool/standalone_libraries/arena.h b/src/build_tool/standalone_libraries/arena.h deleted file mode 100644 index b7c9e87..0000000 --- a/src/build_tool/standalone_libraries/arena.h +++ /dev/null @@ -1,179 +0,0 @@ -#ifndef MA_HEADER -#define MA_HEADER -#include -#include -#include - -#define MA_KIB(x) ((x##ull) * 1024ull) -#define MA_MIB(x) (MA_KIB(x) * 1024ull) -#define MA_GIB(x) (MA_MIB(x) * 1024ull) -#define MA_TIB(x) (MA_GIB(x) * 1024ull) - -typedef struct MV_Memory MV_Memory; -typedef struct MA_Temp MA_Temp; -typedef struct MA_Arena MA_Arena; -typedef struct MA_SourceLoc MA_SourceLoc; - -#ifndef MA_DEFAULT_RESERVE_SIZE - #define MA_DEFAULT_RESERVE_SIZE MA_GIB(1) -#endif - -#ifndef MA_DEFAULT_ALIGNMENT - #define MA_DEFAULT_ALIGNMENT 8 -#endif - -#ifndef MA_COMMIT_ADD_SIZE - #define MA_COMMIT_ADD_SIZE MA_MIB(4) -#endif - -#ifndef MA_ZERO_IS_INITIALIZATION - #define MA_ZERO_IS_INITIALIZATION 1 -#endif - -#ifndef MA_API - #ifdef __cplusplus - #define MA_API extern "C" - #else - #define MA_API - #endif -#endif - -#ifndef MA_THREAD_LOCAL - #if defined(__cplusplus) && __cplusplus >= 201103L - #define MA_THREAD_LOCAL thread_local - #elif defined(__GNUC__) - #define MA_THREAD_LOCAL __thread - #elif defined(_MSC_VER) - #define MA_THREAD_LOCAL __declspec(thread) - #elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && !defined(__STDC_NO_THREADS__) - #define MA_THREAD_LOCAL _Thread_local - #elif defined(__TINYC__) - #define MA_THREAD_LOCAL _Thread_local - #else - #error Couldnt figure out thread local, needs to be provided manually - #endif -#endif - -#ifndef MA_MemoryZero - #include - #define MA_MemoryZero(p, size) memset(p, 0, size) -#endif - -#ifndef MA_MemoryCopy - #include - #define MA_MemoryCopy(dst, src, size) memcpy(dst, src, size); -#endif - -struct MV_Memory { - size_t commit; - size_t reserve; - uint8_t *data; -}; - -struct MA_Arena { - MV_Memory memory; - int alignment; - size_t len; - size_t base_len; // When popping to 0 this is the minimum "len" value - // It's so that Bootstrapped arena won't delete itself when Reseting. -}; - -struct MA_Temp { - MA_Arena *arena; - size_t pos; -}; - -struct MA_SourceLoc { - const char *file; - int line; -}; - -extern MA_THREAD_LOCAL MA_SourceLoc MA_SavedSourceLoc; -#define MA_SaveSourceLoc() MA_SaveSourceLocEx(__FILE__, __LINE__) -MA_API void MA_SaveSourceLocEx(const char *file, int line); - -#define MA_PushSize(a, size) MA__PushSize(a, size) -#define MA_PushSizeNonZeroed(a, size) MA__PushSizeNonZeroed(a, size) -#define MA_PushCopy(a, p, size) MA__PushCopy(a, p, size) -#define MA_PushStringCopy(a, p, size) MA__PushStringCopy(a, p, size) - -#define MA_PushArrayNonZeroed(a, T, c) (T *)MA__PushSizeNonZeroed(a, sizeof(T) * (c)) -#define MA_PushStructNonZeroed(a, T) (T *)MA__PushSizeNonZeroed(a, sizeof(T)) -#define MA_PushStruct(a, T) (T *)MA__PushSize(a, sizeof(T)) -#define MA_PushArray(a, T, c) (T *)MA__PushSize(a, sizeof(T) * (c)) -#define MA_PushStructCopy(a, T, p) (T *)MA__PushCopy(a, (p), sizeof(T)) - -// clang-format off -MA_API void MA_InitEx(MA_Arena *a, size_t reserve); -MA_API void MA_Init(MA_Arena *a); -MA_API MA_Arena MA_Create(); -MA_API void MA_MakeSureInitialized(MA_Arena *a); -MA_API void MA_InitFromBuffer(MA_Arena *arena, void *buffer, size_t size); -MA_API MA_Arena MA_MakeFromBuffer(void *buffer, size_t size); -MA_API MA_Arena * MA_Bootstrap(void); -MA_API MA_Arena MA_PushArena(MA_Arena *arena, size_t size); -MA_API MA_Arena * MA_PushArenaP(MA_Arena *arena, size_t size); - -MA_API void * MA__PushSizeNonZeroed(MA_Arena *a, size_t size); -MA_API void * MA__PushSize(MA_Arena *arena, size_t size); -MA_API char * MA__PushStringCopy(MA_Arena *arena, char *p, size_t size); -MA_API void * MA__PushCopy(MA_Arena *arena, void *p, size_t size); -MA_API MA_Temp MA_BeginTemp(MA_Arena *arena); -MA_API void MA_EndTemp(MA_Temp checkpoint); - -MA_API void MA_PopToPos(MA_Arena *arena, size_t pos); -MA_API void MA_PopSize(MA_Arena *arena, size_t size); -MA_API void MA_DeallocateArena(MA_Arena *arena); -MA_API void MA_Reset(MA_Arena *arena); - -MA_API size_t MA_GetAlignOffset(size_t size, size_t align); -MA_API size_t MA_AlignUp(size_t size, size_t align); -MA_API size_t MA_AlignDown(size_t size, size_t align); - -MA_API bool MA_IsPointerInside(MA_Arena *arena, void *p); -MA_API void MA_SetAlignment(MA_Arena *arena, int alignment); -MA_API uint8_t * MA_GetTop(MA_Arena *a); - -MA_API MV_Memory MV_Reserve(size_t size); -MA_API bool MV_Commit(MV_Memory *m, size_t commit); -MA_API void MV_Deallocate(MV_Memory *m); -MA_API bool MV_DecommitPos(MV_Memory *m, size_t pos); -// clang-format on - -extern MA_THREAD_LOCAL MA_Arena *MA_ScratchArenaPool[4]; -#define MA_CheckpointScope(name, InArena) for (MA_Temp name = MA_BeginTemp(InArena); name.arena; (MA_EndTemp(name), name.arena = 0)) -#define MA_ScratchScope(x) for (MA_Temp x = MA_GetScratch(); x.arena; (MA_ReleaseScratch(x), x.arena = 0)) -#define MA_ReleaseScratch MA_EndTemp -MA_API MA_Temp MA_GetScratchEx(MA_Arena **conflicts, int conflict_count); -MA_API MA_Temp MA_GetScratch(void); -MA_API MA_Temp MA_GetScratch1(MA_Arena *conflict); - -#if defined(__cplusplus) -struct MA_Scratch { - MA_Temp checkpoint; - MA_Scratch() { this->checkpoint = MA_GetScratch(); } - MA_Scratch(MA_Temp conflict) { this->checkpoint = MA_GetScratch1(conflict.arena); } - MA_Scratch(MA_Temp c1, MA_Temp c2) { - MA_Arena *conflicts[] = {c1.arena, c2.arena}; - this->checkpoint = MA_GetScratchEx(conflicts, 2); - } - ~MA_Scratch() { MA_EndTemp(checkpoint); } - operator MA_Arena *() { return checkpoint.arena; } - - private: // @Note: Disable copy constructors, cause its error prone - MA_Scratch(MA_Scratch &arena); - MA_Scratch(MA_Scratch &arena, MA_Scratch &a2); -}; -#endif // __cplusplus - -#define MA_IS_POW2(x) (((x) & ((x)-1)) == 0) -#define MA_MIN(x, y) ((x) <= (y) ? (x) : (y)) -#define MA_MAX(x, y) ((x) >= (y) ? (x) : (y)) -#define MA_Lengthof(x) ((int64_t)((sizeof(x) / sizeof((x)[0])))) - -#define MA_CLAMP_TOP(x, max) ((x) >= (max) ? (max) : (x)) -#define MA_CLAMP_BOT(x, min) ((x) <= (min) ? (min) : (x)) -#define MA_CLAMP(x, min, max) ((x) >= (max) ? (max) : (x) <= (min) ? (min) \ - : (x)) - -#endif // MA_HEADER \ No newline at end of file diff --git a/src/build_tool/standalone_libraries/clexer.c b/src/build_tool/standalone_libraries/clexer.c deleted file mode 100644 index d8fac92..0000000 --- a/src/build_tool/standalone_libraries/clexer.c +++ /dev/null @@ -1,1549 +0,0 @@ -#include "clexer.h" -#include - -/* -- I'm pretty sure I can remove allocations for most of the current functions. -- I also can fix ResolvePath stuff so that it uses string+len and doesn't need allocations -- Add lexing options like in stb_c_lexer.h - -Instead of AND_CL_STRING_TERMINATE_ON_NEW_LINE he is doing some weird cool stuff with redefining -https://github.com/nothings/stb/blob/master/stb_c_lexer.h - -CL_MULTILINE_SSTRINGS -CL_DOLLAR_IDENT - -- Add proper string parsing, as additional function, CL_ParseString() or something, this is the only one that would need allocations - -*/ - -#ifndef CL_PRIVATE_FUNCTION - #if defined(__GNUC__) || defined(__clang__) - #define CL_PRIVATE_FUNCTION __attribute__((unused)) static - #else - #define CL_PRIVATE_FUNCTION static - #endif -#endif - -#ifndef CL_Allocate - #include - #define CL_Allocate(allocator, size) malloc(size) -#endif - -#ifndef CL_STRING_TO_DOUBLE - #include - #define CL_STRING_TO_DOUBLE(str, len) strtod(str, 0) -#endif - -#ifndef CL_ASSERT - #include - #define CL_ASSERT(x) assert(x) -#endif - -#ifndef CL_VSNPRINTF - #include - #define CL_VSNPRINTF vsnprintf -#endif - -#ifndef CL_SNPRINTF - #include - #define CL_SNPRINTF snprintf -#endif - -#ifndef CL__MemoryCopy - #include - #define CL__MemoryCopy(dst, src, s) memcpy(dst, src, s) -#endif - -#ifndef CL_MemoryZero - #include - #define CL_MemoryZero(p, size) memset(p, 0, size) -#endif - -#ifndef CL_FileExists - #define CL_FileExists CL__FileExists - #include -CL_PRIVATE_FUNCTION bool CL_FileExists(char *name) { - bool result = false; - FILE *f = fopen(name, "rb"); - if (f) { - result = true; - fclose(f); - } - return result; -} -#endif - -CL_PRIVATE_FUNCTION void CL_ReportError(CL_Lexer *T, CL_Token *token, const char *string, ...); - -CL_PRIVATE_FUNCTION char *CL_PushStringCopy(CL_Allocator arena, char *p, int size) { - char *copy_buffer = (char *)CL_Allocate(arena, size + 1); - CL__MemoryCopy(copy_buffer, p, size); - copy_buffer[size] = 0; - return copy_buffer; -} - -CL_INLINE void CL_Advance(CL_Lexer *T) { - if (*T->stream == '\n') { - T->line += 1; - T->column = 0; - } - else if (*T->stream == ' ') { - T->column += 1; - } - else if (*T->stream == '\t') { - T->column += 1; - } - else if (*T->stream == 0) { - return; - } - T->stream += 1; -} - -CL_INLINE bool CL_IsAlphabetic(char c) { - bool result = (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); - return result; -} - -CL_INLINE bool CL_IsNumeric(char c) { - bool result = (c >= '0' && c <= '9'); - return result; -} - -CL_INLINE bool CL_IsHexNumeric(char c) { - bool result = (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f'); - return result; -} - -CL_INLINE bool CL_IsWhitespace(char c) { - bool result = c == ' ' || c == '\n' || c == '\r' || c == '\t'; - return result; -} - -CL_INLINE bool CL_IsAlphanumeric(char c) { - bool result = CL_IsAlphabetic(c) || CL_IsNumeric(c); - return result; -} - -CL_API_FUNCTION void CL_SetTokenLength(CL_Lexer *T, CL_Token *token) { - intptr_t diff = T->stream - token->str; - CL_ASSERT(diff < 2147483647); - token->len = (int)diff; -} - -CL_PRIVATE_FUNCTION uint64_t CL_CharMapToNumber(char c) { - switch (c) { - case '0': return 0; break; - case '1': return 1; break; - case '2': return 2; break; - case '3': return 3; break; - case '4': return 4; break; - case '5': return 5; break; - case '6': return 6; break; - case '7': return 7; break; - case '8': return 8; break; - case '9': return 9; break; - case 'a': - case 'A': return 10; break; - case 'b': - case 'B': return 11; break; - case 'c': - case 'C': return 12; break; - case 'd': - case 'D': return 13; break; - case 'e': - case 'E': return 14; break; - case 'f': - case 'F': return 15; break; - default: return 255; - } -} - -CL_PRIVATE_FUNCTION uint64_t CL_ParseInteger(CL_Lexer *T, CL_Token *token, char *string, uint64_t len, uint64_t base) { - CL_ASSERT(base >= 2 && base <= 16); - uint64_t acc = 0; - for (uint64_t i = 0; i < len; i++) { - uint64_t num = CL_CharMapToNumber(string[i]); - if (num >= base) { - CL_ReportError(T, token, "Internal compiler error! Failed to parse a number"); - break; - } - acc *= base; - acc += num; - } - return acc; -} - -typedef struct CL_UTF32Result { - uint32_t out_str; - int advance; - int error; -} CL_UTF32Result; - -CL_PRIVATE_FUNCTION CL_UTF32Result CL_UTF8ToUTF32(char *c, int max_advance) { - CL_UTF32Result result = {0}; - - if ((c[0] & 0x80) == 0) { // Check if leftmost zero of first byte is unset - if (max_advance >= 1) { - result.out_str = c[0]; - result.advance = 1; - } - else result.error = 1; - } - - else if ((c[0] & 0xe0) == 0xc0) { - if ((c[1] & 0xc0) == 0x80) { // Continuation byte required - if (max_advance >= 2) { - result.out_str = (uint32_t)(c[0] & 0x1f) << 6u | (c[1] & 0x3f); - result.advance = 2; - } - else result.error = 2; - } - else result.error = 2; - } - - else if ((c[0] & 0xf0) == 0xe0) { - if ((c[1] & 0xc0) == 0x80 && (c[2] & 0xc0) == 0x80) { // Two continuation bytes required - if (max_advance >= 3) { - result.out_str = (uint32_t)(c[0] & 0xf) << 12u | (uint32_t)(c[1] & 0x3f) << 6u | (c[2] & 0x3f); - result.advance = 3; - } - else result.error = 3; - } - else result.error = 3; - } - - else if ((c[0] & 0xf8) == 0xf0) { - if ((c[1] & 0xc0) == 0x80 && (c[2] & 0xc0) == 0x80 && (c[3] & 0xc0) == 0x80) { // Three continuation bytes required - if (max_advance >= 4) { - result.out_str = (uint32_t)(c[0] & 0xf) << 18u | (uint32_t)(c[1] & 0x3f) << 12u | (uint32_t)(c[2] & 0x3f) << 6u | (uint32_t)(c[3] & 0x3f); - result.advance = 4; - } - else result.error = 4; - } - else result.error = 4; - } - else result.error = 4; - - return result; -} - -// @todo I think I should look at this again -CL_PRIVATE_FUNCTION void CL_ParseCharLiteral(CL_Lexer *T, CL_Token *token) { - token->kind = CL_CHARLIT; - token->str = T->stream; - while (*T->stream != '\'') { - if (*T->stream == '\\') { - CL_Advance(T); - } - if (*T->stream == 0) { - CL_ReportError(T, token, "Unclosed character literal!"); - return; - } - CL_Advance(T); - } - CL_SetTokenLength(T, token); - - if (token->str[0] == '\\') { - switch (token->str[1]) { - case '\\': token->u64 = '\\'; break; - case '\'': token->u64 = '\''; break; - case '"': token->u64 = '"'; break; - case 't': token->u64 = '\t'; break; - case 'v': token->u64 = '\v'; break; - case 'f': token->u64 = '\f'; break; - case 'n': token->u64 = '\n'; break; - case 'r': token->u64 = '\r'; break; - case 'a': token->u64 = '\a'; break; - case 'b': token->u64 = '\b'; break; - case '0': token->u64 = '\0'; break; - case 'x': - case 'X': CL_ASSERT(!"Not implemented"); break; // Hex constant - case 'u': CL_ASSERT(!"Not implemented"); break; // Unicode constant - default: { - CL_ReportError(T, token, "Unknown escape code"); - } - } - } - - else { - if (token->len > 4) { - CL_ReportError(T, token, "This character literal has invalid format, it's too big"); - goto skip_utf_encode; - } - - token->u64 = 0; - int i = 0; - - for (; i < token->len;) { - CL_UTF32Result result = CL_UTF8ToUTF32(token->str + i, (int)token->len); - i += result.advance; - token->u64 |= result.out_str << (8 * (token->len - i)); - if (result.error) { - CL_ReportError(T, token, "This character literal couldnt be parsed as utf8"); - break; - } - } - if (i != token->len) { - CL_ReportError(T, token, "Character literal decode error"); - } - } - -skip_utf_encode: - CL_Advance(T); -} - -// It combines strings, verifies the escape sequences but doesn't do any allocations -// so the final string actually needs additional transformation pass. A pass -// that will combine the string snippets, replace escape sequences with actual values etc. -// -// @warning: @not_sure: we are not setting token->string_literal -// -// "String 1" "String 2" - those strings snippets are combined -// @todo: look at this again -// @todo: make a manual correct version that user can execute if he needs to -CL_PRIVATE_FUNCTION void CL_CheckString(CL_Lexer *T, CL_Token *token) { - token->kind = CL_STRINGLIT; -combine_next_string_literal: - while (*T->stream != '"' && *T->stream != 0 AND_CL_STRING_TERMINATE_ON_NEW_LINE) { - if (*T->stream == '\\') { - CL_Advance(T); - switch (*T->stream) { - case 'a': - case 'b': - case 'e': - case 'f': - case 'n': - case 'r': - case 't': - case 'v': - case '\\': - case '\'': - case '?': - case '"': - case 'x': - case 'X': // Hex constant - case 'u': // Unicode constant - case 'U': - break; - case '0': // octal numbers or null - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - break; - default: { - CL_ReportError(T, token, "Invalid escape sequence"); - return; - } - } - } - CL_Advance(T); - } - CL_Advance(T); - - // Try to seek if there is a consecutive string. - // If there is such string we try to combine it. - { - char *seek_for_next_string = T->stream; - while (CL_IsWhitespace(*seek_for_next_string)) { - seek_for_next_string += 1; - } - - if (*seek_for_next_string == '"') { - seek_for_next_string += 1; - while (T->stream != seek_for_next_string) CL_Advance(T); - goto combine_next_string_literal; - } - } - CL_SetTokenLength(T, token); -} - -CL_PRIVATE_FUNCTION void CL_IsIdentifierKeyword(CL_Token *token) { - if (token->len == 1) return; - char *c = token->str; - switch (c[0]) { - case 'v': { - switch (c[1]) { - case 'o': { - if (CL_StringsAreEqual(token->str, token->len, "void", 4)) { - token->kind = CL_KEYWORD_VOID; - } - else if (CL_StringsAreEqual(token->str, token->len, "volatile", 8)) { - token->kind = CL_KEYWORD_VOLATILE; - } - } break; - } - } break; - case 'i': { - switch (c[1]) { - case 'n': { - if (CL_StringsAreEqual(token->str, token->len, "int", 3)) { - token->kind = CL_KEYWORD_INT; - } - else if (CL_StringsAreEqual(token->str, token->len, "inline", 6)) { - token->kind = CL_KEYWORD_INLINE; - } - } break; - case 'f': { - if (CL_StringsAreEqual(token->str, token->len, "if", 2)) { - token->kind = CL_KEYWORD_IF; - } - } break; - } - } break; - case 'c': { - switch (c[1]) { - case 'h': { - if (CL_StringsAreEqual(token->str, token->len, "char", 4)) { - token->kind = CL_KEYWORD_CHAR; - } - } break; - case 'o': { - if (CL_StringsAreEqual(token->str, token->len, "const", 5)) { - token->kind = CL_KEYWORD_CONST; - } - else if (CL_StringsAreEqual(token->str, token->len, "continue", 8)) { - token->kind = CL_KEYWORD_CONTINUE; - } - } break; - case 'a': { - if (CL_StringsAreEqual(token->str, token->len, "case", 4)) { - token->kind = CL_KEYWORD_CASE; - } - } break; - } - } break; - case 'u': { - switch (c[1]) { - case 'n': { - if (CL_StringsAreEqual(token->str, token->len, "unsigned", 8)) { - token->kind = CL_KEYWORD_UNSIGNED; - } - else if (CL_StringsAreEqual(token->str, token->len, "union", 5)) { - token->kind = CL_KEYWORD_UNION; - } - } break; - } - } break; - case 's': { - switch (c[1]) { - case 'i': { - if (CL_StringsAreEqual(token->str, token->len, "signed", 6)) { - token->kind = CL_KEYWORD_SIGNED; - } - else if (CL_StringsAreEqual(token->str, token->len, "sizeof", 6)) { - token->kind = CL_KEYWORD_SIZEOF; - } - } break; - case 'h': { - if (CL_StringsAreEqual(token->str, token->len, "short", 5)) { - token->kind = CL_KEYWORD_SHORT; - } - } break; - case 't': { - if (CL_StringsAreEqual(token->str, token->len, "static", 6)) { - token->kind = CL_KEYWORD_STATIC; - } - else if (CL_StringsAreEqual(token->str, token->len, "struct", 6)) { - token->kind = CL_KEYWORD_STRUCT; - } - } break; - case 'w': { - if (CL_StringsAreEqual(token->str, token->len, "switch", 6)) { - token->kind = CL_KEYWORD_SWITCH; - } - } break; - } - } break; - case 'l': { - switch (c[1]) { - case 'o': { - if (CL_StringsAreEqual(token->str, token->len, "long", 4)) { - token->kind = CL_KEYWORD_LONG; - } - } break; - } - } break; - case 'd': { - switch (c[1]) { - case 'o': { - if (CL_StringsAreEqual(token->str, token->len, "double", 6)) { - token->kind = CL_KEYWORD_DOUBLE; - } - else if (CL_StringsAreEqual(token->str, token->len, "do", 2)) { - token->kind = CL_KEYWORD_DO; - } - } break; - case 'e': { - if (CL_StringsAreEqual(token->str, token->len, "default", 7)) { - token->kind = CL_KEYWORD_DEFAULT; - } - } break; - } - } break; - case 'f': { - switch (c[1]) { - case 'l': { - if (CL_StringsAreEqual(token->str, token->len, "float", 5)) { - token->kind = CL_KEYWORD_FLOAT; - } - } break; - case 'o': { - if (CL_StringsAreEqual(token->str, token->len, "for", 3)) { - token->kind = CL_KEYWORD_FOR; - } - } break; - } - } break; - case '_': { - switch (c[1]) { - case 'B': { - if (CL_StringsAreEqual(token->str, token->len, "_Bool", 5)) { - token->kind = CL_KEYWORD__BOOL; - } - } break; - case 'C': { - if (CL_StringsAreEqual(token->str, token->len, "_Complex", 8)) { - token->kind = CL_KEYWORD__COMPLEX; - } - } break; - case 'I': { - if (CL_StringsAreEqual(token->str, token->len, "_Imaginary", 10)) { - token->kind = CL_KEYWORD__IMAGINARY; - } - } break; - case 'T': { - if (CL_StringsAreEqual(token->str, token->len, "_Thread_local", 13)) { - token->kind = CL_KEYWORD__THREAD_LOCAL; - } - } break; - case 'A': { - if (CL_StringsAreEqual(token->str, token->len, "_Atomic", 7)) { - token->kind = CL_KEYWORD__ATOMIC; - } - else if (CL_StringsAreEqual(token->str, token->len, "_Alignas", 8)) { - token->kind = CL_KEYWORD__ALIGNAS; - } - else if (CL_StringsAreEqual(token->str, token->len, "_Alignof", 8)) { - token->kind = CL_KEYWORD__ALIGNOF; - } - } break; - case 'N': { - if (CL_StringsAreEqual(token->str, token->len, "_Noreturn", 9)) { - token->kind = CL_KEYWORD__NORETURN; - } - } break; - case 'S': { - if (CL_StringsAreEqual(token->str, token->len, "_Static_assert", 14)) { - token->kind = CL_KEYWORD__STATIC_ASSERT; - } - } break; - case 'G': { - if (CL_StringsAreEqual(token->str, token->len, "_Generic", 8)) { - token->kind = CL_KEYWORD__GENERIC; - } - } break; - } - } break; - case 'a': { - switch (c[1]) { - case 'u': { - if (CL_StringsAreEqual(token->str, token->len, "auto", 4)) { - token->kind = CL_KEYWORD_AUTO; - } - } break; - } - } break; - case 'e': { - switch (c[1]) { - case 'x': { - if (CL_StringsAreEqual(token->str, token->len, "extern", 6)) { - token->kind = CL_KEYWORD_EXTERN; - } - } break; - case 'n': { - if (CL_StringsAreEqual(token->str, token->len, "enum", 4)) { - token->kind = CL_KEYWORD_ENUM; - } - } break; - case 'l': { - if (CL_StringsAreEqual(token->str, token->len, "else", 4)) { - token->kind = CL_KEYWORD_ELSE; - } - } break; - } - } break; - case 'r': { - switch (c[1]) { - case 'e': { - if (CL_StringsAreEqual(token->str, token->len, "register", 8)) { - token->kind = CL_KEYWORD_REGISTER; - } - else if (CL_StringsAreEqual(token->str, token->len, "restrict", 8)) { - token->kind = CL_KEYWORD_RESTRICT; - } - else if (CL_StringsAreEqual(token->str, token->len, "return", 6)) { - token->kind = CL_KEYWORD_RETURN; - } - } break; - } - } break; - case 't': { - switch (c[1]) { - case 'y': { - if (CL_StringsAreEqual(token->str, token->len, "typedef", 7)) { - token->kind = CL_KEYWORD_TYPEDEF; - } - } break; - } - } break; - case 'b': { - switch (c[1]) { - case 'r': { - if (CL_StringsAreEqual(token->str, token->len, "break", 5)) { - token->kind = CL_KEYWORD_BREAK; - } - } break; - } - } break; - case 'w': { - switch (c[1]) { - case 'h': { - if (CL_StringsAreEqual(token->str, token->len, "while", 5)) { - token->kind = CL_KEYWORD_WHILE; - } - } break; - } - } break; - case 'g': { - switch (c[1]) { - case 'o': { - if (CL_StringsAreEqual(token->str, token->len, "goto", 4)) { - token->kind = CL_KEYWORD_GOTO; - } - } break; - } - } break; - } -} - -CL_PRIVATE_FUNCTION void CL_EatMacroWhitespace(CL_Lexer *T) { - while (T->stream[0] == ' ' || T->stream[0] == '\t') CL_Advance(T); -} - -CL_PRIVATE_FUNCTION void CL_EatUntil(CL_Lexer *T, char c) { - while (T->stream[0] != c && T->stream[0] != 0) CL_Advance(T); -} - -CL_PRIVATE_FUNCTION void CL_LexMacroInclude(CL_Lexer *T, CL_Token *token) { - token->kind = CL_PREPROC_INCLUDE; - CL_EatMacroWhitespace(T); - char end = 0; - if (*T->stream == '"') { - end = '"'; - } - else if (*T->stream == '<') { - end = '>'; - token->is_system_include = true; - } - else { - CL_ReportError(T, token, "Invalid include directive, file not specified"); - return; - } - CL_Advance(T); - - token->str = T->stream; - while (*T->stream != end) { - if (*T->stream == 0) { - CL_ReportError(T, token, "Invalid include directive, reached end of file while reading filename"); - } - if (*T->stream == '\n') { - CL_ReportError(T, token, "Invalid include directive filename, got newline character while reading filename"); - } - CL_Advance(T); - } - CL_SetTokenLength(T, token); - CL_Advance(T); - - // @not_sure: this is because we want null terminated input into path resolution stuff - token->string_literal = CL_PushStringCopy(T->arena, token->str, token->len); -} - -CL_PRIVATE_FUNCTION bool CL_LexMacro(CL_Lexer *T, CL_Token *token) { - CL_EatMacroWhitespace(T); - token->str = T->stream; - while (CL_IsAlphabetic(*T->stream)) CL_Advance(T); - CL_SetTokenLength(T, token); - - switch (*token->str) { - case 'd': - if (CL_StringsAreEqual(token->str, token->len, "define", 6)) { - token->kind = CL_PREPROC_DEFINE; - } - break; - - case 'i': - if (CL_StringsAreEqual(token->str, token->len, "ifdef", 5)) { - token->kind = CL_PREPROC_IFDEF; - } - else if (CL_StringsAreEqual(token->str, token->len, "ifndef", 6)) { - token->kind = CL_PREPROC_IFNDEF; - } - else if (CL_StringsAreEqual(token->str, token->len, "include", 7)) { - token->kind = CL_PREPROC_INCLUDE; - CL_LexMacroInclude(T, token); - } - else if (CL_StringsAreEqual(token->str, token->len, "if", 2)) { - token->kind = CL_PREPROC_IF; - } - break; - - case 'e': - if (CL_StringsAreEqual(token->str, token->len, "endif", 5)) { - token->kind = CL_PREPROC_ENDIF; - } - else if (CL_StringsAreEqual(token->str, token->len, "error", 5)) { - token->kind = CL_PREPROC_ERROR; - CL_EatMacroWhitespace(T); - token->str = T->stream; - CL_EatUntil(T, '\n'); - CL_SetTokenLength(T, token); - } - else if (CL_StringsAreEqual(token->str, token->len, "else", 4)) { - token->kind = CL_PREPROC_ELSE; - } - else if (CL_StringsAreEqual(token->str, token->len, "elif", 4)) { - token->kind = CL_PREPROC_ELIF; - } - break; - - case 'p': - if (CL_StringsAreEqual(token->str, token->len, "pragma", 6)) { - token->kind = CL_PREPROC_PRAGMA; - } - break; - - case 'u': - if (CL_StringsAreEqual(token->str, token->len, "undef", 5)) { - token->kind = CL_PREPROC_UNDEF; - } - break; - default: return false; - } - return true; -} - -// Skipped space here is for case #define Memes (a), this is not a function like macro because of space -static uint32_t CL_TokenID; // @todo: make it read only -CL_PRIVATE_FUNCTION void CL_PrepareToken(CL_Lexer *T, CL_Token *token, bool skipped_space) { - CL_MemoryZero(token, sizeof(*token)); - token->str = T->stream; - token->line = T->line; - token->column = T->column; - token->file = T->file; - token->id = ++CL_TokenID; - if (skipped_space) token->is_there_whitespace_before_token = true; - CL_Advance(T); -} - -CL_PRIVATE_FUNCTION void CL_DefaultTokenize(CL_Lexer *T, CL_Token *token) { - char *c = token->str; - switch (*c) { - case 0: break; - case '(': token->kind = CL_OPENPAREN; break; - case ')': token->kind = CL_CLOSEPAREN; break; - case '{': token->kind = CL_OPENBRACE; break; - case '}': token->kind = CL_CLOSEBRACE; break; - case '[': token->kind = CL_OPENBRACKET; break; - case ']': token->kind = CL_CLOSEBRACKET; break; - case ',': token->kind = CL_COMMA; break; - case '~': token->kind = CL_NEG; break; - case '?': token->kind = CL_QUESTION; break; - case ';': token->kind = CL_SEMICOLON; break; - case ':': token->kind = CL_COLON; break; - case '.': { - token->kind = CL_DOT; - if (T->stream[0] == '.' && T->stream[1] == '.') { - CL_Advance(T); - CL_Advance(T); - token->kind = CL_THREEDOTS; - } - } break; - case '/': { - token->kind = CL_DIV; - if (*T->stream == '/') { - token->kind = CL_COMMENT; - CL_Advance(T); - CL_EatUntil(T, '\n'); - CL_SetTokenLength(T, token); - } - else if (*T->stream == '*') { - token->kind = CL_COMMENT; - CL_Advance(T); - for (;;) { - if (T->stream[0] == '*' && T->stream[1] == '/') { - break; - } - if (T->stream[0] == 0) { - CL_ReportError(T, token, "Unclosed block comment"); - goto error_end_path; - } - CL_Advance(T); - } - token->str += 2; - CL_SetTokenLength(T, token); - CL_Advance(T); - CL_Advance(T); - } - else if (*T->stream == '=') { - token->kind = CL_DIVASSIGN; - CL_Advance(T); - } - } break; - case '#': { - if (*T->stream == '#') { - token->kind = CL_MACRO_CONCAT; - CL_Advance(T); - } - else { - bool is_macro_directive = CL_LexMacro(T, token); - if (is_macro_directive) { - T->inside_of_macro = true; - } - else { - if (!T->inside_of_macro) { - CL_ReportError(T, token, "Invalid preprocessor directive"); - goto error_end_path; - } - - token->kind = CL_PREPROC_STRINGIFY; - token->str = T->stream; - while (*T->stream == '_' || CL_IsAlphanumeric(*T->stream)) - CL_Advance(T); - CL_SetTokenLength(T, token); - } - } - } break; - case '>': { - if (*T->stream == '=') { - token->kind = CL_GREATERTHEN_OR_EQUAL; - CL_Advance(T); - } - else if (*T->stream == '>') { - CL_Advance(T); - if (*T->stream == '=') { - CL_Advance(T); - token->kind = CL_RIGHTSHIFTASSIGN; - } - else { - token->kind = CL_RIGHTSHIFT; - } - } - else { - token->kind = CL_GREATERTHEN; - } - } break; - case '<': { - token->kind = CL_LESSERTHEN; - if (*T->stream == '=') { - token->kind = CL_LESSERTHEN_OR_EQUAL; - CL_Advance(T); - } - else if (*T->stream == '<') { - CL_Advance(T); - if (*T->stream == '=') { - CL_Advance(T); - token->kind = CL_LEFTSHIFTASSIGN; - } - else { - token->kind = CL_LEFTSHIFT; - } - } - } break; - case '&': { - if (*T->stream == '=') { - token->kind = CL_ANDASSIGN; - CL_Advance(T); - } - else if (*T->stream == '&') { - token->kind = CL_AND; - CL_Advance(T); - } - else { - token->kind = CL_BITAND; - } - } break; - case '-': { - if (*T->stream == '-') { - token->kind = CL_DECREMENT; - CL_Advance(T); - } - else if (*T->stream == '=') { - token->kind = CL_SUBASSIGN; - CL_Advance(T); - } - else { - token->kind = CL_SUB; - } - } break; - case '+': { - if (*T->stream == '+') { - token->kind = CL_INCREMENT; - CL_Advance(T); - } - else if (*T->stream == '=') { - token->kind = CL_ADDASSIGN; - CL_Advance(T); - } - else { - token->kind = CL_ADD; - } - } break; - case '|': { - if (*T->stream == '|') { - token->kind = CL_OR; - CL_Advance(T); - } - else if (*T->stream == '=') { - token->kind = CL_ORASSIGN; - CL_Advance(T); - } - else { - token->kind = CL_BITOR; - } - } break; - case '=': { - if (*T->stream != '=') { - token->kind = CL_ASSIGN; - } - else { - CL_Advance(T); - token->kind = CL_EQUALS; - } - } break; - case '!': { - if (*T->stream != '=') { - token->kind = CL_NOT; - } - else { - CL_Advance(T); - token->kind = CL_NOTEQUALS; - } - } break; - case '*': { - token->kind = CL_MUL; - if (*T->stream == '=') { - CL_Advance(T); - token->kind = CL_MULASSIGN; - } - } break; - case '%': { - token->kind = CL_MOD; - if (*T->stream == '=') { - token->kind = CL_MODASSIGN; - CL_Advance(T); - } - } break; - case '^': { - token->kind = CL_BITXOR; - if (*T->stream == '=') { - CL_Advance(T); - token->kind = CL_XORASSIGN; - } - } break; - case '"': { - CL_CheckString(T, token); - } break; - case '\'': { - CL_ParseCharLiteral(T, token); - } break; - case 'U': { // @todo Unicode32 - if (*T->stream == '"') { - token->fix = CL_PREFIX_U32; - CL_Advance(T); - CL_CheckString(T, token); - } - else if (*T->stream == '\'') { - token->fix = CL_PREFIX_U32; - CL_Advance(T); - CL_ParseCharLiteral(T, token); - } - else goto parse_regular_char; - } break; - case 'u': { // Unicode16 - if (*T->stream == '8') { // Unicode8 - if (T->stream[1] == '"') { // U8 STRING - token->fix = CL_PREFIX_U8; - CL_Advance(T); - CL_Advance(T); - CL_CheckString(T, token); - } - else if (T->stream[1] == '\'') { // U8 CHAR - token->fix = CL_PREFIX_U8; - CL_Advance(T); - CL_Advance(T); - CL_ParseCharLiteral(T, token); - } - else goto parse_regular_char; - } - else if (*T->stream == '"') { // U16 STRING - token->fix = CL_PREFIX_U16; - CL_Advance(T); - CL_CheckString(T, token); - } - else if (*T->stream == '\'') { // U16 CHAR - CL_Advance(T); - CL_ParseCharLiteral(T, token); - } - else goto parse_regular_char; - } - case 'L': { // Widechar - if (*T->stream == '"') { - token->fix = CL_PREFIX_L; - CL_Advance(T); - CL_CheckString(T, token); // @todo UTF16 - } - else if (*T->stream == '\'') { - token->fix = CL_PREFIX_L; - CL_Advance(T); - CL_ParseCharLiteral(T, token); - } - else goto parse_regular_char; - } break; - case 'A': - case 'a': - case 'B': - case 'b': - case 'C': - case 'c': - case 'D': - case 'd': - case 'E': - case 'e': - case 'F': - case 'f': - case 'G': - case 'g': - case 'H': - case 'h': - case 'I': - case 'i': - case 'J': - case 'j': - case 'K': - case 'k': - /*case 'L':*/ case 'l': - case 'M': - case 'm': - case 'N': - case 'n': - case 'O': - case 'o': - case 'P': - case 'p': - case 'Q': - case 'q': - case 'R': - case 'r': - case 'S': - case 's': - case 'T': - case 't': - // case 'U': case 'u': - case 'V': - case 'v': - case 'W': - case 'w': - case 'X': - case 'x': - case 'Y': - case 'y': - case 'Z': - case 'z': - case '_': - parse_regular_char : { - token->kind = CL_IDENTIFIER; - while (*T->stream == '_' || CL_IsAlphanumeric(*T->stream)) { - CL_Advance(T); - } - CL_SetTokenLength(T, token); - CL_IsIdentifierKeyword(token); - } break; - case '0': { - if (*T->stream == 'x' || *T->stream == 'X') { - token->kind = CL_INT; - token->is_hex = true; - CL_Advance(T); - while (CL_IsHexNumeric(*T->stream)) { - CL_Advance(T); - } - uint64_t len = T->stream - token->str; - CL_ASSERT(len > 2); - token->u64 = CL_ParseInteger(T, token, token->str + 2, len - 2, 16); - break; - } - } - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': { - token->kind = CL_INT; - for (;;) { - if (*T->stream == '.') { - if (token->kind == CL_FLOAT) { - CL_ReportError(T, token, "Failed to parse a floating point number, invalid format, found multiple '.'"); - } - - if (token->kind == CL_INT) { - token->kind = CL_FLOAT; - } - } - else if (CL_IsNumeric(*T->stream) == false) { - break; - } - CL_Advance(T); - } - - if (token->kind == CL_INT) { - uint64_t len = T->stream - token->str; - CL_ASSERT(len > 0); - token->u64 = CL_ParseInteger(T, token, token->str, len, 10); - } - - else if (token->kind == CL_FLOAT) { - token->f64 = CL_STRING_TO_DOUBLE(token->str, token->len); - } - - else { - CL_ASSERT(token->kind == CL_ERROR); - } - - if (*T->stream == 'f' || *T->stream == 'F') { - CL_Advance(T); - token->fix = CL_SUFFIX_F; - } - - else if (*T->stream == 'l' || *T->stream == 'L') { - CL_Advance(T); - token->fix = CL_SUFFIX_L; - if (*T->stream == 'l' || *T->stream == 'L') { - CL_Advance(T); - token->fix = CL_SUFFIX_LL; - if (*T->stream == 'u' || *T->stream == 'U') { - CL_Advance(T); - token->fix = CL_SUFFIX_ULL; - } - } - else if (*T->stream == 'u' || *T->stream == 'U') { - CL_Advance(T); - token->fix = CL_SUFFIX_UL; - } - } - - else if (*T->stream == 'u' || *T->stream == 'U') { - CL_Advance(T); - token->fix = CL_SUFFIX_U; - if (*T->stream == 'l' || *T->stream == 'L') { - CL_Advance(T); - token->fix = CL_SUFFIX_UL; - if (*T->stream == 'l' || *T->stream == 'L') { - CL_Advance(T); - token->fix = CL_SUFFIX_ULL; - } - } - } - - } break; - - default: { - CL_ReportError(T, token, "Unhandled character, skipping ..."); - } break; - } - -error_end_path:; -} - -CL_PRIVATE_FUNCTION bool CL_EatWhitespace(CL_Lexer *T) { - bool skipped = false; - for (;;) { - if (CL_IsWhitespace(*T->stream)) { - if (*T->stream == '\n') T->inside_of_macro = false; - CL_Advance(T); - skipped = true; - } - else if (T->stream[0] == '\\' && T->stream[1] == '\n') { - CL_Advance(T); - CL_Advance(T); - skipped = true; - } - else if (T->stream[0] == '\\' && T->stream[1] == '\r' && T->stream[2] == '\n') { - CL_Advance(T); - CL_Advance(T); - CL_Advance(T); - skipped = true; - } - else { - break; - } - } - return skipped; -} - -CL_PRIVATE_FUNCTION void CL_TryToFinalizeToken(CL_Lexer *T, CL_Token *token) { - if (!token->len) { - CL_SetTokenLength(T, token); - } - if (T->inside_of_macro) { - token->is_inside_macro = true; - } -} - -CL_PRIVATE_FUNCTION void CL_InitNextToken(CL_Lexer *T, CL_Token *token) { - // Skip comments, comments get allocated on perm and gathered on the Tokenizer. - // First non comment token gets those comments attached. - for (;;) { - bool skipped = CL_EatWhitespace(T); - CL_PrepareToken(T, token, skipped); - CL_DefaultTokenize(T, token); - - if (token->kind == CL_EOF) { - break; - } - - if (T->select_includes) { - if (token->kind != CL_PREPROC_INCLUDE) continue; - } - - if (T->select_macros) { - if (!token->is_inside_macro) continue; - } - - if (T->select_comments) { - if (token->kind != CL_COMMENT) continue; - } - - if (T->skip_comments) { - if (token->kind == CL_COMMENT) continue; - } - - if (T->skip_macros) { - if (token->is_inside_macro) continue; - } - - break; - } - CL_TryToFinalizeToken(T, token); -} - -CL_API_FUNCTION CL_Token CL_Next(CL_Lexer *T) { - CL_Token result; - CL_MemoryZero(&result, sizeof(CL_Token)); - CL_InitNextToken(T, &result); - return result; -} - -CL_API_FUNCTION CL_Lexer CL_Begin(CL_Allocator arena, char *stream, char *filename) { - CL_Lexer lexer = {0}; - lexer.stream = lexer.stream_begin = stream; - lexer.file = filename; - lexer.arena = arena; - lexer.skip_comments = true; - return lexer; -} - -// -// -// - -CL_PRIVATE_FUNCTION char *CL_ChopLastSlash(CL_Allocator arena, char *str) { - int i = 0; - int slash_pos = -1; - while (str[i]) { - if (str[i] == '/') { - slash_pos = i; - } - i += 1; - } - - char *result = str; - if (slash_pos != -1) { - result = CL_PushStringCopy(arena, str, slash_pos); - } - else { - result = (char *)"./"; - } - return result; -} - -CL_PRIVATE_FUNCTION char *CL_JoinPath(CL_Allocator arena, char *a, char *b) { - int alen = CL_StringLength(a); - int blen = CL_StringLength(b); - int additional_len = 0; - - if (alen && a[alen - 1] != '/') additional_len = 1; - char *result = (char *)CL_Allocate(arena, sizeof(char) * (alen + blen + 1 + additional_len)); - CL__MemoryCopy(result, a, alen); - if (additional_len) result[alen++] = '/'; - CL__MemoryCopy(result + alen, b, blen); - result[alen + blen] = 0; - return result; -} - -CL_PRIVATE_FUNCTION bool CL_IsAbsolutePath(char *path) { -#if _WIN32 - bool result = CL_IsAlphabetic(path[0]) && path[1] == ':' && path[2] == '/'; -#else - bool result = path[0] == '/'; -#endif - return result; -} - -CL_PRIVATE_FUNCTION char *CL_SkipToLastSlash(char *p) { - int last_slash = 0; - for (int i = 0; p[i]; i += 1) { - if (p[i] == '/') last_slash = i; - } - return p + last_slash; -} - -CL_API_FUNCTION char *CL_ResolveFilepath(CL_Allocator arena, CL_SearchPaths *search_paths, char *filename, char *parent_file, bool is_system_include) { - CL_SearchPaths null_search_paths = {0}; - if (search_paths == 0) search_paths = &null_search_paths; - - if (search_paths->file_begin_to_ignore) { - char *name = CL_SkipToLastSlash(filename); - int namelen = CL_StringLength(name); - char *ignore = search_paths->file_begin_to_ignore; - int ignorelen = CL_StringLength(ignore); - if (namelen > ignorelen) { - namelen = ignorelen; - } - if (CL_StringsAreEqual(name, namelen, search_paths->file_begin_to_ignore, ignorelen)) { - return 0; - } - } - - if (CL_IsAbsolutePath(filename) && CL_FileExists(filename)) { - return filename; - } - - if (is_system_include) { - for (int path_i = 0; path_i < search_paths->system_include_path_count; path_i += 1) { - char *path_it = search_paths->system_include_path[path_i]; - char *file = CL_JoinPath(arena, path_it, filename); - if (CL_FileExists(file)) { - return file; - } - } - } - else { - if (parent_file) { - char *parent_dir = CL_ChopLastSlash(arena, parent_file); - char *file = CL_JoinPath(arena, parent_dir, filename); - if (CL_FileExists(file)) { - return file; - } - } - - for (int path_i = 0; path_i < search_paths->include_path_count; path_i += 1) { - char *path_it = search_paths->include_path[path_i]; - char *file = CL_JoinPath(arena, path_it, filename); - if (CL_FileExists(file)) { - return file; - } - } - } - return 0; -} - -// -// -// - -const char *CL_FixString[] = { - "SUFFIX_INVALID", - "SUFFIX_U", - "SUFFIX_UL", - "SUFFIX_ULL", - "SUFFIX_L", - "SUFFIX_LL", - "SUFFIX_F", - "SUFFIX_FL", - "PREFIX_U8", - "PREFIX_U16", - "PREFIX_U32", - "PREFIX_L", -}; - -const char *CL_KindString[] = { - "EOF", - "*", - "/", - "%", - "<<", - ">>", - "+", - "-", - "==", - "<", - ">", - "<=", - ">=", - "!=", - "&", - "|", - "^", - "&&", - "||", - "~", - "!", - "--", - "++", - "--", - "++", - "=", - "/=", - "*=", - "%=", - "-=", - "+=", - "&=", - "|=", - "^=", - "<<=", - ">>=", - "(", - ")", - "{", - "}", - "[", - "]", - ",", - "##", - "#Stringify", - "?", - "...", - ";", - ".", - ":", - "TAG", - "->", - "SIZEOF", - "DOCCOMMENT", - "COMMENT", - "IDENTIFIER", - "STRING_LITERAL", - "CHARACTER_LITERAL", - "ERROR TOKEN", - "FLOAT", - "INT", - "PREPROC_NULL", - "PREPROC_DEFINE", - "PREPROC_IFDEF", - "PREPROC_IFNDEF", - "PREPROC_INCLUDE", - "PREPROC_ENDIF", - "PREPROC_IF", - "PREPROC_PRAGMA", - "PREPROC_ERROR", - "PREPROC_ELSE", - "PREPROC_ELIF", - "PREPROC_UNDEF", - "KEYWORD_VOID", - "KEYWORD_INT", - "KEYWORD_CHAR", - "KEYWORD_UNSIGNED", - "KEYWORD_SIGNED", - "KEYWORD_LONG", - "KEYWORD_SHORT", - "KEYWORD_DOUBLE", - "KEYWORD_FLOAT", - "KEYWORD__BOOL", - "KEYWORD__COMPLEX", - "KEYWORD__IMAGINARY", - "KEYWORD_STATIC", - "KEYWORD_AUTO", - "KEYWORD_CONST", - "KEYWORD_EXTERN", - "KEYWORD_INLINE", - "KEYWORD_REGISTER", - "KEYWORD_RESTRICT", - "KEYWORD_VOLATILE", - "KEYWORD__THREAD_LOCAL", - "KEYWORD__ATOMIC", - "KEYWORD__NORETURN", - "KEYWORD_STRUCT", - "KEYWORD_UNION", - "KEYWORD_ENUM", - "KEYWORD_TYPEDEF", - "KEYWORD_DEFAULT", - "KEYWORD_BREAK", - "KEYWORD_RETURN", - "KEYWORD_SWITCH", - "KEYWORD_IF", - "KEYWORD_ELSE", - "KEYWORD_FOR", - "KEYWORD_WHILE", - "KEYWORD_CASE", - "KEYWORD_CONTINUE", - "KEYWORD_DO", - "KEYWORD_GOTO", - "KEYWORD_SIZEOF", - "KEYWORD__ALIGNAS", - "KEYWORD__ALIGNOF", - "KEYWORD__STATIC_ASSERT", - "KEYWORD__GENERIC", -}; - -CL_API_FUNCTION void CL_StringifyMessage(char *buff, int buff_size, CL_Message *msg) { - CL_SNPRINTF(buff, buff_size, "%s(%d,%d): %15s", msg->token.file, msg->token.line + 1, msg->token.column + 1, msg->string); -} - -CL_API_FUNCTION void CL_Stringify(char *buff, int buff_size, CL_Token *token) { - const char *token_kind = "UNKNOWN"; - if (token->kind < CL_COUNT) token_kind = CL_KindString[token->kind]; - CL_SNPRINTF(buff, buff_size, "%s(%d,%d): %15s %15.*s", token->file, token->line + 1, token->column + 1, token_kind, token->len, token->str); -} - -#define CL_SLL_QUEUE_ADD_MOD(f, l, n, next) \ - do { \ - (n)->next = 0; \ - if ((f) == 0) { \ - (f) = (l) = (n); \ - } \ - else { \ - (l) = (l)->next = (n); \ - } \ - } while (0) -#define CL_SLL_QUEUE_ADD(f, l, n) CL_SLL_QUEUE_ADD_MOD(f, l, n, next) - -#define CL__FORMAT(arena, string, result) \ - va_list args1, args2; \ - va_start(args1, string); \ - va_copy(args2, args1); \ - int len = CL_VSNPRINTF(0, 0, string, args2); \ - va_end(args2); \ - char *result = (char *)CL_Allocate((arena), len + 1); \ - CL_VSNPRINTF(result, len + 1, string, args1); \ - va_end(args1) - -CL_PRIVATE_FUNCTION void CL_ReportError(CL_Lexer *T, CL_Token *token, const char *string, ...) { - CL__FORMAT(T->arena, string, message_string); - CL_Message *result = (CL_Message *)CL_Allocate(T->arena, sizeof(CL_Message)); - CL_MemoryZero(result, sizeof(CL_Message)); - CL_SLL_QUEUE_ADD(T->first_message, T->last_message, result); - - result->string = (char *)string; - result->token = *token; - token->kind = CL_ERROR; - token->error = result; - T->errors += 1; -} diff --git a/src/build_tool/standalone_libraries/clexer.h b/src/build_tool/standalone_libraries/clexer.h deleted file mode 100644 index 47179ee..0000000 --- a/src/build_tool/standalone_libraries/clexer.h +++ /dev/null @@ -1,302 +0,0 @@ -#ifndef FIRST_CL_HEADER -#define FIRST_CL_HEADER - -#include -#include -#include - -#ifndef CL_API_FUNCTION - #ifdef __cplusplus - #define CL_API_FUNCTION extern "C" - #else - #define CL_API_FUNCTION - #endif -#endif - -#ifndef CL_INLINE - #ifndef _MSC_VER - #ifdef __cplusplus - #define CL_INLINE inline - #else - #define CL_INLINE - #endif - #else - #define CL_INLINE __forceinline - #endif -#endif - -#ifndef CL_Allocator -struct MA_Arena; - #define CL_Allocator MA_Arena * -#endif - -#ifndef AND_CL_STRING_TERMINATE_ON_NEW_LINE - #define AND_CL_STRING_TERMINATE_ON_NEW_LINE &&*T->stream != '\n' -#endif - -typedef enum CL_Kind { - CL_EOF, - CL_MUL, - CL_DIV, - CL_MOD, - CL_LEFTSHIFT, - CL_RIGHTSHIFT, - CL_ADD, - CL_SUB, - CL_EQUALS, - CL_LESSERTHEN, - CL_GREATERTHEN, - CL_LESSERTHEN_OR_EQUAL, - CL_GREATERTHEN_OR_EQUAL, - CL_NOTEQUALS, - CL_BITAND, - CL_BITOR, - CL_BITXOR, - CL_AND, - CL_OR, - CL_NEG, - CL_NOT, - CL_DECREMENT, - CL_INCREMENT, - CL_POSTDECREMENT, - CL_POSTINCREMENT, - CL_ASSIGN, - CL_DIVASSIGN, - CL_MULASSIGN, - CL_MODASSIGN, - CL_SUBASSIGN, - CL_ADDASSIGN, - CL_ANDASSIGN, - CL_ORASSIGN, - CL_XORASSIGN, - CL_LEFTSHIFTASSIGN, - CL_RIGHTSHIFTASSIGN, - CL_OPENPAREN, - CL_CLOSEPAREN, - CL_OPENBRACE, - CL_CLOSEBRACE, - CL_OPENBRACKET, - CL_CLOSEBRACKET, - CL_COMMA, - CL_MACRO_CONCAT, - CL_PREPROC_STRINGIFY, - CL_QUESTION, - CL_THREEDOTS, - CL_SEMICOLON, - CL_DOT, - CL_COLON, - CL_TAG, - CL_ARROW, - CL_EXPRSIZEOF, - CL_DOCCOMMENT, - CL_COMMENT, - CL_IDENTIFIER, - CL_STRINGLIT, - CL_CHARLIT, - CL_ERROR, - CL_FLOAT, - CL_INT, - CL_PREPROC_NULL, - CL_PREPROC_DEFINE, - CL_PREPROC_IFDEF, - CL_PREPROC_IFNDEF, - CL_PREPROC_INCLUDE, - CL_PREPROC_ENDIF, - CL_PREPROC_IF, - CL_PREPROC_PRAGMA, - CL_PREPROC_ERROR, - CL_PREPROC_ELSE, - CL_PREPROC_ELIF, - CL_PREPROC_UNDEF, - CL_KEYWORD_VOID, - CL_KEYWORD_INT, - CL_KEYWORD_CHAR, - CL_KEYWORD_UNSIGNED, - CL_KEYWORD_SIGNED, - CL_KEYWORD_LONG, - CL_KEYWORD_SHORT, - CL_KEYWORD_DOUBLE, - CL_KEYWORD_FLOAT, - CL_KEYWORD__BOOL, - CL_KEYWORD__COMPLEX, - CL_KEYWORD__IMAGINARY, - CL_KEYWORD_STATIC, - CL_KEYWORD_AUTO, - CL_KEYWORD_CONST, - CL_KEYWORD_EXTERN, - CL_KEYWORD_INLINE, - CL_KEYWORD_REGISTER, - CL_KEYWORD_RESTRICT, - CL_KEYWORD_VOLATILE, - CL_KEYWORD__THREAD_LOCAL, - CL_KEYWORD__ATOMIC, - CL_KEYWORD__NORETURN, - CL_KEYWORD_STRUCT, - CL_KEYWORD_UNION, - CL_KEYWORD_ENUM, - CL_KEYWORD_TYPEDEF, - CL_KEYWORD_DEFAULT, - CL_KEYWORD_BREAK, - CL_KEYWORD_RETURN, - CL_KEYWORD_SWITCH, - CL_KEYWORD_IF, - CL_KEYWORD_ELSE, - CL_KEYWORD_FOR, - CL_KEYWORD_WHILE, - CL_KEYWORD_CASE, - CL_KEYWORD_CONTINUE, - CL_KEYWORD_DO, - CL_KEYWORD_GOTO, - CL_KEYWORD_SIZEOF, - CL_KEYWORD__ALIGNAS, - CL_KEYWORD__ALIGNOF, - CL_KEYWORD__STATIC_ASSERT, - CL_KEYWORD__GENERIC, - CL_COUNT, -} CL_Kind; - -typedef enum CL_Fix { - CL_FIX_NONE, - CL_SUFFIX_U, - CL_SUFFIX_UL, - CL_SUFFIX_ULL, - CL_SUFFIX_L, - CL_SUFFIX_LL, - CL_SUFFIX_F, - CL_SUFFIX_FL, - CL_PREFIX_U8, - CL_PREFIX_U16, - CL_PREFIX_U32, - CL_PREFIX_L, -} CL_Fix; - -typedef struct CL_Token CL_Token; -struct CL_Token { - CL_Kind kind; - CL_Fix fix; - - bool is_hex : 1; - bool is_inside_macro : 1; - bool is_system_include : 1; - bool is_there_whitespace_before_token : 1; - - uint32_t id; - int len; - char *str; - - // Not storing line_begin like I would normally cause the user could - // override the line and file information using directives. - // On error need to do search if I want nice error context. - int line, column; - char *file; - - union { - double f64; - uint64_t u64; - char *intern; - char *string_literal; - struct CL_Message *error; - }; -}; - -typedef struct CL_Message CL_Message; -struct CL_Message { - CL_Message *next; - char *string; - CL_Token token; -}; - -typedef struct CL_Lexer CL_Lexer; -struct CL_Lexer { - CL_Message *first_message; - CL_Message *last_message; - int errors; - - char *stream; - char *stream_begin; - int line; - int column; - char *file; - bool inside_of_macro; - - // filters - bool skip_comments : 1; - bool skip_macros : 1; - bool select_includes : 1; - bool select_comments : 1; - bool select_macros : 1; - - CL_Allocator arena; -}; - -typedef struct CL_SearchPaths CL_SearchPaths; -struct CL_SearchPaths { - char **include_path; - int include_path_count; - - char **system_include_path; - int system_include_path_count; - - char *file_begin_to_ignore; -}; - -CL_API_FUNCTION CL_Token CL_Next(CL_Lexer *T); -CL_API_FUNCTION CL_Lexer CL_Begin(CL_Allocator arena, char *stream, char *filename); -CL_API_FUNCTION char *CL_ResolveFilepath(CL_Allocator arena, CL_SearchPaths *search_paths, char *filename, char *parent_file, bool is_system_include); -CL_API_FUNCTION void CL_StringifyMessage(char *buff, int buff_size, CL_Message *msg); -CL_API_FUNCTION void CL_Stringify(char *buff, int buff_size, CL_Token *token); - -extern const char *CL_FixString[]; -extern const char *CL_KindString[]; - -CL_INLINE int CL_StringLength(char *string) { - int len = 0; - while (*string++ != 0) len++; - return len; -} - -CL_INLINE bool CL_StringsAreEqual(char *a, int64_t alen, const char *b, int64_t blen) { - if (alen != blen) return false; - for (int i = 0; i < alen; i += 1) { - if (a[i] != b[i]) return false; - } - return true; -} - -CL_INLINE bool CL_IsIdentifier(CL_Token *token, char *str) { - int str_len = CL_StringLength(str); - bool result = token->kind == CL_IDENTIFIER && CL_StringsAreEqual(token->str, token->len, str, str_len); - return result; -} - -CL_INLINE bool CL_IsAssign(CL_Kind op) { - bool result = op >= CL_ASSIGN && op <= CL_RIGHTSHIFTASSIGN; - return result; -} - -CL_INLINE bool CL_IsKeywordType(CL_Kind op) { - bool result = op >= CL_KEYWORD_VOID && op <= CL_KEYWORD__IMAGINARY; - return result; -} - -CL_INLINE bool CL_IsKeywordTypeOrSpec(CL_Kind op) { - bool result = op >= CL_KEYWORD_VOID && op <= CL_KEYWORD_TYPEDEF; - return result; -} - -CL_INLINE bool CL_IsMacro(CL_Kind kind) { - bool result = kind >= CL_PREPROC_DEFINE && kind <= CL_PREPROC_UNDEF; - return result; -} - -CL_INLINE bool CL_IsKeyword(CL_Kind kind) { - bool result = kind >= CL_KEYWORD_VOID && kind <= CL_KEYWORD__GENERIC; - return result; -} - -CL_INLINE bool CL_IsKeywordOrIdent(CL_Kind kind) { - bool result = CL_IsKeyword(kind) || kind == CL_IDENTIFIER; - return result; -} - -#endif \ No newline at end of file diff --git a/src/build_tool/standalone_libraries/defer.hpp b/src/build_tool/standalone_libraries/defer.hpp deleted file mode 100644 index 463ec4a..0000000 --- a/src/build_tool/standalone_libraries/defer.hpp +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef FIRST_DEFER_HEADER -#define FIRST_DEFER_HEADER - -template -struct DEFER_ExitScope { - T lambda; - DEFER_ExitScope(T lambda) : lambda(lambda) {} - ~DEFER_ExitScope() { lambda(); } - DEFER_ExitScope(const DEFER_ExitScope &i) : lambda(i.lambda){}; - - private: - DEFER_ExitScope &operator=(const DEFER_ExitScope &); -}; - -class DEFER_ExitScopeHelp { - public: - template - DEFER_ExitScope operator+(T t) { return t; } -}; - -#define DEFER_CONCAT_INTERNAL(x, y) x##y -#define DEFER_CONCAT(x, y) DEFER_CONCAT_INTERNAL(x, y) -#define defer const auto DEFER_CONCAT(defer__, __LINE__) = DEFER_ExitScopeHelp() + [&]() - -#endif \ No newline at end of file diff --git a/src/build_tool/standalone_libraries/hash.c b/src/build_tool/standalone_libraries/hash.c deleted file mode 100644 index 8b44f00..0000000 --- a/src/build_tool/standalone_libraries/hash.c +++ /dev/null @@ -1,53 +0,0 @@ -#include "hash.h" - -// FNV HASH (1a?) -HASH_API_FUNCTION uint64_t HashBytes(void *data, uint64_t size) { - uint8_t *data8 = (uint8_t *)data; - uint64_t hash = (uint64_t)14695981039346656037ULL; - for (uint64_t i = 0; i < size; i++) { - hash = hash ^ (uint64_t)(data8[i]); - hash = hash * (uint64_t)1099511628211ULL; - } - return hash; -} - -HASH_API_FUNCTION RandomSeed MakeRandomSeed(uint64_t value) { - RandomSeed result; - result.a = value; - return result; -} - -HASH_API_FUNCTION uint64_t GetRandomU64(RandomSeed *state) { - uint64_t x = state->a; - x ^= x << 13; - x ^= x >> 7; - x ^= x << 17; - return state->a = x; -} - -HASH_API_FUNCTION int GetRandomRangeI(RandomSeed *seed, int first, int last_included) { - uint64_t random = GetRandomU64(seed); - int range = (last_included - first + 1); - int mapped = random % range; - int result = mapped + first; - return result; -} - -HASH_API_FUNCTION double GetRandomNormal(RandomSeed *series) { - uint64_t rnd = GetRandomU64(series); - double result = (double)rnd / (double)UINT64_MAX; - return result; -} - -HASH_API_FUNCTION double GetRandomNormalRange(RandomSeed *seed, double min, double max) { - double value = GetRandomNormal(seed); - double result = value * (max - min) + min; - return result; -} - -HASH_API_FUNCTION uint64_t HashMix(uint64_t x, uint64_t y) { - x ^= y; - x *= 0xff51afd7ed558ccd; - x ^= x >> 32; - return x; -} diff --git a/src/build_tool/standalone_libraries/hash.h b/src/build_tool/standalone_libraries/hash.h deleted file mode 100644 index 073a9d2..0000000 --- a/src/build_tool/standalone_libraries/hash.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef FIRST_HASH_HEADER -#define FIRST_HASH_HEADER -#include - -#ifndef HASH_API_FUNCTION - #ifdef __cplusplus - #define HASH_API_FUNCTION extern "C" - #else - #define HASH_API_FUNCTION - #endif -#endif - -typedef struct RandomSeed RandomSeed; -struct RandomSeed { - uint64_t a; -}; - -HASH_API_FUNCTION uint64_t HashBytes(void *data, uint64_t size); -HASH_API_FUNCTION RandomSeed MakeRandomSeed(uint64_t value); -HASH_API_FUNCTION uint64_t GetRandomU64(RandomSeed *state); -HASH_API_FUNCTION int GetRandomRangeI(RandomSeed *seed, int first, int last_included); -HASH_API_FUNCTION double GetRandomNormal(RandomSeed *series); -HASH_API_FUNCTION double GetRandomNormalRange(RandomSeed *seed, double min, double max); -HASH_API_FUNCTION uint64_t HashMix(uint64_t x, uint64_t y); - -#define WRAP_AROUND_POWER_OF_2(x, pow2) (((x) & ((pow2)-1llu))) -static inline float GetRandomNormalF(RandomSeed *series) { return (float)GetRandomNormal(series); } -#endif \ No newline at end of file diff --git a/src/build_tool/standalone_libraries/io.c b/src/build_tool/standalone_libraries/io.c deleted file mode 100644 index 6f194ab..0000000 --- a/src/build_tool/standalone_libraries/io.c +++ /dev/null @@ -1,236 +0,0 @@ -#include "io.h" -#include - -#ifndef IO_SNPRINTF - #include - #define IO_SNPRINTF snprintf -#endif - -#ifndef IO_VSNPRINTF - #include - #define IO_VSNPRINTF vsnprintf -#endif - -#ifndef IO_ALLOCATE - #include - #define IO_ALLOCATE(x) malloc(x) - #define IO_FREE(x) free(x) -#endif - -#ifndef IO_StaticFunc - #if defined(__GNUC__) || defined(__clang__) - #define IO_StaticFunc __attribute__((unused)) static - #else - #define IO_StaticFunc static - #endif -#endif - -IO_StaticFunc int IO_Strlen(char *string) { - int len = 0; - while (*string++ != 0) len++; - return len; -} - -IO_THREAD_LOCAL void (*IO_User_OutputMessage)(int kind, const char *file, int line, char *str, int len); - -IO_API bool IO__FatalErrorf(const char *file, int line, const char *msg, ...) { - va_list args1; - va_list args2; - char buff[2048]; - - va_start(args1, msg); - va_copy(args2, args1); - int size = IO_VSNPRINTF(buff, sizeof(buff), msg, args2); - va_end(args2); - - char *new_buffer = 0; - char *user_message = buff; - if (size >= sizeof(buff)) { - size += 4; - new_buffer = (char *)IO_ALLOCATE(size); - IO_VSNPRINTF(new_buffer, size, msg, args1); - user_message = new_buffer; - } - va_end(args1); - - IO_ErrorResult ret = IO_ErrorResult_Continue; - { - char buff2[2048]; - char *result = buff2; - char *b = 0; - int size2 = IO_SNPRINTF(buff2, sizeof(buff2), "%s(%d): error: %s \n", file, line, user_message); - if (size2 >= sizeof(buff2)) { - size2 += 4; - b = (char *)IO_ALLOCATE(size2); - size2 = IO_SNPRINTF(b, size2, "%s(%d): error: %s \n", file, line, user_message); - result = b; - } - - ret = IO_OutputError(result, size2); - if (ret == IO_ErrorResult_Exit) { - IO_Exit(1); - } - - if (b) { - IO_FREE(b); - } - } - - if (new_buffer) { - IO_FREE(new_buffer); - } - - return ret == IO_ErrorResult_Break; -} - -IO_API void IO__Printf(int kind, const char *file, int line, const char *msg, ...) { - // First try to use a static buffer. That can fail because the message - // can be bigger then the buffer. Allocate enough memory to fit in that - // case. - va_list args1; - va_list args2; - char buff[2048]; - - va_start(args1, msg); - va_copy(args2, args1); - int size = IO_VSNPRINTF(buff, sizeof(buff), msg, args2); - va_end(args2); - - char *new_buffer = 0; - char *result = buff; - if (size >= sizeof(buff)) { - size += 4; - new_buffer = (char *)IO_ALLOCATE(size); - IO_VSNPRINTF(new_buffer, size, msg, args1); - result = new_buffer; - } - va_end(args1); - - if (IO_User_OutputMessage) { - IO_User_OutputMessage(kind, file, line, result, size); - } else { - IO_OutputMessage(result, size); - } - - if (new_buffer) { - IO_FREE(new_buffer); - } -} - -IO_API bool IO__FatalError(const char *msg) { - int len = IO_Strlen((char *)msg); - IO_ErrorResult result = IO_OutputError((char *)msg, len); - if (result == IO_ErrorResult_Exit) { - IO_Exit(1); - } - return result == IO_ErrorResult_Break; -} - -IO_API void IO_Print(int kind, const char *file, int line, char *msg, int len) { - if (IO_User_OutputMessage) { - IO_User_OutputMessage(kind, file, line, msg, len); - } else { - IO_OutputMessage(msg, len); - } -} -#ifdef _WIN32 - #ifndef NOMINMAX - #define NOMINMAX - #endif - #ifndef WIN32_LEAN_AND_MEAN - #define WIN32_LEAN_AND_MEAN - #endif - #include - - #pragma comment(lib, "user32") - - #include - -IO_API bool IO_IsDebuggerPresent(void) { - return IsDebuggerPresent(); -} - -IO_API void IO_OutputMessage(char *str, int len) { - if (IsDebuggerPresent()) { - OutputDebugStringA(str); - } - printf("%.*s", len, str); - fflush(stdout); -} - -IO_API IO_ErrorResult IO_OutputError(char *str, int len) { - IO_ErrorResult result = IO_ErrorResult_Continue; - IO_OutputMessage(str, len); - - char *msg = str; - if (str[len] != 0) { - msg = (char *)IO_ALLOCATE(len + 1); - for (int i = 0; i < len; i += 1) msg[i] = str[i]; - msg[len] = 0; - } - - OutputDebugStringA(msg); - if (!IsDebuggerPresent()) { - - // Limit size of error output message - char tmp = 0; - if (len > 4096) { - tmp = str[4096]; - str[4096] = 0; - } - - MessageBoxA(0, msg, "Error!", 0); - - if (tmp != 0) { - str[4096] = tmp; - } - - result = IO_ErrorResult_Exit; - } else { - result = IO_ErrorResult_Break; - } - - if (msg != str) { - IO_FREE(msg); - } - - return result; -} - -IO_API void IO_Exit(int error_code) { - ExitProcess(error_code); -} -#elif __linux__ || __unix__ || __APPLE__ - #include -IO_API IO_ErrorResult IO_OutputError(char *str, int len) { - fprintf(stderr, "%.*s", len, str); - return IO_ErrorResult_Exit; -} - -IO_API void IO_OutputMessage(char *str, int len) { - fprintf(stdout, "%.*s", len, str); -} - -IO_API void IO_Exit(int error_code) { - exit(error_code); -} - -IO_API bool IO_IsDebuggerPresent(void) { - return false; -} -#else -IO_API IO_ErrorResult IO_OutputError(char *str, int len) { - return IO_ErrorResult_Exit; -} - -IO_API void IO_OutputMessage(char *str, int len) { -} - -IO_API void IO_Exit(int error_code) { -} - -IO_API bool IO_IsDebuggerPresent(void) { - return false; -} - -#endif // LIBC diff --git a/src/build_tool/standalone_libraries/io.h b/src/build_tool/standalone_libraries/io.h deleted file mode 100644 index 70f8bb8..0000000 --- a/src/build_tool/standalone_libraries/io.h +++ /dev/null @@ -1,108 +0,0 @@ -#ifndef FIRST_IO_HEADER -#define FIRST_IO_HEADER -#include - -#ifndef IO_API - #ifdef __cplusplus - #define IO_API extern "C" - #else - #define IO_API - #endif -#endif - -typedef enum IO_ErrorResult { - IO_ErrorResult_Continue, - IO_ErrorResult_Break, - IO_ErrorResult_Exit, -} IO_ErrorResult; - -#if defined(_MSC_VER) - #define IO_DebugBreak() (__debugbreak(), 0) -#else - #define IO_DebugBreak() (__builtin_trap(), 0) -#endif - -#ifndef IO_THREAD_LOCAL - #if defined(__cplusplus) && __cplusplus >= 201103L - #define IO_THREAD_LOCAL thread_local - #elif defined(__GNUC__) - #define IO_THREAD_LOCAL __thread - #elif defined(_MSC_VER) - #define IO_THREAD_LOCAL __declspec(thread) - #elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && !defined(__STDC_NO_THREADS__) - #define IO_THREAD_LOCAL _Thread_local - #elif defined(__TINYC__) - #define IO_THREAD_LOCAL _Thread_local - #else - #error Couldnt figure out thread local, needs to be provided manually - #endif -#endif - -#if defined(__has_attribute) - #if __has_attribute(format) - #define IO__PrintfFormat(fmt, va) __attribute__((format(printf, fmt, va))) - #endif -#endif - -#ifndef IO__PrintfFormat - #define IO__PrintfFormat(fmt, va) -#endif - -typedef void IO_MessageHandler(int kind, const char *file, int line, char *str, int len); -extern IO_THREAD_LOCAL void (*IO_User_OutputMessage)(int kind, const char *file, int line, char *str, int len); - -#define IO__STRINGIFY(x) #x -#define IO__TOSTRING(x) IO__STRINGIFY(x) -#define IO_LINE IO__TOSTRING(__LINE__) - -#define IO_Assert(x) !(x) && IO__FatalError((__FILE__ "(" IO_LINE "): " \ - "error: " #x "\n")) && \ - IO_DebugBreak() -#define IO_FatalErrorf(...) \ - do { \ - bool result = IO__FatalErrorf(__FILE__, __LINE__, __VA_ARGS__); \ - if (result) IO_DebugBreak(); \ - } while (0) -#define IO_FatalError(...) \ - do { \ - bool result = IO__FatalError(__FILE__ "(" IO_LINE "): error - " __VA_ARGS__); \ - if (result) IO_DebugBreak(); \ - } while (0) -#define IO_Assertf(x, ...) \ - do { \ - if (!(x)) { \ - bool result = IO__FatalErrorf(__FILE__, __LINE__, __VA_ARGS__); \ - if (result) IO_DebugBreak(); \ - } \ - } while (0) - -#define IO_InvalidElseIf(c) \ - else if (c) { \ - IO_InvalidCodepath(); \ - } -#define IO_InvalidElse() \ - else { \ - IO_InvalidCodepath(); \ - } -#define IO_InvalidCodepath() IO_FatalError("This codepath is invalid") -#define IO_InvalidDefaultCase() \ -default: { \ - IO_FatalError("Entered invalid switch statement case"); \ -} -#define IO_Todo() IO_FatalError("This codepath is not implemented yet") - -IO_API bool IO__FatalErrorf(const char *file, int line, const char *msg, ...) IO__PrintfFormat(3, 4); -IO_API void IO__Printf(int kind, const char *file, int line, const char *msg, ...) IO__PrintfFormat(4, 5); -IO_API bool IO__FatalError(const char *msg); -IO_API void IO_Print(int kind, const char *file, int line, char *msg, int len); -IO_API void IO_OutputMessage(char *str, int len); -IO_API IO_ErrorResult IO_OutputError(char *str, int len); -IO_API void IO_Exit(int error_code); -IO_API bool IO_IsDebuggerPresent(void); - -static const int IO_KindPrintf = 1; -static const int IO_KindWarningf = 2; - -#define IO_Printf(...) IO__Printf(IO_KindPrintf, __FILE__, __LINE__, __VA_ARGS__) -#define IO_Warningf(...) IO__Printf(IO_KindWarningf, __FILE__, __LINE__, __VA_ARGS__) -#endif \ No newline at end of file diff --git a/src/build_tool/standalone_libraries/linked_list.h b/src/build_tool/standalone_libraries/linked_list.h deleted file mode 100644 index 7ae9625..0000000 --- a/src/build_tool/standalone_libraries/linked_list.h +++ /dev/null @@ -1,119 +0,0 @@ -#ifndef FIRST_LL_HEADER -#define FIRST_LL_HEADER -#define SLL_QUEUE_ADD_MOD(f, l, n, next) \ - do { \ - (n)->next = 0; \ - if ((f) == 0) { \ - (f) = (l) = (n); \ - } else { \ - (l) = (l)->next = (n); \ - } \ - } while (0) -#define SLL_QUEUE_ADD(f, l, n) SLL_QUEUE_ADD_MOD(f, l, n, next) - -#define SLL_QUEUE_POP_FIRST_MOD(f, l, next) \ - do { \ - if ((f) == (l)) { \ - (f) = (l) = 0; \ - } else { \ - (f) = (f)->next; \ - } \ - } while (0) -#define SLL_QUEUE_POP_FIRST(f, l) SLL_QUEUE_POP_FIRST_MOD(f, l, next) - -#define SLL_STACK_ADD_MOD(stack_base, new_stack_base, next) \ - do { \ - (new_stack_base)->next = (stack_base); \ - (stack_base) = (new_stack_base); \ - } while (0) -#define SLL_STACK_ADD(stack_base, new_stack_base) \ - SLL_STACK_ADD_MOD(stack_base, new_stack_base, next) - -#define SLL_STACK_POP_AND_STORE(stack_base, out_node) \ - do { \ - if (stack_base) { \ - (out_node) = (stack_base); \ - (stack_base) = (stack_base)->next; \ - (out_node)->next = 0; \ - } \ - } while (0) - -#define DLL_QUEUE_ADD_MOD(f, l, node, next, prev) \ - do { \ - if ((f) == 0) { \ - (f) = (l) = (node); \ - (node)->prev = 0; \ - (node)->next = 0; \ - } else { \ - (l)->next = (node); \ - (node)->prev = (l); \ - (node)->next = 0; \ - (l) = (node); \ - } \ - } while (0) -#define DLL_QUEUE_ADD(f, l, node) DLL_QUEUE_ADD_MOD(f, l, node, next, prev) -#define DLL_QUEUE_ADD_FRONT(f, l, node) DLL_QUEUE_ADD_MOD(l, f, node, prev, next) -#define DLL_QUEUE_REMOVE_MOD(first, last, node, next, prev) \ - do { \ - if ((first) == (last)) { \ - (first) = (last) = 0; \ - } else if ((last) == (node)) { \ - (last) = (last)->prev; \ - (last)->next = 0; \ - } else if ((first) == (node)) { \ - (first) = (first)->next; \ - (first)->prev = 0; \ - } else { \ - (node)->prev->next = (node)->next; \ - (node)->next->prev = (node)->prev; \ - } \ - if (node) { \ - (node)->prev = 0; \ - (node)->next = 0; \ - } \ - } while (0) -#define DLL_QUEUE_REMOVE(first, last, node) DLL_QUEUE_REMOVE_MOD(first, last, node, next, prev) - -#define DLL_STACK_ADD_MOD(first, node, next, prev) \ - do { \ - (node)->next = (first); \ - if ((first)) \ - (first)->prev = (node); \ - (first) = (node); \ - (node)->prev = 0; \ - } while (0) -#define DLL_STACK_ADD(first, node) DLL_STACK_ADD_MOD(first, node, next, prev) -#define DLL_STACK_REMOVE_MOD(first, node, next, prev) \ - do { \ - if ((node) == (first)) { \ - (first) = (first)->next; \ - if ((first)) \ - (first)->prev = 0; \ - } else { \ - (node)->prev->next = (node)->next; \ - if ((node)->next) \ - (node)->next->prev = (node)->prev; \ - } \ - if (node) { \ - (node)->prev = 0; \ - (node)->next = 0; \ - } \ - } while (0) -#define DLL_STACK_REMOVE(first, node) DLL_STACK_REMOVE_MOD(first, node, next, prev) - -#define DLL_INSERT_NEXT_MOD(base, new, next, prev) \ - do { \ - if ((base) == 0) { \ - (base) = (new); \ - (new)->next = 0; \ - (new)->prev = 0; \ - } else { \ - (new)->next = (base)->next; \ - (base)->next = (new); \ - (new)->prev = (base); \ - if ((new)->next) (new)->next->prev = (new); \ - } \ - } while (0) -#define DLL_INSERT_NEXT(base, new) DLL_INSERT_NEXT_MOD(base, new, next, prev) -#define DLL_INSERT_PREV(base, new) DLL_INSERT_NEXT_MOD(base, new, next, prev) -#endif \ No newline at end of file diff --git a/src/build_tool/standalone_libraries/load_library.c b/src/build_tool/standalone_libraries/load_library.c deleted file mode 100644 index eda26be..0000000 --- a/src/build_tool/standalone_libraries/load_library.c +++ /dev/null @@ -1,26 +0,0 @@ -#include "load_library.h" -#ifdef _WIN32 - #ifndef NOMINMAX - #define NOMINMAX - #endif - #ifndef WIN32_LEAN_AND_MEAN - #define WIN32_LEAN_AND_MEAN - #endif - #include - -LIB_Library LIB_LoadLibrary(char *str) { - HMODULE module = LoadLibraryA(str); - return (LIB_Library)module; -} - -void *LIB_LoadSymbol(LIB_Library lib, char *symbol) { - void *result = (void *)GetProcAddress((HMODULE)lib, symbol); - return result; -} - -bool LIB_UnloadLibrary(LIB_Library lib) { - BOOL result = FreeLibrary((HMODULE)lib); - if (result == 0) return false; - return true; -} -#endif // _WIN32 diff --git a/src/build_tool/standalone_libraries/load_library.h b/src/build_tool/standalone_libraries/load_library.h deleted file mode 100644 index 3c98bbd..0000000 --- a/src/build_tool/standalone_libraries/load_library.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef FIRST_LIB_HEADER -#define FIRST_LIB_HEADER -typedef void *LIB_Library; - -LIB_Library LIB_LoadLibrary(char *str); -void *LIB_LoadSymbol(LIB_Library lib, char *symbol); -bool LIB_UnloadLibrary(LIB_Library lib); - -#ifndef LIB_EXPORT - #define LIB_EXPORT __declspec(dllexport) -#endif -#endif \ No newline at end of file diff --git a/src/build_tool/standalone_libraries/multimedia.c b/src/build_tool/standalone_libraries/multimedia.c deleted file mode 100644 index 1b49cc1..0000000 --- a/src/build_tool/standalone_libraries/multimedia.c +++ /dev/null @@ -1,1740 +0,0 @@ -#include "multimedia.h" - -#ifndef MU_StaticFunc - #if defined(__GNUC__) || defined(__clang__) - #define MU_StaticFunc __attribute__((unused)) static - #else - #define MU_StaticFunc static - #endif -#endif - -#ifndef MU_PRIVATE_VAR - #define MU_PRIVATE_VAR MU_StaticFunc -#endif - -#ifdef _WIN32 - #ifndef NOMINMAX - #define NOMINMAX - #endif - #ifndef WIN32_LEAN_AND_MEAN - #define WIN32_LEAN_AND_MEAN - #endif - #include - #include // for handling dropped files - - #define INITGUID - #define CINTERFACE - #define COBJMACROS - #define CONST_VTABLE - #include - #include - #include - #include - - // - // Automatically linking with the libraries - // - #pragma comment(lib, "gdi32.lib") - #pragma comment(lib, "user32.lib") - #pragma comment(lib, "shell32.lib") // For handling dropping files into the app -#endif -MU_StaticFunc void *MU_PushSize(MU_Arena *ar, size_t size); -MU_StaticFunc MU_UTF32Result MU_UTF16ToUTF32(uint16_t *c, int max_advance); -MU_StaticFunc MU_UTF8Result MU_UTF32ToUTF8(uint32_t codepoint); -MU_StaticFunc int64_t MU_CreateCharFromWidechar(char *buffer, int64_t buffer_size, wchar_t *in, int64_t inlen); -MU_StaticFunc void MU_WIN32_UpdateFocusedWindowBasedOnHandle(MU_Context *mu, HWND handle); -MU_StaticFunc void MU_WIN32_UpdateFocusedWindow(MU_Context *mu); -MU_StaticFunc void MU_Win32_GetWindowSize(HWND window, int *x, int *y); -MU_StaticFunc void MU_WIN32_GetWindowPos(HWND window, int *x, int *y); -MU_StaticFunc MU_Int2 MU_WIN32_GetMousePosition(HWND window); -MU_StaticFunc MU_Int2 MU_WIN32_GetMousePositionInverted(HWND window, int y); -MU_StaticFunc void MU_WIN32_CreateCanvas(MU_Window *window); -MU_StaticFunc void MU_WIN32_DestroyCanvas(MU_Window *window); -MU_StaticFunc void MU_WIN32_DrawCanvas(MU_Window *window); -MU_StaticFunc void MU__MemoryCopy(void *dst, const void *src, size_t size); -MU_StaticFunc void MU_PushDroppedFile(MU_Context *mu, MU_Window *window, char *str, int size); -MU_StaticFunc void MU_UpdateWindowState(MU_Window *window); -MU_StaticFunc int MU__AreStringsEqual(const char *src, const char *dst, size_t dstlen); -MU_StaticFunc void *MU_Win32_GLGetWindowProcAddressForGlad(const char *proc); -MU_StaticFunc void MU_WIN32_GetWGLFunctions(MU_Context *mu); -MU_StaticFunc void MU_WIN32_TryToInitGLContextForWindow(MU_Context *mu, MU_Win32_Window *w32_window); -MU_StaticFunc void MU_WIN32_DeinitSound(MU_Context *mu); -MU_StaticFunc void MU_WIN32_LoadCOM(MU_Context *mu); -MU_StaticFunc DWORD MU_WIN32_SoundThread(void *parameter); -MU_StaticFunc void MU_WIN32_InitWasapi(MU_Context *mu); - -#ifndef MU_GL_ENABLE_MULTISAMPLING - #define MU_GL_ENABLE_MULTISAMPLING 1 -#endif - -#ifndef MU_GL_BUILD_DEBUG - #define MU_GL_BUILD_DEBUG 1 -#endif - -#ifndef MU_ASSERT_CODE - #define MU_ASSERT_CODE(x) x -#endif - -#ifndef MU_ASSERT - #include - #define MU_ASSERT(x) assert(x) -#endif - -/* Quake uses this to sleep when user is not interacting with app - void SleepUntilInput (int time) - { - MsgWaitForMultipleObjects(1, &tevent, FALSE, time, QS_ALLINPUT); - } - - if ((cl.paused && (!ActiveApp && !DDActive)) || Minimized || block_drawing) - { - SleepUntilInput (PAUSE_SLEEP); - scr_skipupdate = 1; // no point in bothering to draw - } - else if (!ActiveApp && !DDActive) - { - SleepUntilInput (NOT_FOCUS_SLEEP); - } - */ -// @! Add native handle to MU_Context for Directx 11 initialize -// @! Add option to manually blit, some manual blit param and manual blit function -// @! Add ram info? https://learn.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-globalmemorystatusex -// @! Maybe make the library friendly to people who dont use debuggers -// @! Set window title -// @! Good defaults for multiple windows ?? - -struct MU_UTF32Result { - uint32_t out_str; - int advance; - int error; -}; - -struct MU_UTF8Result { - char out_str[4]; - int len; - int error; -}; - -#define MU_ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) -#define MU_STACK_ADD_MOD(stack_base, new_stack_base, next) \ - do { \ - (new_stack_base)->next = (stack_base); \ - (stack_base) = (new_stack_base); \ - } while (0) -#define MU_STACK_ADD(stack_base, new_stack_base) \ - MU_STACK_ADD_MOD(stack_base, new_stack_base, next) - -MU_API void MU_Quit(MU_Context *mu) { - mu->quit = true; -} - -MU_API void MU_DefaultSoundCallback(MU_Context *mu, uint16_t *buffer, uint32_t samples_to_fill) { -} - -MU_INLINE void MU__WriteChar8(MU_Window *window, char *c, int len) { - if (window->user_text8_count + len < MU_ARRAY_SIZE(window->user_text8)) { - for (int i = 0; i < len; i += 1) { - window->user_text8[window->user_text8_count++] = c[i]; - } - } -} - -MU_INLINE void MU__WriteChar32(MU_Window *window, uint32_t c) { - if (window->user_text32_count + 1 < MU_ARRAY_SIZE(window->user_text32)) { - window->user_text32[window->user_text32_count++] = c; - } -} - -MU_INLINE void MU__KeyDown(MU_Window *window, MU_Key key) { - if (window->key[key].down == false) - window->key[key].press = true; - window->key[key].down = true; - window->key[key].raw_press = true; -} - -MU_INLINE void MU__ZeroMemory(void *p, size_t size) { - uint8_t *p8 = (uint8_t *)p; - for (size_t i = 0; i < size; i += 1) { - p8[i] = 0; - } -} - -MU_INLINE size_t MU__GetAlignOffset(size_t size, size_t align) { - size_t mask = align - 1; - size_t val = size & mask; - if (val) { - val = align - val; - } - return val; -} - -MU_INLINE void MU__KeyUP(MU_Window *window, MU_Key key) { - if (window->key[key].down == true) - window->key[key].unpress = true; - window->key[key].down = false; -} - -MU_INLINE bool MU_DoesSizeFit(MU_Arena *ar, size_t size) { - const size_t alignment = 16; - size_t align = MU__GetAlignOffset((uintptr_t)ar->memory + ar->len, alignment); - size_t cursor = ar->len + align; - bool result = cursor + size <= ar->cap; - return result; -} - -#define MU_PUSH_STRUCT(mu, T) (T *)MU_PushSize(mu, sizeof(T)) -MU_StaticFunc void *MU_PushSize(MU_Arena *ar, size_t size) { - const size_t alignment = 16; - - ar->len += MU__GetAlignOffset((uintptr_t)ar->memory + ar->len, alignment); - if (ar->len + size > ar->cap) { - MU_ASSERT(!"MU_Context has not enough memory for what you are trying to do!"); - } - - void *result = (void *)(ar->memory + ar->len); - ar->len += size; - MU_ASSERT(ar->len < ar->cap); - MU__ZeroMemory(result, size); - return result; -} - -MU_StaticFunc MU_UTF32Result MU_UTF16ToUTF32(uint16_t *c, int max_advance) { - MU_UTF32Result result; - MU__ZeroMemory(&result, sizeof(result)); - if (max_advance >= 1) { - result.advance = 1; - result.out_str = c[0]; - if (c[0] >= 0xD800 && c[0] <= 0xDBFF && c[1] >= 0xDC00 && c[1] <= 0xDFFF) { - if (max_advance >= 2) { - result.out_str = 0x10000; - result.out_str += (uint32_t)(c[0] & 0x03FF) << 10u | (c[1] & 0x03FF); - result.advance = 2; - } - else - result.error = 2; - } - } - else { - result.error = 1; - } - return result; -} - -MU_StaticFunc MU_UTF8Result MU_UTF32ToUTF8(uint32_t codepoint) { - MU_UTF8Result result; - MU__ZeroMemory(&result, sizeof(result)); - if (codepoint <= 0x7F) { - result.len = 1; - result.out_str[0] = (char)codepoint; - } - else if (codepoint <= 0x7FF) { - result.len = 2; - result.out_str[0] = 0xc0 | (0x1f & (codepoint >> 6)); - result.out_str[1] = 0x80 | (0x3f & codepoint); - } - else if (codepoint <= 0xFFFF) { // 16 bit word - result.len = 3; - result.out_str[0] = 0xe0 | (0xf & (codepoint >> 12)); // 4 bits - result.out_str[1] = 0x80 | (0x3f & (codepoint >> 6)); // 6 bits - result.out_str[2] = 0x80 | (0x3f & codepoint); // 6 bits - } - else if (codepoint <= 0x10FFFF) { // 21 bit word - result.len = 4; - result.out_str[0] = 0xf0 | (0x7 & (codepoint >> 18)); // 3 bits - result.out_str[1] = 0x80 | (0x3f & (codepoint >> 12)); // 6 bits - result.out_str[2] = 0x80 | (0x3f & (codepoint >> 6)); // 6 bits - result.out_str[3] = 0x80 | (0x3f & codepoint); // 6 bits - } - else { - result.error = true; - } - - return result; -} - -// @warning: this function is a little different from usual, returns -1 on decode errors -MU_StaticFunc int64_t MU_CreateCharFromWidechar(char *buffer, int64_t buffer_size, wchar_t *in, int64_t inlen) { - int64_t outlen = 0; - for (int64_t i = 0; i < inlen && in[i] != 0;) { - MU_UTF32Result decode = MU_UTF16ToUTF32((uint16_t *)(in + i), (int)(inlen - i)); - if (!decode.error) { - i += decode.advance; - MU_UTF8Result encode = MU_UTF32ToUTF8(decode.out_str); - if (!encode.error) { - for (int64_t j = 0; j < encode.len; j++) { - if (outlen >= buffer_size) { - outlen = -1; - goto failed_to_decode; - } - buffer[outlen++] = encode.out_str[j]; - } - } - else { - outlen = -1; - goto failed_to_decode; - } - } - else { - outlen = -1; - goto failed_to_decode; - } - } - - buffer[outlen] = 0; -failed_to_decode:; - return outlen; -} - -#ifdef _WIN32 - #define MU_DEFAULT_MEMORY_SIZE (1024 * 4) - -// Typedefines for the COM functions which are going to be loaded currently only required for sound -typedef HRESULT CoCreateInstanceFunction(REFCLSID rclsid, LPUNKNOWN *pUnkOuter, DWORD dwClsContext, REFIID riid, LPVOID *ppv); -typedef HRESULT CoInitializeExFunction(LPVOID pvReserved, DWORD dwCoInit); - -struct MU_Win32 { - WNDCLASSW wc; - bool good_scheduling; - MU_glGetProcAddress *wgl_get_proc_address; - HMODULE opengl32; - - HCURSOR cursor_hand; - HCURSOR cursor_arrow; - - // Sound - IMMDevice *device; - IAudioClient *audio_client; - IMMDeviceEnumerator *device_enum; - IAudioRenderClient *audio_render_client; - - uint32_t buffer_frame_count; - // IAudioCaptureClient *audio_capture_client; - - // Pointers to the functions from the dll - CoCreateInstanceFunction *CoCreateInstanceFunctionPointer; - CoInitializeExFunction *CoInitializeExFunctionPointer; -}; - -struct MU_Win32_Window { - HDC handle_dc; - HDC canvas_dc; - HBITMAP canvas_dib; - - // for fullscreen - WINDOWPLACEMENT prev_placement; - DWORD style; -}; - -MU_API double MU_GetTime(void) { - static int64_t counts_per_second; - if (counts_per_second == 0) { - LARGE_INTEGER freq; - QueryPerformanceFrequency(&freq); - counts_per_second = freq.QuadPart; - } - - LARGE_INTEGER time; - QueryPerformanceCounter(&time); - double result = (double)time.QuadPart / (double)counts_per_second; - return result; -} - -MU_StaticFunc void MU_WIN32_UpdateFocusedWindowBasedOnHandle(MU_Context *mu, HWND handle) { - if (mu->all_windows == 0) return; - for (MU_Window *it = mu->all_windows; it; it = it->next) { - if (it->handle == handle) { - mu->window = it; - return; - } - } -} - -MU_StaticFunc void MU_WIN32_UpdateFocusedWindow(MU_Context *mu) { - HWND handle = GetFocus(); - if (handle) { - MU_WIN32_UpdateFocusedWindowBasedOnHandle(mu, handle); - } -} - -MU_StaticFunc void MU_Win32_GetWindowSize(HWND window, int *x, int *y) { - RECT window_rect; - GetClientRect(window, &window_rect); - *x = window_rect.right - window_rect.left; - *y = window_rect.bottom - window_rect.top; -} - -MU_StaticFunc void MU_WIN32_GetWindowPos(HWND window, int *x, int *y) { - POINT point = {0, 0}; - ClientToScreen(window, &point); - *x = point.x; - *y = point.y; -} - -MU_StaticFunc MU_Int2 MU_WIN32_GetMousePosition(HWND window) { - POINT p; - GetCursorPos(&p); - ScreenToClient(window, &p); - MU_Int2 result = {p.x, p.y}; - return result; -} - -MU_StaticFunc MU_Int2 MU_WIN32_GetMousePositionInverted(HWND window, int y) { - MU_Int2 result = MU_WIN32_GetMousePosition(window); - result.y = y - result.y; - return result; -} - -MU_StaticFunc void MU_WIN32_CreateCanvas(MU_Window *window) { - MU_Win32_Window *w32_window = (MU_Win32_Window *)window->platform; - - MU_ASSERT(window->canvas == 0); - - BITMAPINFO bminfo; - { - MU__ZeroMemory(&bminfo, sizeof(bminfo)); - bminfo.bmiHeader.biSize = sizeof(bminfo.bmiHeader); - bminfo.bmiHeader.biWidth = (LONG)window->size.x; - bminfo.bmiHeader.biHeight = (LONG)window->size.y; - bminfo.bmiHeader.biPlanes = 1; - bminfo.bmiHeader.biBitCount = 32; - bminfo.bmiHeader.biCompression = BI_RGB; // AA RR GG BB - bminfo.bmiHeader.biXPelsPerMeter = 1; - bminfo.bmiHeader.biYPelsPerMeter = 1; - } - w32_window->canvas_dib = CreateDIBSection(w32_window->handle_dc, &bminfo, DIB_RGB_COLORS, (void **)&window->canvas, 0, 0); - w32_window->canvas_dc = CreateCompatibleDC(w32_window->handle_dc); -} - -MU_StaticFunc void MU_WIN32_DestroyCanvas(MU_Window *window) { - MU_Win32_Window *w32_window = (MU_Win32_Window *)window->platform; - if (window->canvas) { - DeleteDC(w32_window->canvas_dc); - DeleteObject(w32_window->canvas_dib); - w32_window->canvas_dc = 0; - w32_window->canvas_dib = 0; - window->canvas = 0; - } -} - -MU_StaticFunc void MU_WIN32_DrawCanvas(MU_Window *window) { - if (window->canvas) { - MU_Win32_Window *w32_window = (MU_Win32_Window *)window->platform; - SelectObject(w32_window->canvas_dc, w32_window->canvas_dib); - BitBlt(w32_window->handle_dc, 0, 0, window->size.x, window->size.y, w32_window->canvas_dc, 0, 0, SRCCOPY); - } -} - -MU_API void MU_ToggleFPSMode(MU_Window *window) { - ShowCursor(window->is_fps_mode); - window->is_fps_mode = !window->is_fps_mode; -} - -MU_API void MU_DisableFPSMode(MU_Window *window) { - if (window->is_fps_mode == true) MU_ToggleFPSMode(window); -} - -MU_API void MU_EnableFPSMode(MU_Window *window) { - if (window->is_fps_mode == false) MU_ToggleFPSMode(window); -} - -MU_StaticFunc void MU__MemoryCopy(void *dst, const void *src, size_t size) { - char *src8 = (char *)src; - char *dst8 = (char *)dst; - while (size--) *dst8++ = *src8++; -} - -// https://devblogs.microsoft.com/oldnewthing/20100412-00/?p=14353 -MU_API void MU_ToggleFullscreen(MU_Window *window) { - MU_Win32_Window *w32_window = (MU_Win32_Window *)window->platform; - DWORD dwStyle = GetWindowLong((HWND)window->handle, GWL_STYLE); - if (window->is_fullscreen == false) { - MONITORINFO mi = {sizeof(mi)}; - if (GetWindowPlacement((HWND)window->handle, &w32_window->prev_placement) && - GetMonitorInfo(MonitorFromWindow((HWND)window->handle, MONITOR_DEFAULTTOPRIMARY), &mi)) { - SetWindowLong((HWND)window->handle, GWL_STYLE, dwStyle & ~WS_OVERLAPPEDWINDOW); - BOOL result = SetWindowPos((HWND)window->handle, HWND_TOP, - mi.rcMonitor.left, mi.rcMonitor.top, - mi.rcMonitor.right - mi.rcMonitor.left, - mi.rcMonitor.bottom - mi.rcMonitor.top, - SWP_NOOWNERZORDER | SWP_FRAMECHANGED); - if (result) window->is_fullscreen = true; - } - } - else { - SetWindowLong((HWND)window->handle, GWL_STYLE, w32_window->style); - SetWindowPlacement((HWND)window->handle, &w32_window->prev_placement); - BOOL result = SetWindowPos((HWND)window->handle, NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_FRAMECHANGED); - if (result) window->is_fullscreen = false; - } -} - -MU_StaticFunc void MU_PushDroppedFile(MU_Context *mu, MU_Window *window, char *str, int size) { - if (MU_DoesSizeFit(&mu->frame_arena, sizeof(MU_DroppedFile) + size)) { - MU_DroppedFile *result = MU_PUSH_STRUCT(&mu->frame_arena, MU_DroppedFile); - result->filename = (char *)MU_PushSize(&mu->frame_arena, size + 1); - result->filename_size = size; - MU__MemoryCopy(result->filename, str, size); - result->filename[size] = 0; - - result->next = window->first_dropped_file; - window->first_dropped_file = result; - } -} - -// Should be initialized before processing events -// Should be initialized before initializing opengl functions using GLAD -static MU_Context *MU_WIN32_ContextPointerForEventHandling = 0; -static LRESULT CALLBACK MU_WIN32_WindowProc(HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam) { - MU_Context *mu = MU_WIN32_ContextPointerForEventHandling; - MU_Win32 *w32 = (MU_Win32 *)mu->platform; - - MU_WIN32_UpdateFocusedWindowBasedOnHandle(mu, wnd); - MU_Window *window = mu->window ? mu->window : 0; - if (window) window->processed_events_this_frame += 1; - - (void)w32; - switch (msg) { - - case WM_DROPFILES: { - wchar_t buffer[512]; - char buffer8[1024]; - - HDROP hdrop = (HDROP)wparam; - int file_count = (int)DragQueryFileW(hdrop, 0xffffffff, NULL, 0); - bool drop_failed = false; - for (int i = 0; i < file_count; i += 1) { - // UINT num_chars = DragQueryFileW(hdrop, i, NULL, 0) + 1; - // WCHAR* buffer = (WCHAR*) _sapp_malloc_clear(num_chars * sizeof(WCHAR)); - UINT result = DragQueryFileW(hdrop, i, buffer, MU_ARRAY_SIZE(buffer)); - MU_ASSERT(result != 0); - if (result) { - int64_t size = MU_CreateCharFromWidechar(buffer8, MU_ARRAY_SIZE(buffer8), buffer, MU_ARRAY_SIZE(buffer)); - if (size != -1) { - MU_PushDroppedFile(mu, window, buffer8, (int)size); - } - } - } - DragFinish(hdrop); - } break; - - case WM_CLOSE: { - // @! Make sure that focus works - // @! We should find the window and make sure we inform it that the user clicked the close button - PostQuitMessage(0); - mu->quit = true; - } break; - - case WM_LBUTTONDOWN: { - SetCapture(wnd); - if (window->change_cursor_on_mouse_hold) SetCursor(w32->cursor_hand); - if (window->mouse.left.down == false) - window->mouse.left.press = true; - window->mouse.left.down = true; - } break; - - case WM_LBUTTONUP: { - ReleaseCapture(); - if (window->change_cursor_on_mouse_hold) SetCursor(w32->cursor_arrow); - if (window->mouse.left.down == true) - window->mouse.left.unpress = true; - window->mouse.left.down = false; - } break; - - case WM_RBUTTONDOWN: { - SetCapture(wnd); - if (window->mouse.right.down == false) - window->mouse.right.press = true; - window->mouse.right.down = true; - } break; - - case WM_RBUTTONUP: { - ReleaseCapture(); - if (window->mouse.right.down == true) - window->mouse.right.unpress = true; - window->mouse.right.down = false; - } break; - - case WM_MBUTTONDOWN: { - SetCapture(wnd); - if (window->mouse.middle.down == false) - window->mouse.middle.press = true; - window->mouse.middle.down = true; - } break; - - case WM_MBUTTONUP: { - ReleaseCapture(); - if (window->mouse.middle.down == true) - window->mouse.middle.unpress = true; - window->mouse.middle.down = false; - } break; - - case WM_MOUSEWHEEL: { - if ((int)wparam > 0) { - window->mouse.delta_wheel += 1.0f; - } - else { - window->mouse.delta_wheel -= 1.0f; - } - } break; - - case WM_CHAR: { - MU_UTF32Result encode = MU_UTF16ToUTF32((uint16_t *)&wparam, 2); - if (encode.error) { - MU__WriteChar32(window, (uint32_t)'?'); - MU__WriteChar8(window, "?", 1); - } - else { - MU__WriteChar32(window, encode.out_str); - } - - // Utf8 encode - if (encode.error == false) { - MU_UTF8Result encode8 = MU_UTF32ToUTF8(encode.out_str); - if (encode8.error) { - MU__WriteChar8(window, "?", 1); - } - else { - MU__WriteChar8(window, encode8.out_str, encode8.len); - } - } - } break; - - case WM_KEYUP: - case WM_SYSKEYUP: { - switch (wparam) { - case VK_ESCAPE: MU__KeyUP(window, MU_KEY_ESCAPE); break; - case VK_RETURN: MU__KeyUP(window, MU_KEY_ENTER); break; - case VK_TAB: MU__KeyUP(window, MU_KEY_TAB); break; - case VK_BACK: MU__KeyUP(window, MU_KEY_BACKSPACE); break; - case VK_INSERT: MU__KeyUP(window, MU_KEY_INSERT); break; - case VK_DELETE: MU__KeyUP(window, MU_KEY_DELETE); break; - case VK_RIGHT: MU__KeyUP(window, MU_KEY_RIGHT); break; - case VK_LEFT: MU__KeyUP(window, MU_KEY_LEFT); break; - case VK_DOWN: MU__KeyUP(window, MU_KEY_DOWN); break; - case VK_UP: MU__KeyUP(window, MU_KEY_UP); break; - case VK_PRIOR: MU__KeyUP(window, MU_KEY_PAGE_UP); break; - case VK_NEXT: MU__KeyUP(window, MU_KEY_PAGE_DOWN); break; - case VK_END: MU__KeyUP(window, MU_KEY_HOME); break; - case VK_HOME: MU__KeyUP(window, MU_KEY_END); break; - case VK_F1: MU__KeyUP(window, MU_KEY_F1); break; - case VK_F2: MU__KeyUP(window, MU_KEY_F2); break; - case VK_F3: MU__KeyUP(window, MU_KEY_F3); break; - case VK_F4: MU__KeyUP(window, MU_KEY_F4); break; - case VK_F5: MU__KeyUP(window, MU_KEY_F5); break; - case VK_F6: MU__KeyUP(window, MU_KEY_F6); break; - case VK_F7: MU__KeyUP(window, MU_KEY_F7); break; - case VK_F8: MU__KeyUP(window, MU_KEY_F8); break; - case VK_F9: MU__KeyUP(window, MU_KEY_F9); break; - case VK_F10: MU__KeyUP(window, MU_KEY_F10); break; - case VK_F11: MU__KeyUP(window, MU_KEY_F11); break; - case VK_F12: MU__KeyUP(window, MU_KEY_F12); break; - case VK_SPACE: MU__KeyUP(window, MU_KEY_SPACE); break; - case VK_OEM_PLUS: MU__KeyUP(window, MU_KEY_PLUS); break; - case VK_OEM_COMMA: MU__KeyUP(window, MU_KEY_COMMA); break; - case VK_OEM_MINUS: MU__KeyUP(window, MU_KEY_MINUS); break; - case VK_OEM_PERIOD: MU__KeyUP(window, MU_KEY_PERIOD); break; - case '0': MU__KeyUP(window, MU_KEY_0); break; - case '1': MU__KeyUP(window, MU_KEY_1); break; - case '2': MU__KeyUP(window, MU_KEY_2); break; - case '3': MU__KeyUP(window, MU_KEY_3); break; - case '4': MU__KeyUP(window, MU_KEY_4); break; - case '5': MU__KeyUP(window, MU_KEY_5); break; - case '6': MU__KeyUP(window, MU_KEY_6); break; - case '7': MU__KeyUP(window, MU_KEY_7); break; - case '8': MU__KeyUP(window, MU_KEY_8); break; - case '9': MU__KeyUP(window, MU_KEY_9); break; - case ';': MU__KeyUP(window, MU_KEY_SEMICOLON); break; - case '=': MU__KeyUP(window, MU_KEY_EQUAL); break; - case 'A': MU__KeyUP(window, MU_KEY_A); break; - case 'B': MU__KeyUP(window, MU_KEY_B); break; - case 'C': MU__KeyUP(window, MU_KEY_C); break; - case 'D': MU__KeyUP(window, MU_KEY_D); break; - case 'E': MU__KeyUP(window, MU_KEY_E); break; - case 'F': MU__KeyUP(window, MU_KEY_F); break; - case 'G': MU__KeyUP(window, MU_KEY_G); break; - case 'H': MU__KeyUP(window, MU_KEY_H); break; - case 'I': MU__KeyUP(window, MU_KEY_I); break; - case 'J': MU__KeyUP(window, MU_KEY_J); break; - case 'K': MU__KeyUP(window, MU_KEY_K); break; - case 'L': MU__KeyUP(window, MU_KEY_L); break; - case 'M': MU__KeyUP(window, MU_KEY_M); break; - case 'N': MU__KeyUP(window, MU_KEY_N); break; - case 'O': MU__KeyUP(window, MU_KEY_O); break; - case 'P': MU__KeyUP(window, MU_KEY_P); break; - case 'Q': MU__KeyUP(window, MU_KEY_Q); break; - case 'R': MU__KeyUP(window, MU_KEY_R); break; - case 'S': MU__KeyUP(window, MU_KEY_S); break; - case 'T': MU__KeyUP(window, MU_KEY_T); break; - case 'U': MU__KeyUP(window, MU_KEY_U); break; - case 'V': MU__KeyUP(window, MU_KEY_V); break; - case 'W': MU__KeyUP(window, MU_KEY_W); break; - case 'X': MU__KeyUP(window, MU_KEY_X); break; - case 'Y': MU__KeyUP(window, MU_KEY_Y); break; - case 'Z': MU__KeyUP(window, MU_KEY_Z); break; - case VK_F13: MU__KeyUP(window, MU_KEY_F13); break; - case VK_F14: MU__KeyUP(window, MU_KEY_F14); break; - case VK_F15: MU__KeyUP(window, MU_KEY_F15); break; - case VK_F16: MU__KeyUP(window, MU_KEY_F16); break; - case VK_F17: MU__KeyUP(window, MU_KEY_F17); break; - case VK_F18: MU__KeyUP(window, MU_KEY_F18); break; - case VK_F19: MU__KeyUP(window, MU_KEY_F19); break; - case VK_F20: MU__KeyUP(window, MU_KEY_F20); break; - case VK_F21: MU__KeyUP(window, MU_KEY_F21); break; - case VK_F22: MU__KeyUP(window, MU_KEY_F22); break; - case VK_F23: MU__KeyUP(window, MU_KEY_F23); break; - case VK_F24: MU__KeyUP(window, MU_KEY_F24); break; - case 0x60: MU__KeyUP(window, MU_KEY_KP_0); break; - case 0x61: MU__KeyUP(window, MU_KEY_KP_1); break; - case 0x62: MU__KeyUP(window, MU_KEY_KP_2); break; - case 0x63: MU__KeyUP(window, MU_KEY_KP_3); break; - case 0x64: MU__KeyUP(window, MU_KEY_KP_4); break; - case 0x65: MU__KeyUP(window, MU_KEY_KP_5); break; - case 0x66: MU__KeyUP(window, MU_KEY_KP_6); break; - case 0x67: MU__KeyUP(window, MU_KEY_KP_7); break; - case 0x68: MU__KeyUP(window, MU_KEY_KP_8); break; - case 0x69: MU__KeyUP(window, MU_KEY_KP_9); break; - case VK_DECIMAL: MU__KeyUP(window, MU_KEY_KP_DECIMAL); break; - case VK_DIVIDE: MU__KeyUP(window, MU_KEY_KP_DIVIDE); break; - case VK_MULTIPLY: MU__KeyUP(window, MU_KEY_KP_MULTIPLY); break; - case VK_SUBTRACT: MU__KeyUP(window, MU_KEY_KP_SUBTRACT); break; - case VK_ADD: MU__KeyUP(window, MU_KEY_KP_ADD); break; - case VK_LMENU: MU__KeyUP(window, MU_KEY_LEFT_ALT); break; - case VK_LWIN: MU__KeyUP(window, MU_KEY_LEFT_SUPER); break; - case VK_CONTROL: MU__KeyUP(window, MU_KEY_CONTROL); break; - case VK_SHIFT: MU__KeyUP(window, MU_KEY_SHIFT); break; - case VK_LSHIFT: MU__KeyUP(window, MU_KEY_LEFT_SHIFT); break; - case VK_LCONTROL: MU__KeyUP(window, MU_KEY_LEFT_CONTROL); break; - case VK_RSHIFT: MU__KeyUP(window, MU_KEY_RIGHT_SHIFT); break; - case VK_RCONTROL: MU__KeyUP(window, MU_KEY_RIGHT_CONTROL); break; - case VK_RMENU: MU__KeyUP(window, MU_KEY_RIGHT_ALT); break; - case VK_RWIN: MU__KeyUP(window, MU_KEY_RIGHT_SUPER); break; - case VK_CAPITAL: MU__KeyUP(window, MU_KEY_CAPS_LOCK); break; - case VK_SCROLL: MU__KeyUP(window, MU_KEY_SCROLL_LOCK); break; - case VK_NUMLOCK: MU__KeyUP(window, MU_KEY_NUM_LOCK); break; - case VK_SNAPSHOT: MU__KeyUP(window, MU_KEY_PRINT_SCREEN); break; - case VK_PAUSE: MU__KeyUP(window, MU_KEY_PAUSE); break; - } - } break; - - case WM_KEYDOWN: - case WM_SYSKEYDOWN: { - switch (wparam) { - case VK_ESCAPE: MU__KeyDown(window, MU_KEY_ESCAPE); break; - case VK_RETURN: MU__KeyDown(window, MU_KEY_ENTER); break; - case VK_TAB: MU__KeyDown(window, MU_KEY_TAB); break; - case VK_BACK: MU__KeyDown(window, MU_KEY_BACKSPACE); break; - case VK_INSERT: MU__KeyDown(window, MU_KEY_INSERT); break; - case VK_DELETE: MU__KeyDown(window, MU_KEY_DELETE); break; - case VK_RIGHT: MU__KeyDown(window, MU_KEY_RIGHT); break; - case VK_LEFT: MU__KeyDown(window, MU_KEY_LEFT); break; - case VK_DOWN: MU__KeyDown(window, MU_KEY_DOWN); break; - case VK_UP: MU__KeyDown(window, MU_KEY_UP); break; - case VK_PRIOR: MU__KeyDown(window, MU_KEY_PAGE_UP); break; - case VK_NEXT: MU__KeyDown(window, MU_KEY_PAGE_DOWN); break; - case VK_END: MU__KeyDown(window, MU_KEY_HOME); break; - case VK_HOME: MU__KeyDown(window, MU_KEY_END); break; - case VK_F1: MU__KeyDown(window, MU_KEY_F1); break; - case VK_F2: MU__KeyDown(window, MU_KEY_F2); break; - case VK_F3: MU__KeyDown(window, MU_KEY_F3); break; - case VK_F4: MU__KeyDown(window, MU_KEY_F4); break; - case VK_F5: MU__KeyDown(window, MU_KEY_F5); break; - case VK_F6: MU__KeyDown(window, MU_KEY_F6); break; - case VK_F7: MU__KeyDown(window, MU_KEY_F7); break; - case VK_F8: MU__KeyDown(window, MU_KEY_F8); break; - case VK_F9: MU__KeyDown(window, MU_KEY_F9); break; - case VK_F10: MU__KeyDown(window, MU_KEY_F10); break; - case VK_F11: MU__KeyDown(window, MU_KEY_F11); break; - case VK_F12: MU__KeyDown(window, MU_KEY_F12); break; - case VK_SPACE: MU__KeyDown(window, MU_KEY_SPACE); break; - case VK_OEM_PLUS: MU__KeyDown(window, MU_KEY_PLUS); break; - case VK_OEM_COMMA: MU__KeyDown(window, MU_KEY_COMMA); break; - case VK_OEM_MINUS: MU__KeyDown(window, MU_KEY_MINUS); break; - case VK_OEM_PERIOD: MU__KeyDown(window, MU_KEY_PERIOD); break; - case '0': MU__KeyDown(window, MU_KEY_0); break; - case '1': MU__KeyDown(window, MU_KEY_1); break; - case '2': MU__KeyDown(window, MU_KEY_2); break; - case '3': MU__KeyDown(window, MU_KEY_3); break; - case '4': MU__KeyDown(window, MU_KEY_4); break; - case '5': MU__KeyDown(window, MU_KEY_5); break; - case '6': MU__KeyDown(window, MU_KEY_6); break; - case '7': MU__KeyDown(window, MU_KEY_7); break; - case '8': MU__KeyDown(window, MU_KEY_8); break; - case '9': MU__KeyDown(window, MU_KEY_9); break; - case ';': MU__KeyDown(window, MU_KEY_SEMICOLON); break; - case '=': MU__KeyDown(window, MU_KEY_EQUAL); break; - case 'A': MU__KeyDown(window, MU_KEY_A); break; - case 'B': MU__KeyDown(window, MU_KEY_B); break; - case 'C': MU__KeyDown(window, MU_KEY_C); break; - case 'D': MU__KeyDown(window, MU_KEY_D); break; - case 'E': MU__KeyDown(window, MU_KEY_E); break; - case 'F': MU__KeyDown(window, MU_KEY_F); break; - case 'G': MU__KeyDown(window, MU_KEY_G); break; - case 'H': MU__KeyDown(window, MU_KEY_H); break; - case 'I': MU__KeyDown(window, MU_KEY_I); break; - case 'J': MU__KeyDown(window, MU_KEY_J); break; - case 'K': MU__KeyDown(window, MU_KEY_K); break; - case 'L': MU__KeyDown(window, MU_KEY_L); break; - case 'M': MU__KeyDown(window, MU_KEY_M); break; - case 'N': MU__KeyDown(window, MU_KEY_N); break; - case 'O': MU__KeyDown(window, MU_KEY_O); break; - case 'P': MU__KeyDown(window, MU_KEY_P); break; - case 'Q': MU__KeyDown(window, MU_KEY_Q); break; - case 'R': MU__KeyDown(window, MU_KEY_R); break; - case 'S': MU__KeyDown(window, MU_KEY_S); break; - case 'T': MU__KeyDown(window, MU_KEY_T); break; - case 'U': MU__KeyDown(window, MU_KEY_U); break; - case 'V': MU__KeyDown(window, MU_KEY_V); break; - case 'W': MU__KeyDown(window, MU_KEY_W); break; - case 'X': MU__KeyDown(window, MU_KEY_X); break; - case 'Y': MU__KeyDown(window, MU_KEY_Y); break; - case 'Z': MU__KeyDown(window, MU_KEY_Z); break; - case VK_F13: MU__KeyDown(window, MU_KEY_F13); break; - case VK_F14: MU__KeyDown(window, MU_KEY_F14); break; - case VK_F15: MU__KeyDown(window, MU_KEY_F15); break; - case VK_F16: MU__KeyDown(window, MU_KEY_F16); break; - case VK_F17: MU__KeyDown(window, MU_KEY_F17); break; - case VK_F18: MU__KeyDown(window, MU_KEY_F18); break; - case VK_F19: MU__KeyDown(window, MU_KEY_F19); break; - case VK_F20: MU__KeyDown(window, MU_KEY_F20); break; - case VK_F21: MU__KeyDown(window, MU_KEY_F21); break; - case VK_F22: MU__KeyDown(window, MU_KEY_F22); break; - case VK_F23: MU__KeyDown(window, MU_KEY_F23); break; - case VK_F24: MU__KeyDown(window, MU_KEY_F24); break; - case 0x60: MU__KeyDown(window, MU_KEY_KP_0); break; - case 0x61: MU__KeyDown(window, MU_KEY_KP_1); break; - case 0x62: MU__KeyDown(window, MU_KEY_KP_2); break; - case 0x63: MU__KeyDown(window, MU_KEY_KP_3); break; - case 0x64: MU__KeyDown(window, MU_KEY_KP_4); break; - case 0x65: MU__KeyDown(window, MU_KEY_KP_5); break; - case 0x66: MU__KeyDown(window, MU_KEY_KP_6); break; - case 0x67: MU__KeyDown(window, MU_KEY_KP_7); break; - case 0x68: MU__KeyDown(window, MU_KEY_KP_8); break; - case 0x69: MU__KeyDown(window, MU_KEY_KP_9); break; - case VK_CONTROL: MU__KeyDown(window, MU_KEY_CONTROL); break; - case VK_SHIFT: MU__KeyDown(window, MU_KEY_SHIFT); break; - case VK_DECIMAL: MU__KeyDown(window, MU_KEY_KP_DECIMAL); break; - case VK_DIVIDE: MU__KeyDown(window, MU_KEY_KP_DIVIDE); break; - case VK_MULTIPLY: MU__KeyDown(window, MU_KEY_KP_MULTIPLY); break; - case VK_SUBTRACT: MU__KeyDown(window, MU_KEY_KP_SUBTRACT); break; - case VK_ADD: MU__KeyDown(window, MU_KEY_KP_ADD); break; - case VK_LSHIFT: MU__KeyDown(window, MU_KEY_LEFT_SHIFT); break; - case VK_LCONTROL: MU__KeyDown(window, MU_KEY_LEFT_CONTROL); break; - case VK_LMENU: MU__KeyDown(window, MU_KEY_LEFT_ALT); break; - case VK_LWIN: MU__KeyDown(window, MU_KEY_LEFT_SUPER); break; - case VK_RSHIFT: MU__KeyDown(window, MU_KEY_RIGHT_SHIFT); break; - case VK_RCONTROL: MU__KeyDown(window, MU_KEY_RIGHT_CONTROL); break; - case VK_RMENU: MU__KeyDown(window, MU_KEY_RIGHT_ALT); break; - case VK_RWIN: MU__KeyDown(window, MU_KEY_RIGHT_SUPER); break; - case VK_CAPITAL: MU__KeyDown(window, MU_KEY_CAPS_LOCK); break; - case VK_SCROLL: MU__KeyDown(window, MU_KEY_SCROLL_LOCK); break; - case VK_NUMLOCK: MU__KeyDown(window, MU_KEY_NUM_LOCK); break; - case VK_SNAPSHOT: MU__KeyDown(window, MU_KEY_PRINT_SCREEN); break; - case VK_PAUSE: MU__KeyDown(window, MU_KEY_PAUSE); break; - } - } break; - - default: { - return DefWindowProcW(wnd, msg, wparam, lparam); - } - } - return 0; -} - -MU_API void MU_Init(MU_Context *mu, MU_Params params, size_t len) { - MU_ASSERT(params.memory && params.cap && "Expected any kind of memory"); - - MU__ZeroMemory(mu, sizeof(*mu)); - mu->perm_arena.memory = (char *)params.memory; - mu->perm_arena.cap = params.cap; - mu->perm_arena.len = len; - MU_WIN32_ContextPointerForEventHandling = mu; - - mu->platform = MU_PUSH_STRUCT(&mu->perm_arena, MU_Win32); - MU_Win32 *w32 = (MU_Win32 *)mu->platform; - - mu->frame_arena.cap = (mu->perm_arena.cap - mu->perm_arena.len) / 2; - mu->frame_arena.memory = (char *)MU_PushSize(&mu->perm_arena, mu->frame_arena.cap); - - mu->time.delta = params.delta_time == 0.0 ? 0.0166666 : params.delta_time; - - mu->sound.callback = params.sound_callback; - mu->params = params; - - if (mu->sound.callback) { - MU_WIN32_InitWasapi(mu); - MU_ASSERT(mu->sound.initialized); - } - - typedef enum MU_PROCESS_DPI_AWARENESS { - MU_PROCESS_DPI_UNAWARE = 0, - MU_PROCESS_SYSTEM_DPI_AWARE = 1, - MU_PROCESS_PER_MONITOR_DPI_AWARE = 2 - } MU_PROCESS_DPI_AWARENESS; - typedef unsigned MU_TimeBeginPeriod(unsigned); - typedef HRESULT MU_SetProcessDpiAwareness(MU_PROCESS_DPI_AWARENESS); - - HMODULE shcore = LoadLibraryA("Shcore.dll"); - if (shcore) { - MU_SetProcessDpiAwareness *set_dpi_awr = (MU_SetProcessDpiAwareness *)GetProcAddress(shcore, "SetProcessDpiAwareness"); - if (set_dpi_awr) { - HRESULT hr = set_dpi_awr(MU_PROCESS_PER_MONITOR_DPI_AWARE); - MU_ASSERT(SUCCEEDED(hr) && "Failed to set dpi awareness"); - } - } - - HMODULE winmm = LoadLibraryA("winmm.dll"); - if (winmm) { - MU_TimeBeginPeriod *timeBeginPeriod = (MU_TimeBeginPeriod *)GetProcAddress(winmm, "timeBeginPeriod"); - if (timeBeginPeriod) { - if (timeBeginPeriod(1) == 0) { - w32->good_scheduling = true; - } - } - } - - WNDCLASSW wc; - { - MU__ZeroMemory(&wc, sizeof(wc)); - wc.lpfnWndProc = MU_WIN32_WindowProc; - wc.hInstance = GetModuleHandleW(NULL); - wc.lpszClassName = L"Multimedia_Start"; - wc.hCursor = LoadCursor(0, IDC_ARROW); - wc.hIcon = NULL; // LoadIcon(wc.hInstance, IDI_APPLICATION); - wc.style = CS_OWNDC | CS_VREDRAW | CS_HREDRAW; - MU_ASSERT_CODE(ATOM result =) - RegisterClassW(&wc); - MU_ASSERT(result != 0); - w32->wc = wc; - } - - mu->primary_monitor_size.x = GetSystemMetrics(SM_CXSCREEN); - mu->primary_monitor_size.y = GetSystemMetrics(SM_CYSCREEN); - - w32->cursor_hand = LoadCursor(0, IDC_SIZEALL); - w32->cursor_arrow = LoadCursor(0, IDC_ARROW); - - mu->time.app_start = MU_GetTime(); - mu->first_frame = true; -} - -MU_StaticFunc void MU_UpdateWindowState(MU_Window *window) { - MU_Win32_Window *w32_window = (MU_Win32_Window *)window->platform; - - UINT dpi = GetDpiForWindow((HWND)window->handle); - MU_ASSERT(dpi != 0 && "Failed to get dpi for window"); - window->dpi_scale = (float)dpi / 96.f; - - MU_Int2 size; - MU_WIN32_GetWindowPos((HWND)window->handle, &window->pos.x, &window->pos.y); - MU_Win32_GetWindowSize((HWND)window->handle, &size.x, &size.y); - - if (window->canvas_enabled == false || window->size.x != size.x || window->size.y != size.y) { - MU_WIN32_DestroyCanvas(window); - } - - window->size = size; - window->sizef.x = (float)window->size.x; - window->sizef.y = (float)window->size.y; - - window->posf.x = (float)window->pos.x; - window->posf.y = (float)window->pos.y; - - if (window->canvas_enabled && window->canvas == 0) { - MU_WIN32_CreateCanvas(window); - } -} - -MU_API MU_Window *MU_AddWindow(MU_Context *mu, MU_Window_Params params) { - MU_Window *window = MU_PUSH_STRUCT(&mu->perm_arena, MU_Window); - MU_InitWindow(mu, window, params); - return window; -} - -MU_API void MU_InitWindow(MU_Context *mu, MU_Window *window, MU_Window_Params params) { - window->platform = MU_PUSH_STRUCT(&mu->perm_arena, MU_Win32_Window); - - MU_Win32 *w32 = (MU_Win32 *)mu->platform; - MU_Win32_Window *w32_window = (MU_Win32_Window *)window->platform; - - if (params.pos.x == 0) params.pos.x = (int)((double)mu->primary_monitor_size.x * 0.1); - if (params.pos.y == 0) params.pos.y = (int)((double)mu->primary_monitor_size.y * 0.1); - if (params.size.x == 0) params.size.x = (int)((double)mu->primary_monitor_size.x * 0.8); - if (params.size.y == 0) params.size.y = (int)((double)mu->primary_monitor_size.y * 0.8); - window->canvas_enabled = params.enable_canvas; - - w32_window->style = WS_OVERLAPPEDWINDOW; - if (!params.resizable) { - w32_window->style &= ~WS_THICKFRAME & ~WS_MAXIMIZEBOX; - } - if (params.borderless) { - w32_window->style = WS_POPUP | WS_VISIBLE | WS_SYSMENU; - } - - RECT window_rect; - window_rect.left = (LONG)params.pos.x; - window_rect.top = (LONG)params.pos.y; - window_rect.right = (LONG)params.size.x + window_rect.left; - window_rect.bottom = (LONG)params.size.y + window_rect.top; - AdjustWindowRectEx(&window_rect, w32_window->style, false, 0); - - HWND handle = CreateWindowW(w32->wc.lpszClassName, L"Zzz... Window, hello!", w32_window->style, window_rect.left, window_rect.top, window_rect.right - window_rect.left, window_rect.bottom - window_rect.top, NULL, NULL, w32->wc.hInstance, NULL); - MU_ASSERT(handle); - - window->handle = handle; - w32_window->handle_dc = GetDC(handle); - MU_ASSERT(w32_window->handle_dc); - - DragAcceptFiles(handle, TRUE); - - MU_WIN32_TryToInitGLContextForWindow(mu, w32_window); - - ShowWindow(handle, SW_SHOW); - MU_UpdateWindowState(window); - MU_STACK_ADD(mu->all_windows, window); - MU_WIN32_UpdateFocusedWindow(mu); -} - -MU_API MU_Context *MU_Start(MU_Params params) { - // Bootstrap the context from user memory - // If the user didnt provide memory, allocate it ourselves - if (!params.memory) { - HANDLE process_heap = GetProcessHeap(); - params.cap = MU_DEFAULT_MEMORY_SIZE; - params.memory = HeapAlloc(process_heap, 0, params.cap); - MU_ASSERT(params.memory); - } - MU_Context *mu = (MU_Context *)params.memory; - MU_Init(mu, params, sizeof(MU_Context)); - mu->window = MU_AddWindow(mu, params.window); - - return mu; -} - -MU_API bool MU_Update(MU_Context *mu) { - MU_Win32 *w32 = (MU_Win32 *)mu->platform; - - // Since this is meant to be called in while loop - // first MU_Update happens before first frame - // therfore start of second MU_Update is end of first frame - mu->_MU_Update_count += 1; - if (mu->_MU_Update_count == 2) mu->first_frame = false; - mu->frame_arena.len = 0; - - MU_WIN32_UpdateFocusedWindow(mu); - for (MU_Window *it = mu->all_windows; it; it = it->next) { - if (it->should_render == true && mu->first_frame == false && mu->opengl_initialized) { - MU_Win32_Window *w32_window = (MU_Win32_Window *)it->platform; - MU_ASSERT_CODE(BOOL result =) - SwapBuffers(w32_window->handle_dc); - MU_ASSERT(result); - } - it->should_render = true; - - it->first_dropped_file = 0; - MU_WIN32_DrawCanvas(it); - it->processed_events_this_frame = 0; - it->user_text8_count = 0; - it->user_text32_count = 0; - it->mouse.delta_wheel = 0.0; - it->mouse.left.press = 0; - it->mouse.right.press = 0; - it->mouse.middle.press = 0; - it->mouse.left.unpress = 0; - it->mouse.right.unpress = 0; - it->mouse.middle.unpress = 0; - for (int i = 0; i < MU_KEY_COUNT; i += 1) { - it->key[i].press = 0; - it->key[i].unpress = 0; - it->key[i].raw_press = 0; - } - } - - MSG msg; - MU_WIN32_ContextPointerForEventHandling = mu; - while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE)) { - TranslateMessage(&msg); - DispatchMessage(&msg); - } - - for (MU_Window *it = mu->all_windows; it; it = it->next) { - MU_UpdateWindowState(it); - } - - mu->window->user_text8[mu->window->user_text8_count] = 0; - mu->window->user_text32[mu->window->user_text32_count] = 0; - - MU_Win32_Window *w32_window = (MU_Win32_Window *)mu->window->platform; - HWND focused_window = GetFocus(); - mu->window->is_focused = focused_window == (HWND)mu->window->handle; - - // We only need to update the mouse position of a currently focused window? - { - - MU_Int2 mouse_pos = MU_WIN32_GetMousePositionInverted((HWND)mu->window->handle, mu->window->size.y); - - if (mu->window->is_focused) { - if (mu->first_frame == false) { - mu->window->mouse.delta_pos.x = mouse_pos.x - mu->window->mouse.pos.x; - mu->window->mouse.delta_pos.y = mouse_pos.y - mu->window->mouse.pos.y; - mu->window->mouse.delta_pos_normalized.x = (float)mu->window->mouse.delta_pos.x / (float)mu->window->size.x; - mu->window->mouse.delta_pos_normalized.y = (float)mu->window->mouse.delta_pos.y / (float)mu->window->size.y; - } - if (mu->window->is_fps_mode) { - SetCursorPos(mu->window->size.x / 2, mu->window->size.y / 2); - mouse_pos = MU_WIN32_GetMousePositionInverted((HWND)mu->window->handle, mu->window->size.y); - } - } - mu->window->mouse.pos = mouse_pos; - mu->window->mouse.posf.x = (float)mouse_pos.x; - mu->window->mouse.posf.y = (float)mouse_pos.y; - } - - // Timming - if (mu->first_frame == false) { - mu->time.update = MU_GetTime() - mu->time.frame_start; - if (mu->time.update < mu->time.delta) { - mu->consecutive_missed_frames = 0; - - // Try to use the Sleep, if we dont have good scheduler priority - // then we can miss framerate so need to busy loop instead - if (w32->good_scheduling) { - double time_to_sleep = mu->time.delta - mu->time.update; - double time_to_sleep_in_ms = time_to_sleep * 1000.0 - 1; - if (time_to_sleep > 0.0) { - DWORD time_to_sleep_uint = (DWORD)time_to_sleep_in_ms; - if (time_to_sleep_uint) { - Sleep(time_to_sleep_uint); - } - } - } - - // Busy loop if we dont have good scheduling - // or we woke up early - double update_time = MU_GetTime() - mu->time.frame_start; - while (update_time < mu->time.delta) { - update_time = MU_GetTime() - mu->time.frame_start; - } - } - else { - mu->consecutive_missed_frames += 1; - mu->total_missed_frames += 1; - } - - mu->frame += 1; - mu->time.update_total = MU_GetTime() - mu->time.frame_start; - mu->time.total += mu->time.delta; - } - mu->time.frame_start = MU_GetTime(); - - mu->time.deltaf = (float)mu->time.delta; - mu->time.totalf = (float)mu->time.total; - - return !mu->quit; -} - -// -// Opengl context setup -// -// @! Cleanup OpenGL - Should the user be cappable of detecting that opengl couldnt load? -// Should the layer automatically downscale? -// Should the layer inform and allow for a response? -/* - MU_Context *mu = MU_Start((MU_Params){ - .enable_opengl = true, - }); - if (mu->opengl_initialized == false) { - mu_opengl_try_initializng_context_for_window(mu->window, 3, 3); - } - if (mu->opengl_initialized == false) { - // directx - } - - - */ - -// Symbols taken from GLFW -// -// Executables (but not DLLs) exporting this symbol with this value will be -// automatically directed to the high-performance GPU on Nvidia Optimus systems -// with up-to-date drivers -// -__declspec(dllexport) DWORD NvOptimusEnablement = 1; - -// Executables (but not DLLs) exporting this symbol with this value will be -// automatically directed to the high-performance GPU on AMD PowerXpress systems -// with up-to-date drivers -// -__declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1; - -typedef HGLRC MU_wglCreateContext(HDC unnamedParam1); -typedef BOOL MU_wglMakeCurrent(HDC unnamedParam1, HGLRC unnamedParam2); -typedef BOOL MU_wglDeleteContext(HGLRC unnamedParam1); -HGLRC(*mu_wglCreateContext) -(HDC unnamedParam1); -BOOL(*mu_wglMakeCurrent) -(HDC unnamedParam1, HGLRC unnamedParam2); -BOOL(*mu_wglDeleteContext) -(HGLRC unnamedParam1); - -typedef const char *MU_wglGetExtensionsStringARB(HDC hdc); -typedef BOOL MU_wglChoosePixelFormatARB(HDC hdc, const int *piAttribIList, const float *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats); -typedef HGLRC MU_wglCreateContextAttribsARB(HDC hDC, HGLRC hshareContext, const int *attribList); -typedef BOOL MU_wglSwapIntervalEXT(int interval); -MU_wglChoosePixelFormatARB *wglChoosePixelFormatARB; -MU_wglCreateContextAttribsARB *wglCreateContextAttribsARB; -MU_wglSwapIntervalEXT *wglSwapIntervalEXT; - - #define WGL_DRAW_TO_WINDOW_ARB 0x2001 - #define WGL_SUPPORT_OPENGL_ARB 0x2010 - #define WGL_DOUBLE_BUFFER_ARB 0x2011 - #define WGL_PIXEL_TYPE_ARB 0x2013 - #define WGL_TYPE_RGBA_ARB 0x202B - #define WGL_COLOR_BITS_ARB 0x2014 - #define WGL_DEPTH_BITS_ARB 0x2022 - #define WGL_STENCIL_BITS_ARB 0x2023 - - #define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091 - #define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092 - #define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126 - #define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001 - #define WGL_CONTEXT_FLAGS_ARB 0x2094 - #define WGL_CONTEXT_DEBUG_BIT_ARB 0x00000001 - - #define WGL_SAMPLE_BUFFERS_ARB 0x2041 - #define WGL_SAMPLES_ARB 0x2042 - -// -// Below loading part largely taken from github gist of Martins Mozeiko -// - -// compares src string with dstlen characters from dst, returns 1 if they are equal, 0 if not -MU_StaticFunc int MU__AreStringsEqual(const char *src, const char *dst, size_t dstlen) { - while (*src && dstlen-- && *dst) { - if (*src++ != *dst++) { - return 0; - } - } - - return (dstlen && *src == *dst) || (!dstlen && *src == 0); -} - -MU_StaticFunc void *MU_Win32_GLGetWindowProcAddressForGlad(const char *proc) { - MU_Win32 *w32 = (MU_Win32 *)MU_WIN32_ContextPointerForEventHandling->platform; - void *func; - - func = w32->wgl_get_proc_address(proc); - if (!func) { - func = GetProcAddress(w32->opengl32, proc); - } - return func; -} - -MU_StaticFunc void MU_WIN32_GetWGLFunctions(MU_Context *mu) { - MU_Win32 *w32 = (MU_Win32 *)mu->platform; - HMODULE opengl32 = LoadLibraryA("opengl32"); - MU_ASSERT(opengl32); - if (opengl32) { - w32->opengl32 = opengl32; - w32->wgl_get_proc_address = (MU_glGetProcAddress *)GetProcAddress(opengl32, "wglGetProcAddress"); - mu->gl_get_proc_address = MU_Win32_GLGetWindowProcAddressForGlad; - mu_wglCreateContext = (MU_wglCreateContext *)GetProcAddress(opengl32, "wglCreateContext"); - mu_wglMakeCurrent = (MU_wglMakeCurrent *)GetProcAddress(opengl32, "wglMakeCurrent"); - mu_wglDeleteContext = (MU_wglDeleteContext *)GetProcAddress(opengl32, "wglDeleteContext"); - } - if (opengl32 == NULL || mu_wglCreateContext == NULL || mu->gl_get_proc_address == NULL || mu_wglMakeCurrent == NULL || mu_wglDeleteContext == NULL) { - MU_ASSERT(!"Failed to load Opengl wgl functions from opengl32.lib"); - return; - } - - // to get WGL functions we need valid GL context, so create dummy window for dummy GL contetx - HWND dummy = CreateWindowExW( - 0, L"STATIC", L"DummyWindow", WS_OVERLAPPED, - CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, - NULL, NULL, NULL, NULL); - MU_ASSERT(dummy && "Failed to create dummy window"); - - HDC dc = GetDC(dummy); - MU_ASSERT(dc && "Failed to get device context for dummy window"); - - PIXELFORMATDESCRIPTOR desc; - MU__ZeroMemory(&desc, sizeof(desc)); - { - desc.nSize = sizeof(desc); - desc.nVersion = 1; - desc.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; - desc.iPixelType = PFD_TYPE_RGBA; - desc.cColorBits = 24; - }; - - int format = ChoosePixelFormat(dc, &desc); - if (!format) { - MU_ASSERT(!"Cannot choose OpenGL pixel format for dummy window!"); - } - - int ok = DescribePixelFormat(dc, format, sizeof(desc), &desc); - MU_ASSERT(ok && "Failed to describe OpenGL pixel format"); - - // reason to create dummy window is that SetPixelFormat can be called only once for the window - if (!SetPixelFormat(dc, format, &desc)) { - MU_ASSERT(!"Cannot set OpenGL pixel format for dummy window!"); - } - - HGLRC rc = mu_wglCreateContext(dc); - MU_ASSERT(rc && "Failed to create OpenGL context for dummy window"); - - ok = mu_wglMakeCurrent(dc, rc); - MU_ASSERT(ok && "Failed to make current OpenGL context for dummy window"); - - // https://www.khronos.org/registry/OpenGL/extensions/ARB/WGL_ARB_extensions_string.txt - MU_wglGetExtensionsStringARB *wglGetExtensionsStringARB = (MU_wglGetExtensionsStringARB *)mu->gl_get_proc_address("wglGetExtensionsStringARB"); - if (!wglGetExtensionsStringARB) { - MU_ASSERT(!"OpenGL does not support WGL_ARB_extensions_string extension!"); - } - - const char *ext = wglGetExtensionsStringARB(dc); - MU_ASSERT(ext && "Failed to get OpenGL WGL extension string"); - - const char *start = ext; - for (;;) { - while (*ext != 0 && *ext != ' ') { - ext++; - } - size_t length = ext - start; - if (MU__AreStringsEqual("WGL_ARB_pixel_format", start, length)) { - // https://www.khronos.org/registry/OpenGL/extensions/ARB/WGL_ARB_pixel_format.txt - wglChoosePixelFormatARB = (MU_wglChoosePixelFormatARB *)mu->gl_get_proc_address("wglChoosePixelFormatARB"); - } - else if (MU__AreStringsEqual("WGL_ARB_create_context", start, length)) { - // https://www.khronos.org/registry/OpenGL/extensions/ARB/WGL_ARB_create_context.txt - wglCreateContextAttribsARB = (MU_wglCreateContextAttribsARB *)mu->gl_get_proc_address("wglCreateContextAttribsARB"); - } - else if (MU__AreStringsEqual("WGL_EXT_swap_control", start, length)) { - // https://www.khronos.org/registry/OpenGL/extensions/EXT/WGL_EXT_swap_control.txt - wglSwapIntervalEXT = (MU_wglSwapIntervalEXT *)mu->gl_get_proc_address("wglSwapIntervalEXT"); - } - - if (*ext == 0) { - break; - } - - ext++; - start = ext; - } - - if (!wglChoosePixelFormatARB || !wglCreateContextAttribsARB || !wglSwapIntervalEXT) { - MU_ASSERT(!"OpenGL does not support required WGL extensions for modern context!"); - } - - mu_wglMakeCurrent(NULL, NULL); - mu_wglDeleteContext(rc); - ReleaseDC(dummy, dc); - DestroyWindow(dummy); - - mu->opengl_initialized = true; -} - -MU_StaticFunc void MU_WIN32_TryToInitGLContextForWindow(MU_Context *mu, MU_Win32_Window *w32_window) { - if (mu->opengl_initialized == false && mu->params.enable_opengl) { - MU_WIN32_GetWGLFunctions(mu); - if (mu->opengl_initialized) { - mu->opengl_major = mu->params.opengl_major ? mu->params.opengl_major : 4; - mu->opengl_minor = mu->params.opengl_minor ? mu->params.opengl_minor : 5; - } - } - - if (mu->opengl_initialized) { - // set pixel format for OpenGL context - int attrib[] = - { - WGL_DRAW_TO_WINDOW_ARB, - true, - WGL_SUPPORT_OPENGL_ARB, - true, - WGL_DOUBLE_BUFFER_ARB, - true, - WGL_PIXEL_TYPE_ARB, - WGL_TYPE_RGBA_ARB, - WGL_COLOR_BITS_ARB, - 32, - WGL_DEPTH_BITS_ARB, - 24, - WGL_STENCIL_BITS_ARB, - 8, - - // uncomment for sRGB framebuffer, from WGL_ARB_framebuffer_sRGB extension - // https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_framebuffer_sRGB.txt - // WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB, GL_TRUE, - - // uncomment for multisampeld framebuffer, from WGL_ARB_multisample extension - // https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_multisample.txt - #if MU_GL_ENABLE_MULTISAMPLING - WGL_SAMPLE_BUFFERS_ARB, - 1, - WGL_SAMPLES_ARB, - 4, // 4x MSAA - #endif - - 0, - }; - - int format; - UINT formats; - if (!wglChoosePixelFormatARB(w32_window->handle_dc, attrib, 0, 1, &format, &formats) || formats == 0) { - MU_ASSERT(!"OpenGL does not support required pixel format!"); - } - - PIXELFORMATDESCRIPTOR desc; - MU__ZeroMemory(&desc, sizeof(desc)); - desc.nSize = sizeof(desc); - int ok = DescribePixelFormat(w32_window->handle_dc, format, sizeof(desc), &desc); - MU_ASSERT(ok && "Failed to describe OpenGL pixel format"); - - if (!SetPixelFormat(w32_window->handle_dc, format, &desc)) { - MU_ASSERT(!"Cannot set OpenGL selected pixel format!"); - } - - // create modern OpenGL context - { - int attrib[] = - { - WGL_CONTEXT_MAJOR_VERSION_ARB, - mu->opengl_major, - WGL_CONTEXT_MINOR_VERSION_ARB, - mu->opengl_minor, - WGL_CONTEXT_PROFILE_MASK_ARB, - WGL_CONTEXT_CORE_PROFILE_BIT_ARB, - - #if MU_GL_BUILD_DEBUG - WGL_CONTEXT_FLAGS_ARB, - WGL_CONTEXT_DEBUG_BIT_ARB, - #endif - - 0, - }; - - HGLRC rc = wglCreateContextAttribsARB(w32_window->handle_dc, 0, attrib); - if (!rc) { - MU_ASSERT(!"Cannot create modern OpenGL context! OpenGL version 4.5 not supported?"); - } - - BOOL ok = mu_wglMakeCurrent(w32_window->handle_dc, rc); - MU_ASSERT(ok && "Failed to make current OpenGL context"); - } - } -} - -// -// Sound using WASAPI -// @! Sound: Comeback to it later! I dont really know what I should expect from a sound system -// What actually in reality errors out in WASAPI, what is important when working with sound. -// As such I'm not really currently equiped to make something good / reliable. -// Probably would be nice to work with it a bit more. -// -// Sound params should probably be configurable -// but I dont really understand what I should want to expect -// from this sort of system -// -// Not sure if I should in the future implement some different non threaded api. -// -// -// Below GUID stuff taken from libsoundio -// reference: https://github.com/andrewrk/libsoundio/blob/master/src/wasapi.c -// - -// And some GUID are never implemented (Ignoring the INITGUID define) -MU_PRIVATE_VAR const CLSID MU_CLSID_MMDeviceEnumerator = { - 0xbcde0395, 0xe52f, 0x467c, {0x8e, 0x3d, 0xc4, 0x57, 0x92, 0x91, 0x69, 0x2e} -}; -MU_PRIVATE_VAR const IID MU_IID_IMMDeviceEnumerator = { - // MIDL_INTERFACE("A95664D2-9614-4F35-A746-DE8DB63617E6") - 0xa95664d2, - 0x9614, - 0x4f35, - {0xa7, 0x46, 0xde, 0x8d, 0xb6, 0x36, 0x17, 0xe6} -}; -MU_PRIVATE_VAR const IID MU_IID_IMMNotificationClient = { - // MIDL_INTERFACE("7991EEC9-7E89-4D85-8390-6C703CEC60C0") - 0x7991eec9, - 0x7e89, - 0x4d85, - {0x83, 0x90, 0x6c, 0x70, 0x3c, 0xec, 0x60, 0xc0} -}; -MU_PRIVATE_VAR const IID MU_IID_IAudioClient = { - // MIDL_INTERFACE("1CB9AD4C-DBFA-4c32-B178-C2F568A703B2") - 0x1cb9ad4c, - 0xdbfa, - 0x4c32, - {0xb1, 0x78, 0xc2, 0xf5, 0x68, 0xa7, 0x03, 0xb2} -}; -MU_PRIVATE_VAR const IID MU_IID_IAudioRenderClient = { - // MIDL_INTERFACE("F294ACFC-3146-4483-A7BF-ADDCA7C260E2") - 0xf294acfc, - 0x3146, - 0x4483, - {0xa7, 0xbf, 0xad, 0xdc, 0xa7, 0xc2, 0x60, 0xe2} -}; -MU_PRIVATE_VAR const IID MU_IID_IAudioSessionControl = { - // MIDL_INTERFACE("F4B1A599-7266-4319-A8CA-E70ACB11E8CD") - 0xf4b1a599, - 0x7266, - 0x4319, - {0xa8, 0xca, 0xe7, 0x0a, 0xcb, 0x11, 0xe8, 0xcd} -}; -MU_PRIVATE_VAR const IID MU_IID_IAudioSessionEvents = { - // MIDL_INTERFACE("24918ACC-64B3-37C1-8CA9-74A66E9957A8") - 0x24918acc, - 0x64b3, - 0x37c1, - {0x8c, 0xa9, 0x74, 0xa6, 0x6e, 0x99, 0x57, 0xa8} -}; -MU_PRIVATE_VAR const IID MU_IID_IMMEndpoint = { - // MIDL_INTERFACE("1BE09788-6894-4089-8586-9A2A6C265AC5") - 0x1be09788, - 0x6894, - 0x4089, - {0x85, 0x86, 0x9a, 0x2a, 0x6c, 0x26, 0x5a, 0xc5} -}; -MU_PRIVATE_VAR const IID MU_IID_IAudioClockAdjustment = { - // MIDL_INTERFACE("f6e4c0a0-46d9-4fb8-be21-57a3ef2b626c") - 0xf6e4c0a0, - 0x46d9, - 0x4fb8, - {0xbe, 0x21, 0x57, 0xa3, 0xef, 0x2b, 0x62, 0x6c} -}; -MU_PRIVATE_VAR const IID MU_IID_IAudioCaptureClient = { - // MIDL_INTERFACE("C8ADBD64-E71E-48a0-A4DE-185C395CD317") - 0xc8adbd64, - 0xe71e, - 0x48a0, - {0xa4, 0xde, 0x18, 0x5c, 0x39, 0x5c, 0xd3, 0x17} -}; -MU_PRIVATE_VAR const IID MU_IID_ISimpleAudioVolume = { - // MIDL_INTERFACE("87ce5498-68d6-44e5-9215-6da47ef883d8") - 0x87ce5498, - 0x68d6, - 0x44e5, - {0x92, 0x15, 0x6d, 0xa4, 0x7e, 0xf8, 0x83, 0xd8} -}; - - #ifdef __cplusplus - // In C++ mode, IsEqualGUID() takes its arguments by reference - #define IS_EQUAL_GUID(a, b) IsEqualGUID(*(a), *(b)) - #define IS_EQUAL_IID(a, b) IsEqualIID((a), *(b)) - - // And some constants are passed by reference - #define MU_IID_IAUDIOCLIENT (MU_IID_IAudioClient) - #define MU_IID_IMMENDPOINT (MU_IID_IMMEndpoint) - #define MU_IID_IAUDIOCLOCKADJUSTMENT (MU_IID_IAudioClockAdjustment) - #define MU_IID_IAUDIOSESSIONCONTROL (MU_IID_IAudioSessionControl) - #define MU_IID_IAUDIORENDERCLIENT (MU_IID_IAudioRenderClient) - #define MU_IID_IMMDEVICEENUMERATOR (MU_IID_IMMDeviceEnumerator) - #define MU_IID_IAUDIOCAPTURECLIENT (MU_IID_IAudioCaptureClient) - #define MU_IID_ISIMPLEAUDIOVOLUME (MU_IID_ISimpleAudioVolume) - #define MU_CLSID_MMDEVICEENUMERATOR (MU_CLSID_MMDeviceEnumerator) - #define MU_PKEY_DEVICE_FRIENDLYNAME (PKEY_Device_FriendlyName) - #define MU_PKEY_AUDIOENGINE_DEVICEFORMAT (PKEY_AudioEngine_DeviceFormat) - - #else - #define IS_EQUAL_GUID(a, b) IsEqualGUID((a), (b)) - #define IS_EQUAL_IID(a, b) IsEqualIID((a), (b)) - - #define MU_IID_IAUDIOCLIENT (&MU_IID_IAudioClient) - #define MU_IID_IMMENDPOINT (&MU_IID_IMMEndpoint) - #define MU_PKEY_DEVICE_FRIENDLYNAME (&PKEY_Device_FriendlyName) - #define MU_PKEY_AUDIOENGINE_DEVICEFORMAT (&PKEY_AudioEngine_DeviceFormat) - #define MU_CLSID_MMDEVICEENUMERATOR (&MU_CLSID_MMDeviceEnumerator) - #define MU_IID_IAUDIOCLOCKADJUSTMENT (&MU_IID_IAudioClockAdjustment) - #define MU_IID_IAUDIOSESSIONCONTROL (&MU_IID_IAudioSessionControl) - #define MU_IID_IAUDIORENDERCLIENT (&MU_IID_IAudioRenderClient) - #define MU_IID_IMMDEVICEENUMERATOR (&MU_IID_IMMDeviceEnumerator) - #define MU_IID_IAUDIOCAPTURECLIENT (&MU_IID_IAudioCaptureClient) - #define MU_IID_ISIMPLEAUDIOVOLUME (&MU_IID_ISimpleAudioVolume) - #endif - - // Number of REFERENCE_TIME units per second - // One unit is equal to 100 nano seconds - #define MU_REF_TIMES_PER_SECOND 10000000 - #define MU_REF_TIMES_PER_MSECOND 10000 - -// Empty functions(stubs) which are used when library fails to load -static HRESULT CoCreateInstanceStub(REFCLSID rclsid, LPUNKNOWN *pUnkOuter, DWORD dwClsContext, REFIID riid, LPVOID *ppv) { - (void)(rclsid); - (void)(pUnkOuter); - (void)(dwClsContext); - (void)(riid); - (void)(ppv); - return S_FALSE; -} - -static HRESULT CoInitializeExStub(LPVOID pvReserved, DWORD dwCoInit) { - (void)(pvReserved); - (void)(dwCoInit); - return S_FALSE; -} - -MU_StaticFunc void MU_WIN32_DeinitSound(MU_Context *mu) { - MU_Win32 *w32 = (MU_Win32 *)mu->platform; - if (w32->audio_client) w32->audio_client->lpVtbl->Stop(w32->audio_client); - if (w32->audio_client) w32->audio_client->lpVtbl->Release(w32->audio_client); - if (w32->device_enum) w32->device_enum->lpVtbl->Release(w32->device_enum); - if (w32->device) w32->device->lpVtbl->Release(w32->device); - if (w32->audio_render_client) w32->audio_render_client->lpVtbl->Release(w32->audio_render_client); - mu->sound.initialized = false; -} - -// Load COM Library functions dynamically, -// this way sound is not necessary to run the game -MU_StaticFunc void MU_WIN32_LoadCOM(MU_Context *mu) { - MU_Win32 *w32 = (MU_Win32 *)mu->platform; - - HMODULE ole32_lib = LoadLibraryA("ole32.dll"); - if (ole32_lib) { - w32->CoCreateInstanceFunctionPointer = (CoCreateInstanceFunction *)GetProcAddress(ole32_lib, "CoCreateInstance"); - w32->CoInitializeExFunctionPointer = (CoInitializeExFunction *)GetProcAddress(ole32_lib, "CoInitializeEx"); - mu->sound.initialized = true; - } - - if (ole32_lib == 0 || w32->CoCreateInstanceFunctionPointer == 0 || w32->CoInitializeExFunctionPointer == 0) { - w32->CoCreateInstanceFunctionPointer = CoCreateInstanceStub; - w32->CoInitializeExFunctionPointer = CoInitializeExStub; - mu->sound.initialized = false; - } -} - -MU_StaticFunc DWORD MU_WIN32_SoundThread(void *parameter) { - MU_Context *mu = (MU_Context *)parameter; - MU_Win32 *w32 = (MU_Win32 *)mu->platform; - - HANDLE thread_handle = GetCurrentThread(); - SetThreadPriority(thread_handle, THREAD_PRIORITY_HIGHEST); - HANDLE buffer_ready_event = CreateEvent(0, 0, 0, 0); - if (!buffer_ready_event) { - MU_ASSERT(!"Sound thread failed"); - goto error_cleanup; - } - if (FAILED(IAudioClient_SetEventHandle(w32->audio_client, buffer_ready_event))) { - MU_ASSERT(!"Sound thread failed"); - goto error_cleanup; - } - - if (FAILED(IAudioClient_Start(w32->audio_client))) { - MU_ASSERT(!"Sound thread failed"); - goto error_cleanup; - } - for (;;) { - if (WaitForSingleObject(buffer_ready_event, INFINITE) != WAIT_OBJECT_0) { - MU_ASSERT(!"Sound thread failed"); - goto error_cleanup; - } - uint32_t padding_frame_count; - if (FAILED(IAudioClient_GetCurrentPadding(w32->audio_client, &padding_frame_count))) { - MU_ASSERT(!"Sound thread failed"); - goto error_cleanup; - } - uint32_t *samples; - uint32_t fill_frame_count = w32->buffer_frame_count - padding_frame_count; - if (FAILED(IAudioRenderClient_GetBuffer(w32->audio_render_client, fill_frame_count, (BYTE **)&samples))) { - MU_ASSERT(!"Sound thread failed"); - goto error_cleanup; - } - - // Call user callback - uint32_t sample_count_to_fill = fill_frame_count * mu->sound.number_of_channels; - mu->sound.callback((MU_Context *)mu, (uint16_t *)samples, sample_count_to_fill); - - if (FAILED(IAudioRenderClient_ReleaseBuffer(w32->audio_render_client, fill_frame_count, 0))) { - MU_ASSERT(!"Sound thread failed"); - goto error_cleanup; - } - } - return 0; -error_cleanup: - MU_WIN32_DeinitSound(mu); - return -1; -} - -MU_StaticFunc void MU_WIN32_InitWasapi(MU_Context *mu) { - REFERENCE_TIME requested_buffer_duration = MU_REF_TIMES_PER_MSECOND * 40; - MU_Win32 *w32 = (MU_Win32 *)mu->platform; - - MU_WIN32_LoadCOM(mu); - MU_ASSERT(mu->sound.initialized); - if (mu->sound.initialized == false) { - return; - } - - mu->sound.bytes_per_sample = 2; - mu->sound.number_of_channels = 2; - mu->sound.samples_per_second = 44100; - - HANDLE thread_handle; - - HRESULT hr = w32->CoInitializeExFunctionPointer(0, COINITBASE_MULTITHREADED); - if (FAILED(hr)) { - MU_ASSERT(!"Failed to initialize sound"); - goto failure_path; - } - - hr = w32->CoCreateInstanceFunctionPointer(MU_CLSID_MMDEVICEENUMERATOR, NULL, CLSCTX_ALL, MU_IID_IMMDEVICEENUMERATOR, (void **)&w32->device_enum); - if (FAILED(hr)) { - MU_ASSERT(!"Failed to initialize sound"); - goto failure_path; - } - - hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(w32->device_enum, eRender, eMultimedia, &w32->device); - if (FAILED(hr)) { - MU_ASSERT(!"Failed to initialize sound"); - goto failure_path; - } - - hr = IMMDevice_Activate(w32->device, MU_IID_IAUDIOCLIENT, CLSCTX_ALL, NULL, (void **)&w32->audio_client); - if (FAILED(hr)) { - MU_ASSERT(!"Failed to initialize sound"); - goto failure_path; - } - - WAVEFORMATEX fmt; - { - MU__ZeroMemory(&fmt, sizeof(fmt)); - fmt.wFormatTag = WAVE_FORMAT_PCM; - fmt.nChannels = mu->sound.number_of_channels; - fmt.nSamplesPerSec = mu->sound.samples_per_second; - fmt.wBitsPerSample = mu->sound.bytes_per_sample * 8; - fmt.nBlockAlign = fmt.nChannels * fmt.wBitsPerSample / 8; - fmt.nAvgBytesPerSec = fmt.nSamplesPerSec * fmt.nBlockAlign; - } - - hr = IAudioClient_Initialize( - w32->audio_client, AUDCLNT_SHAREMODE_SHARED, - AUDCLNT_STREAMFLAGS_EVENTCALLBACK | AUDCLNT_STREAMFLAGS_RATEADJUST | - AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM | AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY, - requested_buffer_duration, 0, &fmt, 0); - if (FAILED(hr)) { - MU_ASSERT(!"Failed to initialize sound"); - goto failure_path; - } - - hr = IAudioClient_GetService(w32->audio_client, MU_IID_IAUDIORENDERCLIENT, (void **)&w32->audio_render_client); - if (FAILED(hr)) { - MU_ASSERT(!"Failed to initialize sound"); - goto failure_path; - } - - hr = IAudioClient_GetBufferSize(w32->audio_client, &w32->buffer_frame_count); - if (FAILED(hr)) { - MU_ASSERT(!"Failed to initialize sound"); - goto failure_path; - } - - thread_handle = CreateThread(0, 0, MU_WIN32_SoundThread, mu, 0, 0); - if (thread_handle == INVALID_HANDLE_VALUE) { - MU_ASSERT(!"Failed to create a sound thread"); - goto failure_path; - } - - return; -failure_path: - MU_WIN32_DeinitSound(mu); -} - -#endif // _WIN32 \ No newline at end of file diff --git a/src/build_tool/standalone_libraries/multimedia.h b/src/build_tool/standalone_libraries/multimedia.h deleted file mode 100644 index 241bf09..0000000 --- a/src/build_tool/standalone_libraries/multimedia.h +++ /dev/null @@ -1,370 +0,0 @@ -#ifndef FIRST_MU_HEADER -#define FIRST_MU_HEADER -#include -#include -#include -#ifndef MU_API - #ifdef __cplusplus - #define MU_API extern "C" - #else - #define MU_API - #endif -#endif - -#ifndef MU_INLINE - #ifndef _MSC_VER - #ifdef __cplusplus - #define MU_INLINE inline - #else - #define MU_INLINE - #endif - #else - #define MU_INLINE __forceinline - #endif -#endif - -#ifndef MU_Float2 - #define MU_Float2 MU__Float2 -typedef struct MU__Float2 { - float x; - float y; -} MU__Float2; -#endif - -#ifndef MU_Int2 - #define MU_Int2 MU__Int2 -typedef struct MU__Int2 { - int x; - int y; -} MU__Int2; -#endif - -//@begin gen_structs -typedef struct MU_UTF32Result MU_UTF32Result; -typedef struct MU_UTF8Result MU_UTF8Result; -typedef struct MU_Win32 MU_Win32; -typedef struct MU_Win32_Window MU_Win32_Window; -typedef struct MU_Window_Params MU_Window_Params; -typedef struct MU_Params MU_Params; -typedef struct MU_Key_State MU_Key_State; -typedef struct MU_Mouse_State MU_Mouse_State; -typedef struct MU_DroppedFile MU_DroppedFile; -typedef struct MU_Arena MU_Arena; -typedef struct MU_Window MU_Window; -typedef struct MU_Time MU_Time; -typedef struct MU_Sound MU_Sound; -typedef struct MU_Context MU_Context; -//@end gen_structs - -typedef void *MU_glGetProcAddress(const char *); - -struct MU_Window_Params { - MU_Int2 size; - MU_Int2 pos; - char *title; - bool enable_canvas; - bool resizable; - bool borderless; - bool fps_cursor; -}; - -struct MU_Params { - void *memory; - size_t cap; - - bool enable_opengl; - int opengl_major; - int opengl_minor; - - double delta_time; - MU_Window_Params window; // this controls window when calling MU_Start - void (*sound_callback)(MU_Context *mu, uint16_t *buffer, uint32_t samples_to_fill); -}; - -struct MU_Key_State { - bool down; - bool press; - bool unpress; - bool raw_press; -}; - -typedef enum MU_Key { - MU_KEY_INVALID, - MU_KEY_ESCAPE, - MU_KEY_ENTER, - MU_KEY_TAB, - MU_KEY_BACKSPACE, - MU_KEY_INSERT, - MU_KEY_DELETE, - MU_KEY_RIGHT, - MU_KEY_LEFT, - MU_KEY_DOWN, - MU_KEY_UP, - MU_KEY_PAGE_UP, - MU_KEY_PAGE_DOWN, - MU_KEY_HOME, - MU_KEY_END, - MU_KEY_F1, - MU_KEY_F2, - MU_KEY_F3, - MU_KEY_F4, - MU_KEY_F5, - MU_KEY_F6, - MU_KEY_F7, - MU_KEY_F8, - MU_KEY_F9, - MU_KEY_F10, - MU_KEY_F11, - MU_KEY_F12, - MU_KEY_SPACE = 32, - MU_KEY_APOSTROPHE = 39, - MU_KEY_PLUS = 43, - MU_KEY_COMMA = 44, - MU_KEY_MINUS = 45, - MU_KEY_PERIOD = 46, - MU_KEY_SLASH = 47, - MU_KEY_0 = 48, - MU_KEY_1 = 49, - MU_KEY_2 = 50, - MU_KEY_3 = 51, - MU_KEY_4 = 52, - MU_KEY_5 = 53, - MU_KEY_6 = 54, - MU_KEY_7 = 55, - MU_KEY_8 = 56, - MU_KEY_9 = 57, - MU_KEY_SEMICOLON = 59, - MU_KEY_EQUAL = 61, - MU_KEY_A = 65, - MU_KEY_B = 66, - MU_KEY_C = 67, - MU_KEY_D = 68, - MU_KEY_E = 69, - MU_KEY_F = 70, - MU_KEY_G = 71, - MU_KEY_H = 72, - MU_KEY_I = 73, - MU_KEY_J = 74, - MU_KEY_K = 75, - MU_KEY_L = 76, - MU_KEY_M = 77, - MU_KEY_N = 78, - MU_KEY_O = 79, - MU_KEY_P = 80, - MU_KEY_Q = 81, - MU_KEY_R = 82, - MU_KEY_S = 83, - MU_KEY_T = 84, - MU_KEY_U = 85, - MU_KEY_V = 86, - MU_KEY_W = 87, - MU_KEY_X = 88, - MU_KEY_Y = 89, - MU_KEY_Z = 90, - MU_KEY_LEFT_BRACKET = 91, - MU_KEY_BACKSLASH = 92, - MU_KEY_RIGHT_BRACKET = 93, - MU_KEY_GRAVE_ACCENT = 96, - MU_KEY_F13, - MU_KEY_F14, - MU_KEY_F15, - MU_KEY_F16, - MU_KEY_F17, - MU_KEY_F18, - MU_KEY_F19, - MU_KEY_F20, - MU_KEY_F21, - MU_KEY_F22, - MU_KEY_F23, - MU_KEY_F24, - MU_KEY_KP_0, - MU_KEY_KP_1, - MU_KEY_KP_2, - MU_KEY_KP_3, - MU_KEY_KP_4, - MU_KEY_KP_5, - MU_KEY_KP_6, - MU_KEY_KP_7, - MU_KEY_KP_8, - MU_KEY_KP_9, - MU_KEY_KP_DECIMAL, - MU_KEY_KP_DIVIDE, - MU_KEY_KP_MULTIPLY, - MU_KEY_KP_SUBTRACT, - MU_KEY_KP_ADD, - MU_KEY_KP_ENTER, - MU_KEY_LEFT_SHIFT, - MU_KEY_LEFT_CONTROL, - MU_KEY_LEFT_ALT, - MU_KEY_LEFT_SUPER, - MU_KEY_RIGHT_SHIFT, - MU_KEY_RIGHT_CONTROL, - MU_KEY_RIGHT_ALT, - MU_KEY_RIGHT_SUPER, - MU_KEY_CAPS_LOCK, - MU_KEY_SCROLL_LOCK, - MU_KEY_NUM_LOCK, - MU_KEY_PRINT_SCREEN, - MU_KEY_PAUSE, - MU_KEY_SHIFT, - MU_KEY_CONTROL, - MU_KEY_COUNT, -} MU_Key; - -struct MU_Mouse_State { - MU_Int2 pos; - MU_Float2 posf; - MU_Int2 delta_pos; - MU_Float2 delta_pos_normalized; - MU_Key_State left; - MU_Key_State middle; - MU_Key_State right; - float delta_wheel; // @todo: add smooth delta? -}; - -struct MU_DroppedFile { - MU_DroppedFile *next; - char *filename; // null terminated - int filename_size; -}; - -struct MU_Arena { - char *memory; - size_t len; - size_t cap; -}; - -// Most of the fields in the window struct are read only. They are updated -// in appropriate update functions. The window should belong to the MU_Context -// but you get access to the information. -struct MU_Window { - MU_Int2 size; - MU_Float2 sizef; - MU_Int2 pos; - MU_Float2 posf; - float dpi_scale; - bool is_fullscreen; - bool is_fps_mode; - bool is_focused; - bool change_cursor_on_mouse_hold; // @in @out - uint64_t processed_events_this_frame; - bool should_render; // @in @out this is false on first frame but it doesn't matter cause it shouldnt be rendered - - MU_DroppedFile *first_dropped_file; - - uint32_t *canvas; - bool canvas_enabled; // @in @out - - MU_Mouse_State mouse; - MU_Key_State key[MU_KEY_COUNT]; - - uint32_t user_text32[32]; - int user_text32_count; - - char user_text8[32]; - int user_text8_count; - - MU_Window *next; - void *handle; - void *platform; -}; - -struct MU_Time { - double app_start; - double frame_start; - - double update; - double update_total; - - double delta; - float deltaf; - double total; - float totalf; -}; - -struct MU_Sound { - bool initialized; - unsigned samples_per_second; - unsigned number_of_channels; - unsigned bytes_per_sample; - void (*callback)(MU_Context *mu, uint16_t *buffer, uint32_t samples_to_fill); -}; - -struct MU_Context { - bool quit; - - MU_Sound sound; - MU_Time time; - bool first_frame; - int _MU_Update_count; - size_t frame; - size_t consecutive_missed_frames; - size_t total_missed_frames; - - MU_Int2 primary_monitor_size; - bool opengl_initialized; - int opengl_major; - int opengl_minor; - void *(*gl_get_proc_address)(const char *str); - - MU_Params params; - MU_Window *window; - MU_Window *all_windows; - MU_Arena perm_arena; - MU_Arena frame_arena; // Reset at beginning of MU_Update - void *platform; -}; - -//@begin gen_api_funcs -MU_API void MU_Quit(MU_Context *mu); -MU_API void MU_DefaultSoundCallback(MU_Context *mu, uint16_t *buffer, uint32_t samples_to_fill); -MU_API double MU_GetTime(void); -MU_API void MU_ToggleFPSMode(MU_Window *window); -MU_API void MU_DisableFPSMode(MU_Window *window); -MU_API void MU_EnableFPSMode(MU_Window *window); -MU_API void MU_ToggleFullscreen(MU_Window *window); -MU_API void MU_Init(MU_Context *mu, MU_Params params, size_t len); -MU_API MU_Window *MU_AddWindow(MU_Context *mu, MU_Window_Params params); -MU_API void MU_InitWindow(MU_Context *mu, MU_Window *window, MU_Window_Params params); -MU_API MU_Context *MU_Start(MU_Params params); -MU_API bool MU_Update(MU_Context *mu); -//@end gen_api_funcs - -/* @! In the future, api for processing messages manually - - while(true) { - MU_Event event; - while (mu_get_event_blocking(&event)) { - switch(event.kind) { - - } - } - } - -typedef int MU_Modifier; -enum MU_Modifier { - MU_MODIFIER_SHIFT = 0x1, // left or right shift key - MU_MODIFIER_CTRL = 0x2, // left or right control key - MU_MODIFIER_ALT = 0x4, // left or right alt key - MU_MODIFIER_SUPER = 0x8, // left or right 'super' key - MU_MODIFIER_LMB = 0x100, // left mouse button - MU_MODIFIER_RMB = 0x200, // right mouse button - MU_MODIFIER_MMB = 0x400, // middle mouse button -}; - -typedef enum MU_Event_Kind { - MU_EVENT_KIND_INVALID, - MU_EVENT_KIND_KEY_DOWN, - MU_EVENT_KIND_KEY_UP, - MU_EVENT_KIND_MOUSE_MOVE, -} MU_Event_Kind; - -typedef struct MU_Event { - MU_Event_Kind kind; - MU_Modifier modifier; - MU_Key key; -} MU_Event; - - - */ -#endif \ No newline at end of file diff --git a/src/build_tool/standalone_libraries/preproc_env.h b/src/build_tool/standalone_libraries/preproc_env.h deleted file mode 100644 index 77b8084..0000000 --- a/src/build_tool/standalone_libraries/preproc_env.h +++ /dev/null @@ -1,119 +0,0 @@ -#ifndef FIRST_ENV_HEADER -#define FIRST_ENV_HEADER -#ifndef _CRT_SECURE_NO_WARNINGS - #define _CRT_SECURE_NO_WARNINGS -#endif - -#if defined(__APPLE__) && defined(__MACH__) - #define OS_MAC 1 -#elif defined(_WIN32) - #define OS_WINDOWS 1 -#elif defined(__linux__) - #define OS_POSIX 1 - #define OS_LINUX 1 -#elif OS_WASM -#else - #error Unsupported platform -#endif - -#if defined(__clang__) - #define COMPILER_CLANG 1 -#elif defined(__GNUC__) || defined(__GNUG__) - #define COMPILER_GCC 1 -#elif defined(_MSC_VER) - #define COMPILER_MSVC 1 -#elif defined(__TINYC__) - #define COMPILER_TCC 1 -#else - #error Unsupported compiler -#endif - -#ifdef __cplusplus - #define LANG_CPP 1 -#else - #define LANG_C 1 -#endif - -#ifndef OS_MAC - #define OS_MAC 0 -#endif - -#ifndef OS_WINDOWS - #define OS_WINDOWS 0 -#endif - -#ifndef OS_LINUX - #define OS_LINUX 0 -#endif - -#ifndef OS_POSIX - #define OS_POSIX 0 -#endif - -#ifndef COMPILER_MSVC - #define COMPILER_MSVC 0 -#endif - -#ifndef COMPILER_CLANG - #define COMPILER_CLANG 0 -#endif - -#ifndef COMPILER_GCC - #define COMPILER_GCC 0 -#endif - -#ifndef COMPILER_TCC - #define COMPILER_TCC 0 -#endif - -#ifndef LANG_CPP - #define LANG_CPP 0 -#endif - -#ifndef LANG_C - #define LANG_C 0 -#endif - -#if COMPILER_MSVC - #define FORCE_INLINE __forceinline -#elif COMPILER_GCC || COMPILER_CLANG - #define FORCE_INLINE __attribute__((always_inline)) inline -#else - #define FORCE_INLINE inline -#endif - -#if OS_MAC - #define IF_MAC(x) x -#else - #define IF_MAC(x) -#endif - -#if OS_WINDOWS - #define IF_WINDOWS(x) x - #define IF_WINDOWS_ELSE(x, y) x -#else - #define IF_WINDOWS(x) - #define IF_WINDOWS_ELSE(x, y) y -#endif - -#if OS_LINUX - #define IF_LINUX(x) x - #define IF_LINUX_ELSE(x, y) x -#else - #define IF_LINUX(x) - #define IF_LINUX_ELSE(x, y) y -#endif - -#if OS_WINDOWS - #define OS_NAME "windows" -#elif OS_LINUX - #define OS_NAME "linux" -#elif OS_MAC - #define OS_NAME "mac_os" -#elif OS_WASM - #define OS_NAME "wasm" -#else - #error couldnt figure out OS -#endif - -#endif \ No newline at end of file diff --git a/src/build_tool/standalone_libraries/regex.c b/src/build_tool/standalone_libraries/regex.c deleted file mode 100644 index 3fd3e4e..0000000 --- a/src/build_tool/standalone_libraries/regex.c +++ /dev/null @@ -1,558 +0,0 @@ -#include "regex.h" - -#ifndef RE_ASSERT - #include - #define RE_ASSERT(x) assert(x) -#endif - -#ifndef RE_STRICT_ASSERT - #define RE_STRICT_ASSERT RE_ASSERT -#endif - -#ifndef RE_MemoryZero - #include - #define RE_MemoryZero(p, size) memset(p, 0, size) -#endif - -typedef struct RE__Arena { - char *buff; - RE_Int len; - RE_Int cap; -} RE_Arena; - -struct RE_String { - char *str; - RE_Int len; -}; - -struct RE_Utf32Result { - uint32_t out_str; - int advance; - int error; -}; -static RE_Regex RE_NullRegex; -static char RE_NullChar; - -struct RE_Parser { - RE_String string; - RE_Int i; - RE_Regex *first; - RE_Regex *last; -}; -RE_API RE_Regex *RE1_ParseEx(RE_Arena *arena, char *string); -RE_API RE_Regex *RE2_ParseEx(RE_Arena *arena, char *string, RE_Int len); - -RE_StaticFunc void *RE_PushSize(RE_Arena *arena, RE_Int size) { - if (arena->len + size > arena->cap) { - RE_ASSERT(!"RE_Regex: Not enough memory passed for this regex"); - } - void *result = arena->buff + arena->len; - arena->len += size; - return result; -} - -RE_StaticFunc RE_Arena RE_ArenaFromBuffer(char *buff, RE_Int size) { - RE_Arena result; - result.len = 0; - result.cap = size; - result.buff = buff; - return result; -} - -RE_StaticFunc RE_String RE_Skip(RE_String string, RE_Int len) { - if (len > string.len) len = string.len; - RE_Int remain = string.len - len; - RE_String result; - result.str = string.str + len; - result.len = remain; - return result; -} - -RE_StaticFunc RE_Int RE_StringLength(char *string) { - RE_Int len = 0; - while (*string++ != 0) len++; - return len; -} - -RE_StaticFunc RE_Utf32Result RE_ConvertUTF8ToUTF32(char *c, int max_advance) { - RE_Utf32Result result; - RE_MemoryZero(&result, sizeof(result)); - - if ((c[0] & 0x80) == 0) { // Check if leftmost zero of first byte is unset - if (max_advance >= 1) { - result.out_str = c[0]; - result.advance = 1; - } - else result.error = 1; - } - - else if ((c[0] & 0xe0) == 0xc0) { - if ((c[1] & 0xc0) == 0x80) { // Continuation byte required - if (max_advance >= 2) { - result.out_str = (uint32_t)(c[0] & 0x1f) << 6u | (c[1] & 0x3f); - result.advance = 2; - } - else result.error = 2; - } - else result.error = 2; - } - - else if ((c[0] & 0xf0) == 0xe0) { - if ((c[1] & 0xc0) == 0x80 && (c[2] & 0xc0) == 0x80) { // Two continuation bytes required - if (max_advance >= 3) { - result.out_str = (uint32_t)(c[0] & 0xf) << 12u | (uint32_t)(c[1] & 0x3f) << 6u | (c[2] & 0x3f); - result.advance = 3; - } - else result.error = 3; - } - else result.error = 3; - } - - else if ((c[0] & 0xf8) == 0xf0) { - if ((c[1] & 0xc0) == 0x80 && (c[2] & 0xc0) == 0x80 && (c[3] & 0xc0) == 0x80) { // Three continuation bytes required - if (max_advance >= 4) { - result.out_str = (uint32_t)(c[0] & 0xf) << 18u | (uint32_t)(c[1] & 0x3f) << 12u | (uint32_t)(c[2] & 0x3f) << 6u | (uint32_t)(c[3] & 0x3f); - result.advance = 4; - } - else result.error = 4; - } - else result.error = 4; - } - else result.error = 4; - - return result; -} - -#define RE_DLL_QUEUE_REMOVE(first, last, node) \ - do { \ - if ((first) == (last)) { \ - (first) = (last) = 0; \ - } \ - else if ((last) == (node)) { \ - (last) = (last)->prev; \ - (last)->next = 0; \ - } \ - else if ((first) == (node)) { \ - (first) = (first)->next; \ - (first)->prev = 0; \ - } \ - else { \ - (node)->prev->next = (node)->next; \ - (node)->next->prev = (node)->prev; \ - } \ - if (node) (node)->prev = 0; \ - } while (0) - -#define RE_DLL_QUEUE_ADD(f, l, node) \ - do { \ - if ((f) == 0) { \ - (f) = (l) = (node); \ - (node)->prev = 0; \ - (node)->next = 0; \ - } \ - else { \ - (l)->next = (node); \ - (node)->prev = (l); \ - (node)->next = 0; \ - (l) = (node); \ - } \ - } while (0) - -RE_StaticFunc char *RE_GetP(RE_Parser *P) { - if (P->i >= P->string.len) return &RE_NullChar; - return P->string.str + P->i; -} - -RE_StaticFunc char RE_Get(RE_Parser *P) { - if (P->i >= P->string.len) return 0; - return P->string.str[P->i]; -} - -RE_StaticFunc char RE_Get1(RE_Parser *P) { - if ((P->i + 1) >= P->string.len || P->i >= P->string.len) return 0; - return P->string.str[P->i + 1]; -} - -RE_StaticFunc void RE_Advance(RE_Parser *P) { - if (P->i >= P->string.len) return; - P->i += 1; -} - -RE_StaticFunc RE_Regex *RE_ParseSingle(RE_Parser *P, RE_Arena *arena, RE_Regex **first, RE_Regex **last) { - RE_Regex *regex = (RE_Regex *)RE_PushSize(arena, sizeof(RE_Regex)); - RE_MemoryZero(regex, sizeof(*regex)); - char *c = RE_GetP(P); - RE_Int size_left = P->string.len - P->i; - RE_Advance(P); - switch (*c) { - case ')': RE_STRICT_ASSERT(regex->kind != RE_MATCH_NULL && "Invalid regex syntax, ')' appeared without matching '('"); break; - case '\0': RE_STRICT_ASSERT(regex->kind != RE_MATCH_NULL && "Invalid regex syntax, reached end of string obruptly"); break; - case '.': regex->kind = RE_MATCH_ANY; break; - case '^': regex->kind = RE_MATCH_FRONT; break; - case '$': regex->kind = RE_MATCH_BACK; break; - - case '*': { - if (*last) { - regex->kind = RE_MATCH_ZERO_OR_MORE; - RE_Regex *prev = *last; - RE_DLL_QUEUE_REMOVE(*first, *last, *last); - regex->child = prev; - } - else { - RE_STRICT_ASSERT(!"Invalid regex syntax, '*' is not attached to anything"); - } - } break; - - case '+': { - if (*last) { - regex->kind = RE_MATCH_ONE_OR_MORE; - RE_Regex *prev = *last; - RE_DLL_QUEUE_REMOVE(*first, *last, *last); - regex->child = prev; - } - else { - RE_STRICT_ASSERT(!"Invalid regex syntax, '+' is not attached to anything"); - } - } break; - - case '?': { - if (*last) { - regex->kind = RE_MATCH_ZERO_OR_ONE; - RE_Regex *prev = *last; - RE_DLL_QUEUE_REMOVE(*first, *last, *last); - regex->child = prev; - } - else { - RE_STRICT_ASSERT(!"Invalid regex syntax, '?' is not attached to anything"); - } - } break; - - case '[': { - regex->kind = RE_MATCH_SELECTED; - if (RE_Get(P) == '^') { - regex->kind = RE_MATCH_NOT_SELECTED; - RE_Advance(P); - } - while (RE_Get(P) != 0 && RE_Get(P) != ']') { - RE_Regex *r = RE_ParseSingle(P, arena, ®ex->group.first, ®ex->group.last); - if (r->kind == RE_MATCH_NULL) { - regex->kind = RE_MATCH_NULL; - break; - } - if (r->kind == RE_MATCH_WORD && RE_Get(P) == '-') { - char word = RE_Get1(P); - if (word >= '!' && word <= '~') { - RE_Advance(P); - RE_Regex *right = RE_ParseSingle(P, arena, 0, 0); - if (right->kind == RE_MATCH_NULL) { - regex->kind = RE_MATCH_NULL; - break; - } - RE_ASSERT(right->kind == RE_MATCH_WORD); - RE_ASSERT(right->word == word); - r->word_min = word > r->word ? r->word : word; - r->word_max = word > r->word ? word : r->word; - r->kind = RE_MATCH_RANGE; - } - } - RE_DLL_QUEUE_ADD(regex->group.first, regex->group.last, r); - } - RE_Advance(P); - } break; - - case '(': { - regex->kind = RE_MATCH_GROUP; - while (RE_Get(P) != 0 && RE_Get(P) != ')') { - RE_Regex *r = RE_ParseSingle(P, arena, ®ex->group.first, ®ex->group.last); - if (r->kind == RE_MATCH_NULL) { - regex->kind = RE_MATCH_NULL; - break; - } - RE_DLL_QUEUE_ADD(regex->group.first, regex->group.last, r); - } - RE_Advance(P); - } break; - - case '|': { - if (*last) { - regex->kind = RE_MATCH_OR; - RE_Regex *left = *last; - RE_Regex *right = RE_ParseSingle(P, arena, first, last); - if (right->kind == RE_MATCH_NULL) { - regex->kind = RE_MATCH_NULL; - RE_STRICT_ASSERT(!"Invalid regex syntax, '|' appeared but it's right option is invalid"); - } - else { - RE_DLL_QUEUE_REMOVE(*first, *last, left); - regex->left = left; - regex->right = right; - } - } - } break; - - case '\\': { - regex->kind = RE_MATCH_WORD; - regex->word = RE_Get(P); - switch (regex->word) { - case 'n': regex->word = '\n'; break; - case 't': regex->word = '\t'; break; - case 'r': regex->word = '\r'; break; - case 'w': regex->kind = RE_MATCH_ANY_WORD; break; - case 'd': regex->kind = RE_MATCH_ANY_DIGIT; break; - case 's': regex->kind = RE_MATCH_ANY_WHITESPACE; break; - case '\0': { - regex->kind = RE_MATCH_NULL; - RE_STRICT_ASSERT(!"Invalid regex syntax, escape '\\' followed by end of string"); - } break; - } - RE_Advance(P); - } break; - - default: { - regex->kind = RE_MATCH_WORD; - RE_Utf32Result decode = RE_ConvertUTF8ToUTF32(c, (int)size_left); - if (decode.error) { - regex->kind = RE_MATCH_NULL; - RE_STRICT_ASSERT(!"Invalid regex syntax, string is an invalid utf8"); - } - else { - regex->word32 = decode.out_str; - for (int i = 0; i < decode.advance - 1; i += 1) - RE_Advance(P); - } - } - } - - return regex; -} - -RE_StaticFunc RE_Int RE_MatchSingle(RE_Regex *regex, RE_String string) { - switch (regex->kind) { - case RE_MATCH_ZERO_OR_MORE: { - RE_Int result = 0; - for (; string.len;) { - // @idea - // In this case (asd)*(asd) we just quit with 0 - // when we meet asd - // Maybe this should be collapsed in parsing stage/ - // asd should be combined with *asd etc. cause - // now it's a bit weird but I dont know why you would - // type that in the first place - if (RE_MatchSingle(regex->next, string) != -1) break; - RE_Int index = RE_MatchSingle(regex->child, string); - if (index == -1) break; - string = RE_Skip(string, index); - result += index; - } - return result; - } break; - - case RE_MATCH_ONE_OR_MORE: { - RE_Int result = 0; - for (; string.len;) { - RE_Int index = RE_MatchSingle(regex->child, string); - if (index == -1) break; - string = RE_Skip(string, index); - result += index; - } - - if (result == 0) return -1; - return result; - } break; - - case RE_MATCH_OR: { - RE_Int right = RE_MatchSingle(regex->right, string); - RE_Int left = RE_MatchSingle(regex->left, string); - if (left > right) return left; - else return right; - } break; - - case RE_MATCH_GROUP: { - RE_Int result = 0; - for (RE_Regex *it = regex->group.first; it; it = it->next) { - if (string.len == 0) return -1; - RE_Int index = RE_MatchSingle(it, string); - if (index == -1) return -1; - result += index; - string = RE_Skip(string, index); - } - return result; - } break; - - case RE_MATCH_NOT_SELECTED: { - for (RE_Regex *it = regex->group.first; it; it = it->next) { - RE_Int index = RE_MatchSingle(it, string); - if (index != -1) return -1; - } - RE_Utf32Result decode = RE_ConvertUTF8ToUTF32(string.str, (int)string.len); - if (decode.error) return -1; - return decode.advance; - } break; - - case RE_MATCH_SELECTED: { - for (RE_Regex *it = regex->group.first; it; it = it->next) { - RE_Int index = RE_MatchSingle(it, string); - if (index != -1) return index; - } - return -1; - } break; - - case RE_MATCH_RANGE: { - if (string.str[0] >= regex->word_min && string.str[0] <= regex->word_max) - return 1; - return -1; - } - - case RE_MATCH_ANY_WORD: { - if ((string.str[0] >= 'a' && string.str[0] <= 'z') || (string.str[0] >= 'A' && string.str[0] <= 'Z')) - return 1; - return -1; - } break; - - case RE_MATCH_ANY_DIGIT: { - if (string.str[0] >= '0' && string.str[0] <= '9') - return 1; - return -1; - } break; - - case RE_MATCH_ANY_WHITESPACE: { - if (string.str[0] == ' ' || string.str[0] == '\n' || string.str[0] == '\t' || string.str[0] == '\r') - return 1; - return -1; - } break; - - case RE_MATCH_ANY: { - if (string.str[0] != '\n') { - return 1; - } - return -1; - } break; - - case RE_MATCH_ZERO_OR_ONE: { - RE_Int index = RE_MatchSingle(regex->child, string); - if (index == -1) index = 0; - return index; - } break; - - case RE_MATCH_WORD: { - RE_Utf32Result decode = RE_ConvertUTF8ToUTF32(string.str, (int)string.len); - if (decode.error) return -1; - if (decode.out_str == regex->word32) return decode.advance; - return -1; - } break; - - case RE_MATCH_BACK: - case RE_MATCH_NULL: return -1; - - default: RE_ASSERT(!"Invalid codepath"); - } - return -1; -} - -RE_API bool RE1_AreEqual(char *regex, char *string) { - char buff[4096]; - RE_Regex *re = RE1_Parse(buff, sizeof(buff), regex); - bool result = RE3_AreEqual(re, string, RE_StringLength(string)); - return result; -} - -RE_API bool RE2_AreEqual(RE_Regex *regex, char *string) { - return RE3_AreEqual(regex, string, RE_StringLength(string)); -} - -RE_API bool RE3_AreEqual(RE_Regex *regex, char *string, RE_Int len) { - RE_Int result = RE3_MatchFront(regex, string, len, string); - return result == len ? true : false; -} - -RE_API RE_Match RE1_Find(char *regex, char *string) { - char buff[4096]; - RE_Regex *re = RE1_Parse(buff, sizeof(buff), regex); - RE_Match result = RE2_Find(re, string); - return result; -} - -RE_API RE_Match RE2_Find(RE_Regex *regex, char *string) { - return RE3_Find(regex, string, RE_StringLength(string)); -} - -RE_API RE_Match RE3_Find(RE_Regex *regex, char *string, RE_Int len) { - RE_Match result; - for (RE_Int i = 0; i < len; i += 1) { - result.size = RE3_MatchFront(regex, string + i, len - i, string); - if (result.size != -1) { - result.pos = i; - return result; - } - } - - result.size = 0; - result.pos = -1; - return result; -} - -RE_API RE_Match RE2_FindAgain(RE_Regex *regex, char *string, RE_Match prev_match) { - return RE2_Find(regex, string + prev_match.pos); -} - -RE_API RE_Match RE3_FindAgain(RE_Regex *regex, char *string, RE_Int len, RE_Match prev_match) { - return RE3_Find(regex, string + prev_match.pos, len - prev_match.pos); -} - -RE_API RE_Int RE3_MatchFront(RE_Regex *regex, char *string, RE_Int len, char *string_front) { - RE_String re_string; - re_string.str = string; - re_string.len = len; - RE_Int submatch_len = 0; - for (RE_Regex *it = regex; it; it = it->next) { - if (it->kind == RE_MATCH_FRONT) { - if (re_string.str == string_front) - continue; - return -1; - } - if (it->kind == RE_MATCH_BACK) { - if (re_string.len == 0) - continue; - return -1; - } - - RE_Int index = RE_MatchSingle(it, re_string); - if (index == -1) return -1; - re_string = RE_Skip(re_string, index); - submatch_len += index; - } - return submatch_len; -} - -RE_API RE_Regex *RE1_ParseEx(RE_Arena *arena, char *string) { - return RE2_ParseEx(arena, string, RE_StringLength(string)); -} - -RE_API RE_Regex *RE2_ParseEx(RE_Arena *arena, char *string, RE_Int len) { - RE_Parser P; - RE_MemoryZero(&P, sizeof(P)); - P.string.str = string; - P.string.len = len; - - for (; P.i < P.string.len;) { - RE_Regex *regex = RE_ParseSingle(&P, arena, &P.first, &P.last); - RE_DLL_QUEUE_ADD(P.first, P.last, regex); - if (regex->kind == RE_MATCH_NULL) { - P.first = &RE_NullRegex; - break; - } - } - return P.first; -} - -RE_API RE_Regex *RE1_Parse(char *buff, RE_Int buffsize, char *string) { - RE_Arena arena = RE_ArenaFromBuffer(buff, buffsize); - RE_Regex *result = RE1_ParseEx(&arena, string); - return result; -} - -RE_API RE_Regex *RE2_Parse(char *buff, RE_Int buffsize, char *string, RE_Int len) { - RE_Arena arena = RE_ArenaFromBuffer(buff, buffsize); - RE_Regex *result = RE2_ParseEx(&arena, string, len); - return result; -} diff --git a/src/build_tool/standalone_libraries/regex.h b/src/build_tool/standalone_libraries/regex.h deleted file mode 100644 index aca1448..0000000 --- a/src/build_tool/standalone_libraries/regex.h +++ /dev/null @@ -1,95 +0,0 @@ -#ifndef FIRST_REGEX_HEADER -#define FIRST_REGEX_HEADER -#include -#include - -#ifndef RE_Int - #define RE_Int int64_t -#endif - -#ifndef RE_API - #ifdef __cplusplus - #define RE_API extern "C" - #else - #define RE_API - #endif -#endif - -#ifndef RE_StaticFunc - #if defined(__GNUC__) || defined(__clang__) - #define RE_StaticFunc __attribute__((unused)) static - #else - #define RE_StaticFunc static - #endif -#endif - -typedef struct RE_String RE_String; -typedef struct RE_Utf32Result RE_Utf32Result; -typedef struct RE_Parser RE_Parser; -typedef struct RE_Regex RE_Regex; -typedef struct RE_Match RE_Match; - -/* @todo -Add \W \D \S oppsites -*/ - -typedef enum RE_MatchKind { - RE_MATCH_NULL, - RE_MATCH_FRONT, - RE_MATCH_BACK, - RE_MATCH_WORD, - RE_MATCH_OR, - RE_MATCH_GROUP, - RE_MATCH_SELECTED, - RE_MATCH_NOT_SELECTED, - RE_MATCH_RANGE, - RE_MATCH_ANY, - RE_MATCH_ANY_WORD, - RE_MATCH_ANY_DIGIT, - RE_MATCH_ANY_WHITESPACE, - RE_MATCH_ONE_OR_MORE, - RE_MATCH_ZERO_OR_MORE, - RE_MATCH_ZERO_OR_ONE, -} RE_MatchKind; - -struct RE_Regex { - RE_MatchKind kind; - RE_Regex *next; - RE_Regex *prev; - - union { - struct { - char word_min; - char word_max; - }; - char word; - uint32_t word32; - RE_Regex *child; - struct { - RE_Regex *left; - RE_Regex *right; - }; - struct { - RE_Regex *first; - RE_Regex *last; - } group; - }; -}; - -struct RE_Match { - RE_Int pos; - RE_Int size; -}; - -RE_API bool RE1_AreEqual(char *regex, char *string); -RE_API bool RE2_AreEqual(RE_Regex *regex, char *string); -RE_API bool RE3_AreEqual(RE_Regex *regex, char *string, RE_Int len); -RE_API RE_Match RE1_Find(char *regex, char *string); -RE_API RE_Match RE2_Find(RE_Regex *regex, char *string); -RE_API RE_Match RE3_Find(RE_Regex *regex, char *string, RE_Int len); -RE_API RE_Match RE2_FindAgain(RE_Regex *regex, char *string, RE_Match prev_match); -RE_API RE_Match RE3_FindAgain(RE_Regex *regex, char *string, RE_Int len, RE_Match prev_match); -RE_API RE_Int RE3_MatchFront(RE_Regex *regex, char *string, RE_Int len, char *string_front); -RE_API RE_Regex *RE1_Parse(char *buff, RE_Int buffsize, char *string); -RE_API RE_Regex *RE2_Parse(char *buff, RE_Int buffsize, char *string, RE_Int len); -#endif \ No newline at end of file diff --git a/src/build_tool/standalone_libraries/stb_sprintf.c b/src/build_tool/standalone_libraries/stb_sprintf.c deleted file mode 100644 index c6b7a25..0000000 --- a/src/build_tool/standalone_libraries/stb_sprintf.c +++ /dev/null @@ -1,1669 +0,0 @@ - -#define stbsp__uint32 unsigned int -#define stbsp__int32 signed int - -#ifdef _MSC_VER - #define stbsp__uint64 unsigned __int64 - #define stbsp__int64 signed __int64 -#else - #define stbsp__uint64 unsigned long long - #define stbsp__int64 signed long long -#endif -#define stbsp__uint16 unsigned short - -#ifndef stbsp__uintptr - #if defined(__ppc64__) || defined(__powerpc64__) || defined(__aarch64__) || defined(_M_X64) || defined(__x86_64__) || defined(__x86_64) || defined(__s390x__) - #define stbsp__uintptr stbsp__uint64 - #else - #define stbsp__uintptr stbsp__uint32 - #endif -#endif - -#ifndef STB_SPRINTF_MSVC_MODE // used for MSVC2013 and earlier (MSVC2015 matches GCC) - #if defined(_MSC_VER) && (_MSC_VER < 1900) - #define STB_SPRINTF_MSVC_MODE - #endif -#endif - -#ifdef STB_SPRINTF_NOUNALIGNED // define this before inclusion to force stbsp_sprintf to always use aligned accesses - #define STBSP__UNALIGNED(code) -#else - #define STBSP__UNALIGNED(code) code -#endif - -#ifndef STB_SPRINTF_NOFLOAT -// internal float utility functions -static stbsp__int32 stbsp__real_to_str(char const **start, stbsp__uint32 *len, char *out, stbsp__int32 *decimal_pos, double value, stbsp__uint32 frac_digits); -static stbsp__int32 stbsp__real_to_parts(stbsp__int64 *bits, stbsp__int32 *expo, double value); - #define STBSP__SPECIAL 0x7000 -#endif - -static char stbsp__period = '.'; -static char stbsp__comma = ','; -static struct -{ - short temp; // force next field to be 2-byte aligned - char pair[201]; -} stbsp__digitpair = - { - 0, - "00010203040506070809101112131415161718192021222324" - "25262728293031323334353637383940414243444546474849" - "50515253545556575859606162636465666768697071727374" - "75767778798081828384858687888990919293949596979899"}; - -STBSP__PUBLICDEF void STB_SPRINTF_DECORATE(set_separators)(char pcomma, char pperiod) { - stbsp__period = pperiod; - stbsp__comma = pcomma; -} - -#define STBSP__LEFTJUST 1 -#define STBSP__LEADINGPLUS 2 -#define STBSP__LEADINGSPACE 4 -#define STBSP__LEADING_0X 8 -#define STBSP__LEADINGZERO 16 -#define STBSP__INTMAX 32 -#define STBSP__TRIPLET_COMMA 64 -#define STBSP__NEGATIVE 128 -#define STBSP__METRIC_SUFFIX 256 -#define STBSP__HALFWIDTH 512 -#define STBSP__METRIC_NOSPACE 1024 -#define STBSP__METRIC_1024 2048 -#define STBSP__METRIC_JEDEC 4096 - -static void stbsp__lead_sign(stbsp__uint32 fl, char *sign) { - sign[0] = 0; - if (fl & STBSP__NEGATIVE) { - sign[0] = 1; - sign[1] = '-'; - } - else if (fl & STBSP__LEADINGSPACE) { - sign[0] = 1; - sign[1] = ' '; - } - else if (fl & STBSP__LEADINGPLUS) { - sign[0] = 1; - sign[1] = '+'; - } -} - -static STBSP__ASAN stbsp__uint32 stbsp__strlen_limited(char const *s, stbsp__uint32 limit) { - char const *sn = s; - - // get up to 4-byte alignment - for (;;) { - if (((stbsp__uintptr)sn & 3) == 0) - break; - - if (!limit || *sn == 0) - return (stbsp__uint32)(sn - s); - - ++sn; - --limit; - } - - // scan over 4 bytes at a time to find terminating 0 - // this will intentionally scan up to 3 bytes past the end of buffers, - // but becase it works 4B aligned, it will never cross page boundaries - // (hence the STBSP__ASAN markup; the over-read here is intentional - // and harmless) - while (limit >= 4) { - stbsp__uint32 v = *(stbsp__uint32 *)sn; - // bit hack to find if there's a 0 byte in there - if ((v - 0x01010101) & (~v) & 0x80808080UL) - break; - - sn += 4; - limit -= 4; - } - - // handle the last few characters to find actual size - while (limit && *sn) { - ++sn; - --limit; - } - - return (stbsp__uint32)(sn - s); -} - -STBSP__PUBLICDEF int STB_SPRINTF_DECORATE(vsprintfcb)(STBSP_SPRINTFCB *callback, void *user, char *buf, char const *fmt, va_list va) { - static char hex[] = "0123456789abcdefxp"; - static char hexu[] = "0123456789ABCDEFXP"; - char *bf; - char const *f; - int tlen = 0; - - bf = buf; - f = fmt; - for (;;) { - stbsp__int32 fw, pr, tz; - stbsp__uint32 fl; - - // macros for the callback buffer stuff -#define stbsp__chk_cb_bufL(bytes) \ - { \ - int len = (int)(bf - buf); \ - if ((len + (bytes)) >= STB_SPRINTF_MIN) { \ - tlen += len; \ - if (0 == (bf = buf = callback(buf, user, len))) \ - goto done; \ - } \ - } -#define stbsp__chk_cb_buf(bytes) \ - { \ - if (callback) { \ - stbsp__chk_cb_bufL(bytes); \ - } \ - } -#define stbsp__flush_cb() \ - { \ - stbsp__chk_cb_bufL(STB_SPRINTF_MIN - 1); \ - } // flush if there is even one byte in the buffer -#define stbsp__cb_buf_clamp(cl, v) \ - cl = v; \ - if (callback) { \ - int lg = STB_SPRINTF_MIN - (int)(bf - buf); \ - if (cl > lg) \ - cl = lg; \ - } - - // fast copy everything up to the next % (or end of string) - for (;;) { - while (((stbsp__uintptr)f) & 3) { - schk1: - if (f[0] == '%') - goto scandd; - schk2: - if (f[0] == 0) - goto endfmt; - stbsp__chk_cb_buf(1); - *bf++ = f[0]; - ++f; - } - for (;;) { - // Check if the next 4 bytes contain %(0x25) or end of string. - // Using the 'hasless' trick: - // https://graphics.stanford.edu/~seander/bithacks.html#HasLessInWord - stbsp__uint32 v, c; - v = *(stbsp__uint32 *)f; - c = (~v) & 0x80808080; - if (((v ^ 0x25252525) - 0x01010101) & c) - goto schk1; - if ((v - 0x01010101) & c) - goto schk2; - if (callback) - if ((STB_SPRINTF_MIN - (int)(bf - buf)) < 4) - goto schk1; -#ifdef STB_SPRINTF_NOUNALIGNED - if (((stbsp__uintptr)bf) & 3) { - bf[0] = f[0]; - bf[1] = f[1]; - bf[2] = f[2]; - bf[3] = f[3]; - } - else -#endif - { - *(stbsp__uint32 *)bf = v; - } - bf += 4; - f += 4; - } - } - scandd: - - ++f; - - // ok, we have a percent, read the modifiers first - fw = 0; - pr = -1; - fl = 0; - tz = 0; - - // flags - for (;;) { - switch (f[0]) { - // if we have left justify - case '-': - fl |= STBSP__LEFTJUST; - ++f; - continue; - // if we have leading plus - case '+': - fl |= STBSP__LEADINGPLUS; - ++f; - continue; - // if we have leading space - case ' ': - fl |= STBSP__LEADINGSPACE; - ++f; - continue; - // if we have leading 0x - case '#': - fl |= STBSP__LEADING_0X; - ++f; - continue; - // if we have thousand commas - case '\'': - fl |= STBSP__TRIPLET_COMMA; - ++f; - continue; - // if we have kilo marker (none->kilo->kibi->jedec) - case '$': - if (fl & STBSP__METRIC_SUFFIX) { - if (fl & STBSP__METRIC_1024) { - fl |= STBSP__METRIC_JEDEC; - } - else { - fl |= STBSP__METRIC_1024; - } - } - else { - fl |= STBSP__METRIC_SUFFIX; - } - ++f; - continue; - // if we don't want space between metric suffix and number - case '_': - fl |= STBSP__METRIC_NOSPACE; - ++f; - continue; - // if we have leading zero - case '0': - fl |= STBSP__LEADINGZERO; - ++f; - goto flags_done; - default: goto flags_done; - } - } - flags_done: - - // get the field width - if (f[0] == '*') { - fw = va_arg(va, stbsp__uint32); - ++f; - } - else { - while ((f[0] >= '0') && (f[0] <= '9')) { - fw = fw * 10 + f[0] - '0'; - f++; - } - } - // get the precision - if (f[0] == '.') { - ++f; - if (f[0] == '*') { - pr = va_arg(va, stbsp__uint32); - ++f; - } - else { - pr = 0; - while ((f[0] >= '0') && (f[0] <= '9')) { - pr = pr * 10 + f[0] - '0'; - f++; - } - } - } - - // handle integer size overrides - switch (f[0]) { - // are we halfwidth? - case 'h': - fl |= STBSP__HALFWIDTH; - ++f; - if (f[0] == 'h') - ++f; // QUARTERWIDTH - break; - // are we 64-bit (unix style) - case 'l': - fl |= ((sizeof(long) == 8) ? STBSP__INTMAX : 0); - ++f; - if (f[0] == 'l') { - fl |= STBSP__INTMAX; - ++f; - } - break; - // are we 64-bit on intmax? (c99) - case 'j': - fl |= (sizeof(size_t) == 8) ? STBSP__INTMAX : 0; - ++f; - break; - // are we 64-bit on size_t or ptrdiff_t? (c99) - case 'z': - fl |= (sizeof(ptrdiff_t) == 8) ? STBSP__INTMAX : 0; - ++f; - break; - case 't': - fl |= (sizeof(ptrdiff_t) == 8) ? STBSP__INTMAX : 0; - ++f; - break; - // are we 64-bit (msft style) - case 'I': - if ((f[1] == '6') && (f[2] == '4')) { - fl |= STBSP__INTMAX; - f += 3; - } - else if ((f[1] == '3') && (f[2] == '2')) { - f += 3; - } - else { - fl |= ((sizeof(void *) == 8) ? STBSP__INTMAX : 0); - ++f; - } - break; - default: break; - } - - // handle each replacement - switch (f[0]) { -#define STBSP__NUMSZ 512 // big enough for e308 (with commas) or e-307 - char num[STBSP__NUMSZ]; - char lead[8]; - char tail[8]; - char *s; - char const *h; - stbsp__uint32 l, n, cs; - stbsp__uint64 n64; -#ifndef STB_SPRINTF_NOFLOAT - double fv; -#endif - stbsp__int32 dp; - char const *sn; - struct STB_STRING { - char *str; - int64_t len; - }; - struct STB_STRING str; - - case 'Q': - str = va_arg(va, struct STB_STRING); - if (str.str == 0 && str.len != 0) { - str.str = (char *)"null"; - str.len = 4; - } - pr = (int)str.len; - s = (char *)str.str; - l = stbsp__strlen_limited(s, (pr >= 0) ? pr : ~0u); - lead[0] = 0; - tail[0] = 0; - pr = 0; - dp = 0; - cs = 0; - goto scopy; - - case 's': - // get the string - s = va_arg(va, char *); - if (s == 0) - s = (char *)"null"; - // get the length, limited to desired precision - // always limit to ~0u chars since our counts are 32b - l = stbsp__strlen_limited(s, (pr >= 0) ? pr : ~0u); - lead[0] = 0; - tail[0] = 0; - pr = 0; - dp = 0; - cs = 0; - // copy the string in - goto scopy; - - case 'c': // char - // get the character - s = num + STBSP__NUMSZ - 1; - *s = (char)va_arg(va, int); - l = 1; - lead[0] = 0; - tail[0] = 0; - pr = 0; - dp = 0; - cs = 0; - goto scopy; - - case 'n': // weird write-bytes specifier - { - int *d = va_arg(va, int *); - *d = tlen + (int)(bf - buf); - } break; - -#ifdef STB_SPRINTF_NOFLOAT - case 'A': // float - case 'a': // hex float - case 'G': // float - case 'g': // float - case 'E': // float - case 'e': // float - case 'f': // float - va_arg(va, double); // eat it - s = (char *)"No float"; - l = 8; - lead[0] = 0; - tail[0] = 0; - pr = 0; - cs = 0; - STBSP__NOTUSED(dp); - goto scopy; -#else - case 'A': // hex float - case 'a': // hex float - h = (f[0] == 'A') ? hexu : hex; - fv = va_arg(va, double); - if (pr == -1) - pr = 6; // default is 6 - // read the double into a string - if (stbsp__real_to_parts((stbsp__int64 *)&n64, &dp, fv)) - fl |= STBSP__NEGATIVE; - - s = num + 64; - - stbsp__lead_sign(fl, lead); - - if (dp == -1023) - dp = (n64) ? -1022 : 0; - else - n64 |= (((stbsp__uint64)1) << 52); - n64 <<= (64 - 56); - if (pr < 15) - n64 += ((((stbsp__uint64)8) << 56) >> (pr * 4)); - // add leading chars - - #ifdef STB_SPRINTF_MSVC_MODE - *s++ = '0'; - *s++ = 'x'; - #else - lead[1 + lead[0]] = '0'; - lead[2 + lead[0]] = 'x'; - lead[0] += 2; - #endif - *s++ = h[(n64 >> 60) & 15]; - n64 <<= 4; - if (pr) - *s++ = stbsp__period; - sn = s; - - // print the bits - n = pr; - if (n > 13) - n = 13; - if (pr > (stbsp__int32)n) - tz = pr - n; - pr = 0; - while (n--) { - *s++ = h[(n64 >> 60) & 15]; - n64 <<= 4; - } - - // print the expo - tail[1] = h[17]; - if (dp < 0) { - tail[2] = '-'; - dp = -dp; - } - else - tail[2] = '+'; - n = (dp >= 1000) ? 6 : ((dp >= 100) ? 5 : ((dp >= 10) ? 4 : 3)); - tail[0] = (char)n; - for (;;) { - tail[n] = '0' + dp % 10; - if (n <= 3) - break; - --n; - dp /= 10; - } - - dp = (int)(s - sn); - l = (int)(s - (num + 64)); - s = num + 64; - cs = 1 + (3 << 24); - goto scopy; - - case 'G': // float - case 'g': // float - h = (f[0] == 'G') ? hexu : hex; - fv = va_arg(va, double); - if (pr == -1) - pr = 6; - else if (pr == 0) - pr = 1; // default is 6 - // read the double into a string - if (stbsp__real_to_str(&sn, &l, num, &dp, fv, (pr - 1) | 0x80000000)) - fl |= STBSP__NEGATIVE; - - // clamp the precision and delete extra zeros after clamp - n = pr; - if (l > (stbsp__uint32)pr) - l = pr; - while ((l > 1) && (pr) && (sn[l - 1] == '0')) { - --pr; - --l; - } - - // should we use %e - if ((dp <= -4) || (dp > (stbsp__int32)n)) { - if (pr > (stbsp__int32)l) - pr = l - 1; - else if (pr) - --pr; // when using %e, there is one digit before the decimal - goto doexpfromg; - } - // this is the insane action to get the pr to match %g semantics for %f - if (dp > 0) { - pr = (dp < (stbsp__int32)l) ? l - dp : 0; - } - else { - pr = -dp + ((pr > (stbsp__int32)l) ? (stbsp__int32)l : pr); - } - goto dofloatfromg; - - case 'E': // float - case 'e': // float - h = (f[0] == 'E') ? hexu : hex; - fv = va_arg(va, double); - if (pr == -1) - pr = 6; // default is 6 - // read the double into a string - if (stbsp__real_to_str(&sn, &l, num, &dp, fv, pr | 0x80000000)) - fl |= STBSP__NEGATIVE; - doexpfromg: - tail[0] = 0; - stbsp__lead_sign(fl, lead); - if (dp == STBSP__SPECIAL) { - s = (char *)sn; - cs = 0; - pr = 0; - goto scopy; - } - s = num + 64; - // handle leading chars - *s++ = sn[0]; - - if (pr) - *s++ = stbsp__period; - - // handle after decimal - if ((l - 1) > (stbsp__uint32)pr) - l = pr + 1; - for (n = 1; n < l; n++) - *s++ = sn[n]; - // trailing zeros - tz = pr - (l - 1); - pr = 0; - // dump expo - tail[1] = h[0xe]; - dp -= 1; - if (dp < 0) { - tail[2] = '-'; - dp = -dp; - } - else - tail[2] = '+'; - #ifdef STB_SPRINTF_MSVC_MODE - n = 5; - #else - n = (dp >= 100) ? 5 : 4; - #endif - tail[0] = (char)n; - for (;;) { - tail[n] = '0' + dp % 10; - if (n <= 3) - break; - --n; - dp /= 10; - } - cs = 1 + (3 << 24); // how many tens - goto flt_lead; - - case 'f': // float - fv = va_arg(va, double); - doafloat: - // do kilos - if (fl & STBSP__METRIC_SUFFIX) { - double divisor; - divisor = 1000.0f; - if (fl & STBSP__METRIC_1024) - divisor = 1024.0; - while (fl < 0x4000000) { - if ((fv < divisor) && (fv > -divisor)) - break; - fv /= divisor; - fl += 0x1000000; - } - } - if (pr == -1) - pr = 6; // default is 6 - // read the double into a string - if (stbsp__real_to_str(&sn, &l, num, &dp, fv, pr)) - fl |= STBSP__NEGATIVE; - dofloatfromg: - tail[0] = 0; - stbsp__lead_sign(fl, lead); - if (dp == STBSP__SPECIAL) { - s = (char *)sn; - cs = 0; - pr = 0; - goto scopy; - } - s = num + 64; - - // handle the three decimal varieties - if (dp <= 0) { - stbsp__int32 i; - // handle 0.000*000xxxx - *s++ = '0'; - if (pr) - *s++ = stbsp__period; - n = -dp; - if ((stbsp__int32)n > pr) - n = pr; - i = n; - while (i) { - if ((((stbsp__uintptr)s) & 3) == 0) - break; - *s++ = '0'; - --i; - } - while (i >= 4) { - *(stbsp__uint32 *)s = 0x30303030; - s += 4; - i -= 4; - } - while (i) { - *s++ = '0'; - --i; - } - if ((stbsp__int32)(l + n) > pr) - l = pr - n; - i = l; - while (i) { - *s++ = *sn++; - --i; - } - tz = pr - (n + l); - cs = 1 + (3 << 24); // how many tens did we write (for commas below) - } - else { - cs = (fl & STBSP__TRIPLET_COMMA) ? ((600 - (stbsp__uint32)dp) % 3) : 0; - if ((stbsp__uint32)dp >= l) { - // handle xxxx000*000.0 - n = 0; - for (;;) { - if ((fl & STBSP__TRIPLET_COMMA) && (++cs == 4)) { - cs = 0; - *s++ = stbsp__comma; - } - else { - *s++ = sn[n]; - ++n; - if (n >= l) - break; - } - } - if (n < (stbsp__uint32)dp) { - n = dp - n; - if ((fl & STBSP__TRIPLET_COMMA) == 0) { - while (n) { - if ((((stbsp__uintptr)s) & 3) == 0) - break; - *s++ = '0'; - --n; - } - while (n >= 4) { - *(stbsp__uint32 *)s = 0x30303030; - s += 4; - n -= 4; - } - } - while (n) { - if ((fl & STBSP__TRIPLET_COMMA) && (++cs == 4)) { - cs = 0; - *s++ = stbsp__comma; - } - else { - *s++ = '0'; - --n; - } - } - } - cs = (int)(s - (num + 64)) + (3 << 24); // cs is how many tens - if (pr) { - *s++ = stbsp__period; - tz = pr; - } - } - else { - // handle xxxxx.xxxx000*000 - n = 0; - for (;;) { - if ((fl & STBSP__TRIPLET_COMMA) && (++cs == 4)) { - cs = 0; - *s++ = stbsp__comma; - } - else { - *s++ = sn[n]; - ++n; - if (n >= (stbsp__uint32)dp) - break; - } - } - cs = (int)(s - (num + 64)) + (3 << 24); // cs is how many tens - if (pr) - *s++ = stbsp__period; - if ((l - dp) > (stbsp__uint32)pr) - l = pr + dp; - while (n < l) { - *s++ = sn[n]; - ++n; - } - tz = pr - (l - dp); - } - } - pr = 0; - - // handle k,m,g,t - if (fl & STBSP__METRIC_SUFFIX) { - char idx; - idx = 1; - if (fl & STBSP__METRIC_NOSPACE) - idx = 0; - tail[0] = idx; - tail[1] = ' '; - { - if (fl >> 24) { // SI kilo is 'k', JEDEC and SI kibits are 'K'. - if (fl & STBSP__METRIC_1024) - tail[idx + 1] = "_KMGT"[fl >> 24]; - else - tail[idx + 1] = "_kMGT"[fl >> 24]; - idx++; - // If printing kibits and not in jedec, add the 'i'. - if (fl & STBSP__METRIC_1024 && !(fl & STBSP__METRIC_JEDEC)) { - tail[idx + 1] = 'i'; - idx++; - } - tail[0] = idx; - } - } - }; - - flt_lead: - // get the length that we copied - l = (stbsp__uint32)(s - (num + 64)); - s = num + 64; - goto scopy; -#endif - - case 'B': // upper binary - case 'b': // lower binary - h = (f[0] == 'B') ? hexu : hex; - lead[0] = 0; - if (fl & STBSP__LEADING_0X) { - lead[0] = 2; - lead[1] = '0'; - lead[2] = h[0xb]; - } - l = (8 << 4) | (1 << 8); - goto radixnum; - - case 'o': // octal - h = hexu; - lead[0] = 0; - if (fl & STBSP__LEADING_0X) { - lead[0] = 1; - lead[1] = '0'; - } - l = (3 << 4) | (3 << 8); - goto radixnum; - - case 'p': // pointer - fl |= (sizeof(void *) == 8) ? STBSP__INTMAX : 0; - pr = sizeof(void *) * 2; - fl &= ~STBSP__LEADINGZERO; // 'p' only prints the pointer with zeros - // fall through - to X - - case 'X': // upper hex - case 'x': // lower hex - h = (f[0] == 'X') ? hexu : hex; - l = (4 << 4) | (4 << 8); - lead[0] = 0; - if (fl & STBSP__LEADING_0X) { - lead[0] = 2; - lead[1] = '0'; - lead[2] = h[16]; - } - radixnum: - // get the number - if (fl & STBSP__INTMAX) - n64 = va_arg(va, stbsp__uint64); - else - n64 = va_arg(va, stbsp__uint32); - - s = num + STBSP__NUMSZ; - dp = 0; - // clear tail, and clear leading if value is zero - tail[0] = 0; - if (n64 == 0) { - lead[0] = 0; - if (pr == 0) { - l = 0; - cs = 0; - goto scopy; - } - } - // convert to string - for (;;) { - *--s = h[n64 & ((1 << (l >> 8)) - 1)]; - n64 >>= (l >> 8); - if (!((n64) || ((stbsp__int32)((num + STBSP__NUMSZ) - s) < pr))) - break; - if (fl & STBSP__TRIPLET_COMMA) { - ++l; - if ((l & 15) == ((l >> 4) & 15)) { - l &= ~15; - *--s = stbsp__comma; - } - } - }; - // get the tens and the comma pos - cs = (stbsp__uint32)((num + STBSP__NUMSZ) - s) + ((((l >> 4) & 15)) << 24); - // get the length that we copied - l = (stbsp__uint32)((num + STBSP__NUMSZ) - s); - // copy it - goto scopy; - - case 'u': // unsigned - case 'i': - case 'd': // integer - // get the integer and abs it - if (fl & STBSP__INTMAX) { - stbsp__int64 i64 = va_arg(va, stbsp__int64); - n64 = (stbsp__uint64)i64; - if ((f[0] != 'u') && (i64 < 0)) { - n64 = (stbsp__uint64)-i64; - fl |= STBSP__NEGATIVE; - } - } - else { - stbsp__int32 i = va_arg(va, stbsp__int32); - n64 = (stbsp__uint32)i; - if ((f[0] != 'u') && (i < 0)) { - n64 = (stbsp__uint32)-i; - fl |= STBSP__NEGATIVE; - } - } - -#ifndef STB_SPRINTF_NOFLOAT - if (fl & STBSP__METRIC_SUFFIX) { - if (n64 < 1024) - pr = 0; - else if (pr == -1) - pr = 1; - fv = (double)(stbsp__int64)n64; - goto doafloat; - } -#endif - - // convert to string - s = num + STBSP__NUMSZ; - l = 0; - - for (;;) { - // do in 32-bit chunks (avoid lots of 64-bit divides even with constant denominators) - char *o = s - 8; - if (n64 >= 100000000) { - n = (stbsp__uint32)(n64 % 100000000); - n64 /= 100000000; - } - else { - n = (stbsp__uint32)n64; - n64 = 0; - } - if ((fl & STBSP__TRIPLET_COMMA) == 0) { - do { - s -= 2; - *(stbsp__uint16 *)s = *(stbsp__uint16 *)&stbsp__digitpair.pair[(n % 100) * 2]; - n /= 100; - } while (n); - } - while (n) { - if ((fl & STBSP__TRIPLET_COMMA) && (l++ == 3)) { - l = 0; - *--s = stbsp__comma; - --o; - } - else { - *--s = (char)(n % 10) + '0'; - n /= 10; - } - } - if (n64 == 0) { - if ((s[0] == '0') && (s != (num + STBSP__NUMSZ))) - ++s; - break; - } - while (s != o) - if ((fl & STBSP__TRIPLET_COMMA) && (l++ == 3)) { - l = 0; - *--s = stbsp__comma; - --o; - } - else { - *--s = '0'; - } - } - - tail[0] = 0; - stbsp__lead_sign(fl, lead); - - // get the length that we copied - l = (stbsp__uint32)((num + STBSP__NUMSZ) - s); - if (l == 0) { - *--s = '0'; - l = 1; - } - cs = l + (3 << 24); - if (pr < 0) - pr = 0; - - scopy: - // get fw=leading/trailing space, pr=leading zeros - if (pr < (stbsp__int32)l) - pr = l; - n = pr + lead[0] + tail[0] + tz; - if (fw < (stbsp__int32)n) - fw = n; - fw -= n; - pr -= l; - - // handle right justify and leading zeros - if ((fl & STBSP__LEFTJUST) == 0) { - if (fl & STBSP__LEADINGZERO) // if leading zeros, everything is in pr - { - pr = (fw > pr) ? fw : pr; - fw = 0; - } - else { - fl &= ~STBSP__TRIPLET_COMMA; // if no leading zeros, then no commas - } - } - - // copy the spaces and/or zeros - if (fw + pr) { - stbsp__int32 i; - stbsp__uint32 c; - - // copy leading spaces (or when doing %8.4d stuff) - if ((fl & STBSP__LEFTJUST) == 0) - while (fw > 0) { - stbsp__cb_buf_clamp(i, fw); - fw -= i; - while (i) { - if ((((stbsp__uintptr)bf) & 3) == 0) - break; - *bf++ = ' '; - --i; - } - while (i >= 4) { - *(stbsp__uint32 *)bf = 0x20202020; - bf += 4; - i -= 4; - } - while (i) { - *bf++ = ' '; - --i; - } - stbsp__chk_cb_buf(1); - } - - // copy leader - sn = lead + 1; - while (lead[0]) { - stbsp__cb_buf_clamp(i, lead[0]); - lead[0] -= (char)i; - while (i) { - *bf++ = *sn++; - --i; - } - stbsp__chk_cb_buf(1); - } - - // copy leading zeros - c = cs >> 24; - cs &= 0xffffff; - cs = (fl & STBSP__TRIPLET_COMMA) ? ((stbsp__uint32)(c - ((pr + cs) % (c + 1)))) : 0; - while (pr > 0) { - stbsp__cb_buf_clamp(i, pr); - pr -= i; - if ((fl & STBSP__TRIPLET_COMMA) == 0) { - while (i) { - if ((((stbsp__uintptr)bf) & 3) == 0) - break; - *bf++ = '0'; - --i; - } - while (i >= 4) { - *(stbsp__uint32 *)bf = 0x30303030; - bf += 4; - i -= 4; - } - } - while (i) { - if ((fl & STBSP__TRIPLET_COMMA) && (cs++ == c)) { - cs = 0; - *bf++ = stbsp__comma; - } - else - *bf++ = '0'; - --i; - } - stbsp__chk_cb_buf(1); - } - } - - // copy leader if there is still one - sn = lead + 1; - while (lead[0]) { - stbsp__int32 i; - stbsp__cb_buf_clamp(i, lead[0]); - lead[0] -= (char)i; - while (i) { - *bf++ = *sn++; - --i; - } - stbsp__chk_cb_buf(1); - } - - // copy the string - n = l; - while (n) { - stbsp__int32 i; - stbsp__cb_buf_clamp(i, n); - n -= i; - STBSP__UNALIGNED(while (i >= 4) { - *(stbsp__uint32 volatile *)bf = *(stbsp__uint32 volatile *)s; - bf += 4; - s += 4; - i -= 4; - }) - while (i) { - *bf++ = *s++; - --i; - } - stbsp__chk_cb_buf(1); - } - - // copy trailing zeros - while (tz) { - stbsp__int32 i; - stbsp__cb_buf_clamp(i, tz); - tz -= i; - while (i) { - if ((((stbsp__uintptr)bf) & 3) == 0) - break; - *bf++ = '0'; - --i; - } - while (i >= 4) { - *(stbsp__uint32 *)bf = 0x30303030; - bf += 4; - i -= 4; - } - while (i) { - *bf++ = '0'; - --i; - } - stbsp__chk_cb_buf(1); - } - - // copy tail if there is one - sn = tail + 1; - while (tail[0]) { - stbsp__int32 i; - stbsp__cb_buf_clamp(i, tail[0]); - tail[0] -= (char)i; - while (i) { - *bf++ = *sn++; - --i; - } - stbsp__chk_cb_buf(1); - } - - // handle the left justify - if (fl & STBSP__LEFTJUST) - if (fw > 0) { - while (fw) { - stbsp__int32 i; - stbsp__cb_buf_clamp(i, fw); - fw -= i; - while (i) { - if ((((stbsp__uintptr)bf) & 3) == 0) - break; - *bf++ = ' '; - --i; - } - while (i >= 4) { - *(stbsp__uint32 *)bf = 0x20202020; - bf += 4; - i -= 4; - } - while (i--) - *bf++ = ' '; - stbsp__chk_cb_buf(1); - } - } - break; - - default: // unknown, just copy code - s = num + STBSP__NUMSZ - 1; - *s = f[0]; - l = 1; - fw = fl = 0; - lead[0] = 0; - tail[0] = 0; - pr = 0; - dp = 0; - cs = 0; - goto scopy; - } - ++f; - } -endfmt: - - if (!callback) - *bf = 0; - else - stbsp__flush_cb(); - -done: - return tlen + (int)(bf - buf); -} - -// cleanup -#undef STBSP__LEFTJUST -#undef STBSP__LEADINGPLUS -#undef STBSP__LEADINGSPACE -#undef STBSP__LEADING_0X -#undef STBSP__LEADINGZERO -#undef STBSP__INTMAX -#undef STBSP__TRIPLET_COMMA -#undef STBSP__NEGATIVE -#undef STBSP__METRIC_SUFFIX -#undef STBSP__NUMSZ -#undef stbsp__chk_cb_bufL -#undef stbsp__chk_cb_buf -#undef stbsp__flush_cb -#undef stbsp__cb_buf_clamp - -// ============================================================================ -// wrapper functions - -STBSP__PUBLICDEF int STB_SPRINTF_DECORATE(sprintf)(char *buf, char const *fmt, ...) { - int result; - va_list va; - va_start(va, fmt); - result = STB_SPRINTF_DECORATE(vsprintfcb)(0, 0, buf, fmt, va); - va_end(va); - return result; -} - -typedef struct stbsp__context { - char *buf; - int count; - int length; - char tmp[STB_SPRINTF_MIN]; -} stbsp__context; - -static char *stbsp__clamp_callback(const char *buf, void *user, int len) { - stbsp__context *c = (stbsp__context *)user; - c->length += len; - - if (len > c->count) - len = c->count; - - if (len) { - if (buf != c->buf) { - const char *s, *se; - char *d; - d = c->buf; - s = buf; - se = buf + len; - do { - *d++ = *s++; - } while (s < se); - } - c->buf += len; - c->count -= len; - } - - if (c->count <= 0) - return c->tmp; - return (c->count >= STB_SPRINTF_MIN) ? c->buf : c->tmp; // go direct into buffer if you can -} - -static char *stbsp__count_clamp_callback(const char *buf, void *user, int len) { - stbsp__context *c = (stbsp__context *)user; - (void)sizeof(buf); - - c->length += len; - return c->tmp; // go direct into buffer if you can -} - -STBSP__PUBLICDEF int STB_SPRINTF_DECORATE(vsnprintf)(char *buf, int count, char const *fmt, va_list va) { - stbsp__context c; - - if ((count == 0) && !buf) { - c.length = 0; - - STB_SPRINTF_DECORATE(vsprintfcb) - (stbsp__count_clamp_callback, &c, c.tmp, fmt, va); - } - else { - int l; - - c.buf = buf; - c.count = count; - c.length = 0; - - STB_SPRINTF_DECORATE(vsprintfcb) - (stbsp__clamp_callback, &c, stbsp__clamp_callback(0, &c, 0), fmt, va); - - // zero-terminate - l = (int)(c.buf - buf); - if (l >= count) // should never be greater, only equal (or less) than count - l = count - 1; - buf[l] = 0; - } - - return c.length; -} - -STBSP__PUBLICDEF int STB_SPRINTF_DECORATE(snprintf)(char *buf, int count, char const *fmt, ...) { - int result; - va_list va; - va_start(va, fmt); - - result = STB_SPRINTF_DECORATE(vsnprintf)(buf, count, fmt, va); - va_end(va); - - return result; -} - -STBSP__PUBLICDEF int STB_SPRINTF_DECORATE(vsprintf)(char *buf, char const *fmt, va_list va) { - return STB_SPRINTF_DECORATE(vsprintfcb)(0, 0, buf, fmt, va); -} - -// ======================================================================= -// low level float utility functions - -#ifndef STB_SPRINTF_NOFLOAT - - // copies d to bits w/ strict aliasing (this compiles to nothing on /Ox) - #define STBSP__COPYFP(dest, src) \ - { \ - int cn; \ - for (cn = 0; cn < 8; cn++) \ - ((char *)&dest)[cn] = ((char *)&src)[cn]; \ - } - -// get float info -static stbsp__int32 stbsp__real_to_parts(stbsp__int64 *bits, stbsp__int32 *expo, double value) { - double d; - stbsp__int64 b = 0; - - // load value and round at the frac_digits - d = value; - - STBSP__COPYFP(b, d); - - *bits = b & ((((stbsp__uint64)1) << 52) - 1); - *expo = (stbsp__int32)(((b >> 52) & 2047) - 1023); - - return (stbsp__int32)((stbsp__uint64)b >> 63); -} - -static double const stbsp__bot[23] = { - 1e+000, 1e+001, 1e+002, 1e+003, 1e+004, 1e+005, 1e+006, 1e+007, 1e+008, 1e+009, 1e+010, 1e+011, - 1e+012, 1e+013, 1e+014, 1e+015, 1e+016, 1e+017, 1e+018, 1e+019, 1e+020, 1e+021, 1e+022}; -static double const stbsp__negbot[22] = { - 1e-001, 1e-002, 1e-003, 1e-004, 1e-005, 1e-006, 1e-007, 1e-008, 1e-009, 1e-010, 1e-011, - 1e-012, 1e-013, 1e-014, 1e-015, 1e-016, 1e-017, 1e-018, 1e-019, 1e-020, 1e-021, 1e-022}; -static double const stbsp__negboterr[22] = { - -5.551115123125783e-018, -2.0816681711721684e-019, -2.0816681711721686e-020, -4.7921736023859299e-021, -8.1803053914031305e-022, 4.5251888174113741e-023, - 4.5251888174113739e-024, -2.0922560830128471e-025, -6.2281591457779853e-026, -3.6432197315497743e-027, 6.0503030718060191e-028, 2.0113352370744385e-029, - -3.0373745563400371e-030, 1.1806906454401013e-032, -7.7705399876661076e-032, 2.0902213275965398e-033, -7.1542424054621921e-034, -7.1542424054621926e-035, - 2.4754073164739869e-036, 5.4846728545790429e-037, 9.2462547772103625e-038, -4.8596774326570872e-039}; -static double const stbsp__top[13] = { - 1e+023, 1e+046, 1e+069, 1e+092, 1e+115, 1e+138, 1e+161, 1e+184, 1e+207, 1e+230, 1e+253, 1e+276, 1e+299}; -static double const stbsp__negtop[13] = { - 1e-023, 1e-046, 1e-069, 1e-092, 1e-115, 1e-138, 1e-161, 1e-184, 1e-207, 1e-230, 1e-253, 1e-276, 1e-299}; -static double const stbsp__toperr[13] = { - 8388608, - 6.8601809640529717e+028, - -7.253143638152921e+052, - -4.3377296974619174e+075, - -1.5559416129466825e+098, - -3.2841562489204913e+121, - -3.7745893248228135e+144, - -1.7356668416969134e+167, - -3.8893577551088374e+190, - -9.9566444326005119e+213, - 6.3641293062232429e+236, - -5.2069140800249813e+259, - -5.2504760255204387e+282}; -static double const stbsp__negtoperr[13] = { - 3.9565301985100693e-040, -2.299904345391321e-063, 3.6506201437945798e-086, 1.1875228833981544e-109, - -5.0644902316928607e-132, -6.7156837247865426e-155, -2.812077463003139e-178, -5.7778912386589953e-201, - 7.4997100559334532e-224, -4.6439668915134491e-247, -6.3691100762962136e-270, -9.436808465446358e-293, - 8.0970921678014997e-317}; - - #if defined(_MSC_VER) && (_MSC_VER <= 1200) -static stbsp__uint64 const stbsp__powten[20] = { - 1, - 10, - 100, - 1000, - 10000, - 100000, - 1000000, - 10000000, - 100000000, - 1000000000, - 10000000000, - 100000000000, - 1000000000000, - 10000000000000, - 100000000000000, - 1000000000000000, - 10000000000000000, - 100000000000000000, - 1000000000000000000, - 10000000000000000000U}; - #define stbsp__tento19th ((stbsp__uint64)1000000000000000000) - #else -static stbsp__uint64 const stbsp__powten[20] = { - 1, - 10, - 100, - 1000, - 10000, - 100000, - 1000000, - 10000000, - 100000000, - 1000000000, - 10000000000ULL, - 100000000000ULL, - 1000000000000ULL, - 10000000000000ULL, - 100000000000000ULL, - 1000000000000000ULL, - 10000000000000000ULL, - 100000000000000000ULL, - 1000000000000000000ULL, - 10000000000000000000ULL}; - #define stbsp__tento19th (1000000000000000000ULL) - #endif - - #define stbsp__ddmulthi(oh, ol, xh, yh) \ - { \ - double ahi = 0, alo, bhi = 0, blo; \ - stbsp__int64 bt; \ - oh = xh * yh; \ - STBSP__COPYFP(bt, xh); \ - bt &= ((~(stbsp__uint64)0) << 27); \ - STBSP__COPYFP(ahi, bt); \ - alo = xh - ahi; \ - STBSP__COPYFP(bt, yh); \ - bt &= ((~(stbsp__uint64)0) << 27); \ - STBSP__COPYFP(bhi, bt); \ - blo = yh - bhi; \ - ol = ((ahi * bhi - oh) + ahi * blo + alo * bhi) + alo * blo; \ - } - - #define stbsp__ddtoS64(ob, xh, xl) \ - { \ - double ahi = 0, alo, vh, t; \ - ob = (stbsp__int64)xh; \ - vh = (double)ob; \ - ahi = (xh - vh); \ - t = (ahi - xh); \ - alo = (xh - (ahi - t)) - (vh + t); \ - ob += (stbsp__int64)(ahi + alo + xl); \ - } - - #define stbsp__ddrenorm(oh, ol) \ - { \ - double s; \ - s = oh + ol; \ - ol = ol - (s - oh); \ - oh = s; \ - } - - #define stbsp__ddmultlo(oh, ol, xh, xl, yh, yl) ol = ol + (xh * yl + xl * yh); - - #define stbsp__ddmultlos(oh, ol, xh, yl) ol = ol + (xh * yl); - -static void stbsp__raise_to_power10(double *ohi, double *olo, double d, stbsp__int32 power) // power can be -323 to +350 -{ - double ph, pl; - if ((power >= 0) && (power <= 22)) { - stbsp__ddmulthi(ph, pl, d, stbsp__bot[power]); - } - else { - stbsp__int32 e, et, eb; - double p2h, p2l; - - e = power; - if (power < 0) - e = -e; - et = (e * 0x2c9) >> 14; /* %23 */ - if (et > 13) - et = 13; - eb = e - (et * 23); - - ph = d; - pl = 0.0; - if (power < 0) { - if (eb) { - --eb; - stbsp__ddmulthi(ph, pl, d, stbsp__negbot[eb]); - stbsp__ddmultlos(ph, pl, d, stbsp__negboterr[eb]); - } - if (et) { - stbsp__ddrenorm(ph, pl); - --et; - stbsp__ddmulthi(p2h, p2l, ph, stbsp__negtop[et]); - stbsp__ddmultlo(p2h, p2l, ph, pl, stbsp__negtop[et], stbsp__negtoperr[et]); - ph = p2h; - pl = p2l; - } - } - else { - if (eb) { - e = eb; - if (eb > 22) - eb = 22; - e -= eb; - stbsp__ddmulthi(ph, pl, d, stbsp__bot[eb]); - if (e) { - stbsp__ddrenorm(ph, pl); - stbsp__ddmulthi(p2h, p2l, ph, stbsp__bot[e]); - stbsp__ddmultlos(p2h, p2l, stbsp__bot[e], pl); - ph = p2h; - pl = p2l; - } - } - if (et) { - stbsp__ddrenorm(ph, pl); - --et; - stbsp__ddmulthi(p2h, p2l, ph, stbsp__top[et]); - stbsp__ddmultlo(p2h, p2l, ph, pl, stbsp__top[et], stbsp__toperr[et]); - ph = p2h; - pl = p2l; - } - } - } - stbsp__ddrenorm(ph, pl); - *ohi = ph; - *olo = pl; -} - -// given a float value, returns the significant bits in bits, and the position of the -// decimal point in decimal_pos. +/-INF and NAN are specified by special values -// returned in the decimal_pos parameter. -// frac_digits is absolute normally, but if you want from first significant digits (got %g and %e), or in 0x80000000 -static stbsp__int32 stbsp__real_to_str(char const **start, stbsp__uint32 *len, char *out, stbsp__int32 *decimal_pos, double value, stbsp__uint32 frac_digits) { - double d; - stbsp__int64 bits = 0; - stbsp__int32 expo, e, ng, tens; - - d = value; - STBSP__COPYFP(bits, d); - expo = (stbsp__int32)((bits >> 52) & 2047); - ng = (stbsp__int32)((stbsp__uint64)bits >> 63); - if (ng) - d = -d; - - if (expo == 2047) // is nan or inf? - { - *start = (bits & ((((stbsp__uint64)1) << 52) - 1)) ? "NaN" : "Inf"; - *decimal_pos = STBSP__SPECIAL; - *len = 3; - return ng; - } - - if (expo == 0) // is zero or denormal - { - if (((stbsp__uint64)bits << 1) == 0) // do zero - { - *decimal_pos = 1; - *start = out; - out[0] = '0'; - *len = 1; - return ng; - } - // find the right expo for denormals - { - stbsp__int64 v = ((stbsp__uint64)1) << 51; - while ((bits & v) == 0) { - --expo; - v >>= 1; - } - } - } - - // find the decimal exponent as well as the decimal bits of the value - { - double ph, pl; - - // log10 estimate - very specifically tweaked to hit or undershoot by no more than 1 of log10 of all expos 1..2046 - tens = expo - 1023; - tens = (tens < 0) ? ((tens * 617) / 2048) : (((tens * 1233) / 4096) + 1); - - // move the significant bits into position and stick them into an int - stbsp__raise_to_power10(&ph, &pl, d, 18 - tens); - - // get full as much precision from double-double as possible - stbsp__ddtoS64(bits, ph, pl); - - // check if we undershot - if (((stbsp__uint64)bits) >= stbsp__tento19th) - ++tens; - } - - // now do the rounding in integer land - frac_digits = (frac_digits & 0x80000000) ? ((frac_digits & 0x7ffffff) + 1) : (tens + frac_digits); - if ((frac_digits < 24)) { - stbsp__uint32 dg = 1; - if ((stbsp__uint64)bits >= stbsp__powten[9]) - dg = 10; - while ((stbsp__uint64)bits >= stbsp__powten[dg]) { - ++dg; - if (dg == 20) - goto noround; - } - if (frac_digits < dg) { - stbsp__uint64 r; - // add 0.5 at the right position and round - e = dg - frac_digits; - if ((stbsp__uint32)e >= 24) - goto noround; - r = stbsp__powten[e]; - bits = bits + (r / 2); - if ((stbsp__uint64)bits >= stbsp__powten[dg]) - ++tens; - bits /= r; - } - noround:; - } - - // kill long trailing runs of zeros - if (bits) { - stbsp__uint32 n; - for (;;) { - if (bits <= 0xffffffff) - break; - if (bits % 1000) - goto donez; - bits /= 1000; - } - n = (stbsp__uint32)bits; - while ((n % 1000) == 0) - n /= 1000; - bits = n; - donez:; - } - - // convert to string - out += 64; - e = 0; - for (;;) { - stbsp__uint32 n; - char *o = out - 8; - // do the conversion in chunks of U32s (avoid most 64-bit divides, worth it, constant denomiators be damned) - if (bits >= 100000000) { - n = (stbsp__uint32)(bits % 100000000); - bits /= 100000000; - } - else { - n = (stbsp__uint32)bits; - bits = 0; - } - while (n) { - out -= 2; - *(stbsp__uint16 *)out = *(stbsp__uint16 *)&stbsp__digitpair.pair[(n % 100) * 2]; - n /= 100; - e += 2; - } - if (bits == 0) { - if ((e) && (out[0] == '0')) { - ++out; - --e; - } - break; - } - while (out != o) { - *--out = '0'; - ++e; - } - } - - *decimal_pos = tens; - *start = out; - *len = e; - return ng; -} - - #undef stbsp__ddmulthi - #undef stbsp__ddrenorm - #undef stbsp__ddmultlo - #undef stbsp__ddmultlos - #undef STBSP__SPECIAL - #undef STBSP__COPYFP - -#endif // STB_SPRINTF_NOFLOAT - -// clean up -#undef stbsp__uint16 -#undef stbsp__uint32 -#undef stbsp__int32 -#undef stbsp__uint64 -#undef stbsp__int64 -#undef STBSP__UNALIGNED diff --git a/src/build_tool/standalone_libraries/stb_sprintf.h b/src/build_tool/standalone_libraries/stb_sprintf.h deleted file mode 100644 index 0300e84..0000000 --- a/src/build_tool/standalone_libraries/stb_sprintf.h +++ /dev/null @@ -1,262 +0,0 @@ -// stb_sprintf - v1.10 - public domain snprintf() implementation -// originally by Jeff Roberts / RAD Game Tools, 2015/10/20 -// http://github.com/nothings/stb -// -// allowed types: sc uidBboXx p AaGgEef n -// lengths : hh h ll j z t I64 I32 I -// -// Contributors: -// Fabian "ryg" Giesen (reformatting) -// github:aganm (attribute format) -// -// Contributors (bugfixes): -// github:d26435 -// github:trex78 -// github:account-login -// Jari Komppa (SI suffixes) -// Rohit Nirmal -// Marcin Wojdyr -// Leonard Ritter -// Stefano Zanotti -// Adam Allison -// Arvid Gerstmann -// Markus Kolb -// -// LICENSE: -// -// See end of file for license information. - -#ifndef STB_SPRINTF_H_INCLUDE - #define STB_SPRINTF_H_INCLUDE - #include -/* -Single file sprintf replacement. - -Originally written by Jeff Roberts at RAD Game Tools - 2015/10/20. -Hereby placed in public domain. - -This is a full sprintf replacement that supports everything that -the C runtime sprintfs support, including float/double, 64-bit integers, -hex floats, field parameters (%*.*d stuff), length reads backs, etc. - -Why would you need this if sprintf already exists? Well, first off, -it's *much* faster (see below). It's also much smaller than the CRT -versions code-space-wise. We've also added some simple improvements -that are super handy (commas in thousands, callbacks at buffer full, -for example). Finally, the format strings for MSVC and GCC differ -for 64-bit integers (among other small things), so this lets you use -the same format strings in cross platform code. - -It uses the standard single file trick of being both the header file -and the source itself. If you just include it normally, you just get -the header file function definitions. To get the code, you include -it from a C or C++ file and define STB_SPRINTF_IMPLEMENTATION first. - -It only uses va_args macros from the C runtime to do it's work. It -does cast doubles to S64s and shifts and divides U64s, which does -drag in CRT code on most platforms. - -It compiles to roughly 8K with float support, and 4K without. -As a comparison, when using MSVC static libs, calling sprintf drags -in 16K. - -API: -==== -int stbsp_sprintf( char * buf, char const * fmt, ... ) -int stbsp_snprintf( char * buf, int count, char const * fmt, ... ) - Convert an arg list into a buffer. stbsp_snprintf always returns - a zero-terminated string (unlike regular snprintf). - -int stbsp_vsprintf( char * buf, char const * fmt, va_list va ) -int stbsp_vsnprintf( char * buf, int count, char const * fmt, va_list va ) - Convert a va_list arg list into a buffer. stbsp_vsnprintf always returns - a zero-terminated string (unlike regular snprintf). - -int stbsp_vsprintfcb( STBSP_SPRINTFCB * callback, void * user, char * buf, char const * fmt, va_list va ) - typedef char * STBSP_SPRINTFCB( char const * buf, void * user, int len ); - Convert into a buffer, calling back every STB_SPRINTF_MIN chars. - Your callback can then copy the chars out, print them or whatever. - This function is actually the workhorse for everything else. - The buffer you pass in must hold at least STB_SPRINTF_MIN characters. - // you return the next buffer to use or 0 to stop converting - -void stbsp_set_separators( char comma, char period ) - Set the comma and period characters to use. - -FLOATS/DOUBLES: -=============== -This code uses a internal float->ascii conversion method that uses -doubles with error correction (double-doubles, for ~105 bits of -precision). This conversion is round-trip perfect - that is, an atof -of the values output here will give you the bit-exact double back. - -One difference is that our insignificant digits will be different than -with MSVC or GCC (but they don't match each other either). We also -don't attempt to find the minimum length matching float (pre-MSVC15 -doesn't either). - -If you don't need float or doubles at all, define STB_SPRINTF_NOFLOAT -and you'll save 4K of code space. - -64-BIT INTS: -============ -This library also supports 64-bit integers and you can use MSVC style or -GCC style indicators (%I64d or %lld). It supports the C99 specifiers -for size_t and ptr_diff_t (%jd %zd) as well. - -EXTRAS: -======= -Like some GCCs, for integers and floats, you can use a ' (single quote) -specifier and commas will be inserted on the thousands: "%'d" on 12345 -would print 12,345. - -For integers and floats, you can use a "$" specifier and the number -will be converted to float and then divided to get kilo, mega, giga or -tera and then printed, so "%$d" 1000 is "1.0 k", "%$.2d" 2536000 is -"2.53 M", etc. For byte values, use two $:s, like "%$$d" to turn -2536000 to "2.42 Mi". If you prefer JEDEC suffixes to SI ones, use three -$:s: "%$$$d" -> "2.42 M". To remove the space between the number and the -suffix, add "_" specifier: "%_$d" -> "2.53M". - -In addition to octal and hexadecimal conversions, you can print -integers in binary: "%b" for 256 would print 100. - -PERFORMANCE vs MSVC 2008 32-/64-bit (GCC is even slower than MSVC): -=================================================================== -"%d" across all 32-bit ints (4.8x/4.0x faster than 32-/64-bit MSVC) -"%24d" across all 32-bit ints (4.5x/4.2x faster) -"%x" across all 32-bit ints (4.5x/3.8x faster) -"%08x" across all 32-bit ints (4.3x/3.8x faster) -"%f" across e-10 to e+10 floats (7.3x/6.0x faster) -"%e" across e-10 to e+10 floats (8.1x/6.0x faster) -"%g" across e-10 to e+10 floats (10.0x/7.1x faster) -"%f" for values near e-300 (7.9x/6.5x faster) -"%f" for values near e+300 (10.0x/9.1x faster) -"%e" for values near e-300 (10.1x/7.0x faster) -"%e" for values near e+300 (9.2x/6.0x faster) -"%.320f" for values near e-300 (12.6x/11.2x faster) -"%a" for random values (8.6x/4.3x faster) -"%I64d" for 64-bits with 32-bit values (4.8x/3.4x faster) -"%I64d" for 64-bits > 32-bit values (4.9x/5.5x faster) -"%s%s%s" for 64 char strings (7.1x/7.3x faster) -"...512 char string..." ( 35.0x/32.5x faster!) -*/ - - #if defined(__clang__) - #if defined(__has_feature) && defined(__has_attribute) - #if __has_feature(address_sanitizer) - #if __has_attribute(__no_sanitize__) - #define STBSP__ASAN __attribute__((__no_sanitize__("address"))) - #elif __has_attribute(__no_sanitize_address__) - #define STBSP__ASAN __attribute__((__no_sanitize_address__)) - #elif __has_attribute(__no_address_safety_analysis__) - #define STBSP__ASAN __attribute__((__no_address_safety_analysis__)) - #endif - #endif - #endif - #elif defined(__GNUC__) && (__GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)) - #if defined(__SANITIZE_ADDRESS__) && __SANITIZE_ADDRESS__ - #define STBSP__ASAN __attribute__((__no_sanitize_address__)) - #endif - #elif defined(_MSC_VER) - #ifdef __SANITIZE_ADDRESS__ - #define STBSP__ASAN __declspec(no_sanitize_address) - #endif - #endif - - #ifndef STBSP__ASAN - #define STBSP__ASAN - #endif - - #ifdef STB_SPRINTF_STATIC - #define STBSP__PUBLICDEC static - #define STBSP__PUBLICDEF static STBSP__ASAN - #else - #ifdef __cplusplus - #define STBSP__PUBLICDEC extern "C" - #define STBSP__PUBLICDEF extern "C" STBSP__ASAN - #else - #define STBSP__PUBLICDEC extern - #define STBSP__PUBLICDEF STBSP__ASAN - #endif - #endif - - #if defined(__has_attribute) - #if __has_attribute(format) - #define STBSP__ATTRIBUTE_FORMAT(fmt, va) __attribute__((format(printf, fmt, va))) - #endif - #endif - - #ifndef STBSP__ATTRIBUTE_FORMAT - #define STBSP__ATTRIBUTE_FORMAT(fmt, va) - #endif - - #ifdef _MSC_VER - #define STBSP__NOTUSED(v) (void)(v) - #else - #define STBSP__NOTUSED(v) (void)sizeof(v) - #endif - - #include // for va_arg(), va_list() - #include // size_t, ptrdiff_t - - #ifndef STB_SPRINTF_MIN - #define STB_SPRINTF_MIN 512 // how many characters per callback - #endif -typedef char *STBSP_SPRINTFCB(const char *buf, void *user, int len); - - #ifndef STB_SPRINTF_DECORATE - #define STB_SPRINTF_DECORATE(name) stbsp_##name // define this before including if you want to change the names - #endif - -STBSP__PUBLICDEC int STB_SPRINTF_DECORATE(vsprintf)(char *buf, char const *fmt, va_list va); -STBSP__PUBLICDEC int STB_SPRINTF_DECORATE(vsnprintf)(char *buf, int count, char const *fmt, va_list va); -STBSP__PUBLICDEC int STB_SPRINTF_DECORATE(sprintf)(char *buf, char const *fmt, ...) STBSP__ATTRIBUTE_FORMAT(2, 3); -STBSP__PUBLICDEC int STB_SPRINTF_DECORATE(snprintf)(char *buf, int count, char const *fmt, ...) STBSP__ATTRIBUTE_FORMAT(3, 4); - -STBSP__PUBLICDEC int STB_SPRINTF_DECORATE(vsprintfcb)(STBSP_SPRINTFCB *callback, void *user, char *buf, char const *fmt, va_list va); -STBSP__PUBLICDEC void STB_SPRINTF_DECORATE(set_separators)(char comma, char period); - -#endif // STB_SPRINTF_H_INCLUDE - -/* ------------------------------------------------------------------------------- -This software is available under 2 licenses -- choose whichever you prefer. ------------------------------------------------------------------------------- -ALTERNATIVE A - MIT License -Copyright (c) 2017 Sean Barrett -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. ------------------------------------------------------------------------------- -ALTERNATIVE B - Public Domain (www.unlicense.org) -This is free and unencumbered software released into the public domain. -Anyone is free to copy, modify, publish, use, compile, sell, or distribute this -software, either in source code form or as a compiled binary, for any purpose, -commercial or non-commercial, and by any means. -In jurisdictions that recognize copyright laws, the author or authors of this -software dedicate any and all copyright interest in the software to the public -domain. We make this dedication for the benefit of the public at large and to -the detriment of our heirs and successors. We intend this dedication to be an -overt act of relinquishment in perpetuity of all present and future rights to -this software under copyright law. -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 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. ------------------------------------------------------------------------------- -*/ diff --git a/src/build_tool/standalone_libraries/string.c b/src/build_tool/standalone_libraries/string.c deleted file mode 100644 index ff34d17..0000000 --- a/src/build_tool/standalone_libraries/string.c +++ /dev/null @@ -1,566 +0,0 @@ -#include "string.h" -#include - -#ifndef S8_VSNPRINTF - #include - #define S8_VSNPRINTF vsnprintf -#endif - -#ifndef S8_ALLOCATE - #include - #define S8_ALLOCATE(allocator, size) malloc(size) -#endif - -#ifndef S8_ASSERT - #include - #define S8_ASSERT(x) assert(x) -#endif - -#ifndef S8_MemoryCopy - #include - #define S8_MemoryCopy(dst, src, s) memcpy(dst, src, s) -#endif - -#ifndef S8_StaticFunc - #if defined(__GNUC__) || defined(__clang__) - #define S8_StaticFunc __attribute__((unused)) static - #else - #define S8_StaticFunc static - #endif -#endif - -S8_StaticFunc int64_t S8__ClampTop(int64_t val, int64_t max) { - if (val > max) val = max; - return val; -} - -S8_API char CHAR_ToLowerCase(char a) { - if (a >= 'A' && a <= 'Z') a += 32; - return a; -} - -S8_API char CHAR_ToUpperCase(char a) { - if (a >= 'a' && a <= 'z') a -= 32; - return a; -} - -S8_API bool CHAR_IsWhitespace(char w) { - bool result = w == '\n' || w == ' ' || w == '\t' || w == '\v' || w == '\r'; - return result; -} - -S8_API bool CHAR_IsAlphabetic(char a) { - bool result = (a >= 'a' && a <= 'z') || (a >= 'A' && a <= 'Z'); - return result; -} - -S8_API bool CHAR_IsIdent(char a) { - bool result = (a >= 'a' && a <= 'z') || (a >= 'A' && a <= 'Z') || a == '_'; - return result; -} - -S8_API bool CHAR_IsDigit(char a) { - bool result = a >= '0' && a <= '9'; - return result; -} - -S8_API bool CHAR_IsAlphanumeric(char a) { - bool result = CHAR_IsDigit(a) || CHAR_IsAlphabetic(a); - return result; -} - -S8_API bool S8_AreEqual(S8_String a, S8_String b, unsigned ignore_case) { - if (a.len != b.len) return false; - for (int64_t i = 0; i < a.len; i++) { - char A = a.str[i]; - char B = b.str[i]; - if (ignore_case) { - A = CHAR_ToLowerCase(A); - B = CHAR_ToLowerCase(B); - } - if (A != B) - return false; - } - return true; -} - -S8_API bool S8_EndsWith(S8_String a, S8_String end, unsigned ignore_case) { - S8_String a_end = S8_GetPostfix(a, end.len); - bool result = S8_AreEqual(end, a_end, ignore_case); - return result; -} - -S8_API bool S8_StartsWith(S8_String a, S8_String start, unsigned ignore_case) { - S8_String a_start = S8_GetPrefix(a, start.len); - bool result = S8_AreEqual(start, a_start, ignore_case); - return result; -} - -S8_API S8_String S8_Make(char *str, int64_t len) { - S8_String result; - result.str = (char *)str; - result.len = len; - return result; -} - -S8_API S8_String S8_Copy(S8_Allocator allocator, S8_String string) { - char *copy = (char *)S8_ALLOCATE(allocator, sizeof(char) * (string.len + 1)); - S8_MemoryCopy(copy, string.str, string.len); - copy[string.len] = 0; - S8_String result = S8_Make(copy, string.len); - return result; -} - -S8_API S8_String S8_CopyChar(S8_Allocator allocator, char *s) { - int64_t len = S8_Length(s); - char *copy = (char *)S8_ALLOCATE(allocator, sizeof(char) * (len + 1)); - S8_MemoryCopy(copy, s, len); - copy[len] = 0; - S8_String result = S8_Make(copy, len); - return result; -} - -S8_API S8_String S8_NormalizePath(S8_Allocator allocator, S8_String s) { - S8_String copy = S8_Copy(allocator, s); - for (int64_t i = 0; i < copy.len; i++) { - if (copy.str[i] == '\\') - copy.str[i] = '/'; - } - return copy; -} - -S8_API void S8_NormalizePathUnsafe(S8_String s) { - for (int64_t i = 0; i < s.len; i++) { - if (s.str[i] == '\\') - s.str[i] = '/'; - } -} - -S8_API S8_String S8_Chop(S8_String string, int64_t len) { - len = S8__ClampTop(len, string.len); - S8_String result = S8_Make(string.str, string.len - len); - return result; -} - -S8_API S8_String S8_Skip(S8_String string, int64_t len) { - len = S8__ClampTop(len, string.len); - int64_t remain = string.len - len; - S8_String result = S8_Make(string.str + len, remain); - return result; -} - -S8_API bool S8_IsPointerInside(S8_String string, char *p) { - uintptr_t pointer = (uintptr_t)p; - uintptr_t start = (uintptr_t)string.str; - uintptr_t stop = start + (uintptr_t)string.len; - bool result = pointer >= start && pointer < stop; - return result; -} - -S8_API S8_String S8_SkipToP(S8_String string, char *p) { - if (S8_IsPointerInside(string, p)) { - S8_String result = S8_Make(p, p - string.str); - return result; - } - return string; -} - -S8_API S8_String S8_SkipPast(S8_String string, S8_String a) { - if (S8_IsPointerInside(string, a.str)) { - S8_String on_p = S8_Make(a.str, a.str - string.str); - S8_String result = S8_Skip(on_p, a.len); - return result; - } - return string; -} - -S8_API S8_String S8_GetPostfix(S8_String string, int64_t len) { - len = S8__ClampTop(len, string.len); - int64_t remain_len = string.len - len; - S8_String result = S8_Make(string.str + remain_len, len); - return result; -} - -S8_API S8_String S8_GetPrefix(S8_String string, int64_t len) { - len = S8__ClampTop(len, string.len); - S8_String result = S8_Make(string.str, len); - return result; -} - -S8_API S8_String S8_GetNameNoExt(S8_String s) { - return S8_SkipToLastSlash(S8_ChopLastPeriod(s)); -} - -S8_API S8_String S8_Slice(S8_String string, int64_t first_index, int64_t one_past_last_index) { - if (one_past_last_index < 0) one_past_last_index = string.len + one_past_last_index + 1; - if (first_index < 0) first_index = string.len + first_index; - S8_ASSERT(first_index < one_past_last_index && "S8_Slice, first_index is bigger then one_past_last_index"); - S8_ASSERT(string.len > 0 && "Slicing string of length 0! Might be an error!"); - S8_String result = string; - if (string.len > 0) { - if (one_past_last_index > first_index) { - first_index = S8__ClampTop(first_index, string.len - 1); - one_past_last_index = S8__ClampTop(one_past_last_index, string.len); - result.str += first_index; - result.len = one_past_last_index - first_index; - } - else { - result.len = 0; - } - } - return result; -} - -S8_API S8_String S8_Trim(S8_String string) { - if (string.len == 0) - return string; - - int64_t whitespace_begin = 0; - for (; whitespace_begin < string.len; whitespace_begin++) { - if (!CHAR_IsWhitespace(string.str[whitespace_begin])) { - break; - } - } - - int64_t whitespace_end = string.len; - for (; whitespace_end != whitespace_begin; whitespace_end--) { - if (!CHAR_IsWhitespace(string.str[whitespace_end - 1])) { - break; - } - } - - if (whitespace_begin == whitespace_end) { - string.len = 0; - } - else { - string = S8_Slice(string, whitespace_begin, whitespace_end); - } - - return string; -} - -S8_API S8_String S8_TrimEnd(S8_String string) { - int64_t whitespace_end = string.len; - for (; whitespace_end != 0; whitespace_end--) { - if (!CHAR_IsWhitespace(string.str[whitespace_end - 1])) { - break; - } - } - - S8_String result = S8_GetPrefix(string, whitespace_end); - return result; -} - -S8_API S8_String S8_ToLowerCase(S8_Allocator allocator, S8_String s) { - S8_String copy = S8_Copy(allocator, s); - for (int64_t i = 0; i < copy.len; i++) { - copy.str[i] = CHAR_ToLowerCase(copy.str[i]); - } - return copy; -} - -S8_API S8_String S8_ToUpperCase(S8_Allocator allocator, S8_String s) { - S8_String copy = S8_Copy(allocator, s); - for (int64_t i = 0; i < copy.len; i++) { - copy.str[i] = CHAR_ToUpperCase(copy.str[i]); - } - return copy; -} - -S8_API bool S8_Seek(S8_String string, S8_String find, S8_FindFlag flags, int64_t *index_out) { - bool ignore_case = flags & S8_FindFlag_IgnoreCase ? true : false; - bool result = false; - if (flags & S8_FindFlag_MatchFindLast) { - for (int64_t i = string.len; i != 0; i--) { - int64_t index = i - 1; - S8_String substring = S8_Slice(string, index, index + find.len); - if (S8_AreEqual(substring, find, ignore_case)) { - if (index_out) - *index_out = index; - result = true; - break; - } - } - } - else { - for (int64_t i = 0; i < string.len; i++) { - S8_String substring = S8_Slice(string, i, i + find.len); - if (S8_AreEqual(substring, find, ignore_case)) { - if (index_out) - *index_out = i; - result = true; - break; - } - } - } - - return result; -} - -S8_API int64_t S8_Find(S8_String string, S8_String find, S8_FindFlag flag) { - int64_t result = -1; - S8_Seek(string, find, flag, &result); - return result; -} - -S8_API S8_List S8_Split(S8_Allocator allocator, S8_String string, S8_String find, S8_SplitFlag flags) { - S8_List result = S8_MakeEmptyList(); - int64_t index = 0; - - S8_FindFlag find_flag = flags & S8_SplitFlag_IgnoreCase ? S8_FindFlag_IgnoreCase : S8_FindFlag_None; - while (S8_Seek(string, find, find_flag, &index)) { - S8_String before_match = S8_Make(string.str, index); - S8_AddNode(allocator, &result, before_match); - if (flags & S8_SplitFlag_SplitInclusive) { - S8_String match = S8_Make(string.str + index, find.len); - S8_AddNode(allocator, &result, match); - } - string = S8_Skip(string, index + find.len); - } - if (string.len) S8_AddNode(allocator, &result, string); - return result; -} - -S8_API S8_String S8_MergeWithSeparator(S8_Allocator allocator, S8_List list, S8_String separator) { - if (list.node_count == 0) return S8_MakeEmpty(); - if (list.char_count == 0) return S8_MakeEmpty(); - - int64_t base_size = (list.char_count + 1); - int64_t sep_size = (list.node_count - 1) * separator.len; - int64_t size = base_size + sep_size; - char *buff = (char *)S8_ALLOCATE(allocator, sizeof(char) * (size + 1)); - S8_String string = S8_Make(buff, 0); - for (S8_Node *it = list.first; it; it = it->next) { - S8_ASSERT(string.len + it->string.len <= size); - S8_MemoryCopy(string.str + string.len, it->string.str, it->string.len); - string.len += it->string.len; - if (it != list.last) { - S8_MemoryCopy(string.str + string.len, separator.str, separator.len); - string.len += separator.len; - } - } - S8_ASSERT(string.len == size - 1); - string.str[size] = 0; - return string; -} - -S8_API S8_String S8_Merge(S8_Allocator allocator, S8_List list) { - return S8_MergeWithSeparator(allocator, list, S8_Lit("")); -} - -S8_API S8_String S8_ReplaceAll(S8_Allocator allocator, S8_String string, S8_String replace, S8_String with, bool ignore_case) { - S8_SplitFlag split_flag = ignore_case ? S8_SplitFlag_IgnoreCase : S8_SplitFlag_None; - S8_List list = S8_Split(allocator, string, replace, split_flag | S8_SplitFlag_SplitInclusive); - for (S8_Node *it = list.first; it; it = it->next) { - if (S8_AreEqual(it->string, replace, ignore_case)) { - S8_ReplaceNodeString(&list, it, with); - } - } - S8_String result = S8_Merge(allocator, list); - return result; -} - -S8_API S8_List S8_FindAll(S8_Allocator allocator, S8_String string, S8_String find, bool ignore_case) { // @untested - S8_List result = S8_MakeEmptyList(); - int64_t index = 0; - - S8_FindFlag find_flag = ignore_case ? S8_FindFlag_IgnoreCase : 0; - while (S8_Seek(string, find, find_flag, &index)) { - S8_String match = S8_Make(string.str + index, find.len); - S8_AddNode(allocator, &result, match); - string = S8_Skip(string, index + find.len); - } - return result; -} - -S8_API S8_String S8_ChopLastSlash(S8_String s) { - S8_String result = s; - S8_Seek(s, S8_Lit("/"), S8_FindFlag_MatchFindLast, &result.len); - return result; -} - -S8_API S8_String S8_ChopLastPeriod(S8_String s) { - S8_String result = s; - S8_Seek(s, S8_Lit("."), S8_FindFlag_MatchFindLast, &result.len); - return result; -} - -S8_API S8_String S8_SkipToLastSlash(S8_String s) { - int64_t pos; - S8_String result = s; - if (S8_Seek(s, S8_Lit("/"), S8_FindFlag_MatchFindLast, &pos)) { - result = S8_Skip(result, pos + 1); - } - return result; -} - -S8_API S8_String S8_SkipToLastPeriod(S8_String s) { - int64_t pos; - S8_String result = s; - if (S8_Seek(s, S8_Lit("."), S8_FindFlag_MatchFindLast, &pos)) { - result = S8_Skip(result, pos + 1); - } - return result; -} - -S8_API int64_t S8_Length(char *string) { - int64_t len = 0; - while (*string++ != 0) - len++; - return len; -} - -S8_API int64_t S8_WideLength(char16_t *string) { - int64_t len = 0; - while (*string++ != 0) - len++; - return len; -} - -S8_API S8_String S8_MakeFromChar(char *string) { - S8_String result; - result.str = (char *)string; - result.len = S8_Length(string); - return result; -} - -S8_API S8_String S8_MakeEmpty(void) { - return S8_Make(0, 0); -} - -S8_API S8_List S8_MakeEmptyList(void) { - S8_List result; - result.first = 0; - result.last = 0; - result.char_count = 0; - result.node_count = 0; - return result; -} - -S8_API S8_String S8_FormatV(S8_Allocator allocator, const char *str, va_list args1) { - va_list args2; - va_copy(args2, args1); - int64_t len = S8_VSNPRINTF(0, 0, str, args2); - va_end(args2); - - char *result = (char *)S8_ALLOCATE(allocator, sizeof(char) * (len + 1)); - S8_VSNPRINTF(result, (int)(len + 1), str, args1); - S8_String res = S8_Make(result, len); - return res; -} - -S8_API S8_String S8_Format(S8_Allocator allocator, const char *str, ...) { - S8_FORMAT(allocator, str, result); - return result; -} - -S8_API S8_Node *S8_CreateNode(S8_Allocator allocator, S8_String string) { - S8_Node *result = (S8_Node *)S8_ALLOCATE(allocator, sizeof(S8_Node)); - result->string = string; - result->next = 0; - return result; -} - -S8_API void S8_ReplaceNodeString(S8_List *list, S8_Node *node, S8_String new_string) { - list->char_count -= node->string.len; - list->char_count += new_string.len; - node->string = new_string; -} - -S8_API void S8_AddExistingNode(S8_List *list, S8_Node *node) { - if (list->first) { - list->last->next = node; - list->last = list->last->next; - } - else { - list->first = list->last = node; - } - list->node_count += 1; - list->char_count += node->string.len; -} - -S8_API void S8_AddArray(S8_Allocator allocator, S8_List *list, char **array, int count) { - for (int i = 0; i < count; i += 1) { - S8_String s = S8_MakeFromChar(array[i]); - S8_AddNode(allocator, list, s); - } -} - -S8_API void S8_AddArrayWithPrefix(S8_Allocator allocator, S8_List *list, char *prefix, char **array, int count) { - for (int i = 0; i < count; i += 1) { - S8_AddF(allocator, list, "%s%s", prefix, array[i]); - } -} - -S8_API S8_List S8_MakeList(S8_Allocator allocator, S8_String a) { - S8_List result = S8_MakeEmptyList(); - S8_AddNode(allocator, &result, a); - return result; -} - -S8_API S8_List S8_CopyList(S8_Allocator allocator, S8_List a) { - S8_List result = S8_MakeEmptyList(); - for (S8_Node *it = a.first; it; it = it->next) S8_AddNode(allocator, &result, it->string); - return result; -} - -S8_API S8_List S8_ConcatLists(S8_Allocator allocator, S8_List a, S8_List b) { - S8_List result = S8_MakeEmptyList(); - for (S8_Node *it = a.first; it; it = it->next) S8_AddNode(allocator, &result, it->string); - for (S8_Node *it = b.first; it; it = it->next) S8_AddNode(allocator, &result, it->string); - return result; -} - -S8_API S8_Node *S8_AddNode(S8_Allocator allocator, S8_List *list, S8_String string) { - S8_Node *node = S8_CreateNode(allocator, string); - S8_AddExistingNode(list, node); - return node; -} - -S8_API S8_Node *S8_Add(S8_Allocator allocator, S8_List *list, S8_String string) { - S8_String copy = S8_Copy(allocator, string); - S8_Node *node = S8_CreateNode(allocator, copy); - S8_AddExistingNode(list, node); - return node; -} - -S8_API S8_String S8_AddF(S8_Allocator allocator, S8_List *list, const char *str, ...) { - S8_FORMAT(allocator, str, result); - S8_AddNode(allocator, list, result); - return result; -} - -#ifdef FIRST_UTF_HEADER - -S8_API S16_String S8_ToWidecharEx(S8_Allocator allocator, S8_String string) { - S8_ASSERT(sizeof(char16_t) == 2); - char16_t *buffer = (char16_t *)S8_ALLOCATE(allocator, sizeof(char16_t) * (string.len + 1)); - int64_t size = UTF_CreateWidecharFromChar(buffer, string.len + 1, string.str, string.len); - S16_String result = {buffer, size}; - return result; -} - -S8_API char16_t *S8_ToWidechar(S8_Allocator allocator, S8_String string) { - S16_String result = S8_ToWidecharEx(allocator, string); - return result.str; -} - -S8_API S8_String S8_FromWidecharEx(S8_Allocator allocator, char16_t *wstring, int64_t wsize) { - S8_ASSERT(sizeof(char16_t) == 2); - - int64_t buffer_size = (wsize + 1) * 2; - char *buffer = (char *)S8_ALLOCATE(allocator, buffer_size); - int64_t size = UTF_CreateCharFromWidechar(buffer, buffer_size, wstring, wsize); - S8_String result = S8_Make(buffer, size); - - S8_ASSERT(size < buffer_size); - return result; -} - -S8_API S8_String S8_FromWidechar(S8_Allocator allocator, char16_t *wstring) { - int64_t size = S8_WideLength(wstring); - S8_String result = S8_FromWidecharEx(allocator, wstring, size); - return result; -} - -#endif \ No newline at end of file diff --git a/src/build_tool/standalone_libraries/string.h b/src/build_tool/standalone_libraries/string.h deleted file mode 100644 index a370737..0000000 --- a/src/build_tool/standalone_libraries/string.h +++ /dev/null @@ -1,197 +0,0 @@ -#ifndef FIRST_S8_STRING -#define FIRST_S8_STRING -#include -#include -#include - -#ifndef S8_API - #define S8_API -#endif - -#ifdef __cplusplus - #define S8_IF_CPP(x) x -#else - #define S8_IF_CPP(x) -#endif - -#ifndef S8_Allocator -struct MA_Arena; - #define S8_Allocator MA_Arena * -#endif - -typedef struct S8_String S8_String; -typedef struct S8_Node S8_Node; -typedef struct S8_List S8_List; -S8_API int64_t S8_Length(char *string); - -struct S8_String { - char *str; - int64_t len; -#if defined(__cplusplus) - S8_String() = default; - S8_String(char *s) : str(s), len(S8_Length(s)) {} - S8_String(char *s, int64_t l) : str(s), len(l) {} - S8_String(const char *s) : str((char *)s), len(S8_Length((char *)s)) {} - S8_String(const char *s, int64_t l) : str((char *)s), len(l) {} - #if defined(FIRST_UTF_HEADER) - struct Iter { - UTF8_Iter i; - - Iter &operator++() { - UTF8_Advance(&i); - return *this; - } - - friend bool operator!=(const Iter &a, const Iter &b) { return a.i.item != b.i.item; } - UTF8_Iter &operator*() { return i; } - }; - - Iter begin() { return {UTF8_IterateEx(str, (int)len)}; } - Iter end() { return {}; } - #endif // FIRST_UTF_HEADER -#endif // __cplusplus -}; - -struct S8_Node { - S8_Node *next; - S8_String string; -}; - -struct S8_List { - int64_t node_count; - int64_t char_count; - S8_Node *first; - S8_Node *last; - -#if defined(__cplusplus) - struct Iter { - S8_Node *it; - - Iter &operator++() { - it = it->next; - return *this; - } - - friend bool operator!=(const Iter &a, const Iter &b) { return a.it != b.it; } - S8_String &operator*() { return it->string; } - }; - - Iter begin() { return {first}; } - Iter end() { return {0}; } -#endif -}; - -typedef struct S16_String { - char16_t *str; - int64_t len; -} S16_String; - -typedef int S8_FindFlag; -enum { - S8_FindFlag_None = 0, - S8_FindFlag_IgnoreCase = 1, - S8_FindFlag_MatchFindLast = 2, -}; - -typedef int S8_SplitFlag; -enum { - S8_SplitFlag_None = 0, - S8_SplitFlag_IgnoreCase = 1, - S8_SplitFlag_SplitInclusive = 2, -}; - -static const bool S8_IgnoreCase = true; - -#if defined(__has_attribute) - #if __has_attribute(format) - #define S8__PrintfFormat(fmt, va) __attribute__((format(printf, fmt, va))) - #endif -#endif - -#ifndef S8__PrintfFormat - #define S8__PrintfFormat(fmt, va) -#endif - -#define S8_Lit(string) S8_Make((char *)string, sizeof(string) - 1) -#define S8_ConstLit(string) \ - { string, sizeof(string) - 1 } -#define S8_Expand(string) (int)(string).len, (string).str - -#define S8_FORMAT(allocator, str, result) \ - va_list args1; \ - va_start(args1, str); \ - S8_String result = S8_FormatV(allocator, str, args1); \ - va_end(args1) - -#define S8_For(it, x) for (S8_Node *it = (x).first; it; it = it->next) - -S8_API char CHAR_ToLowerCase(char a); -S8_API char CHAR_ToUpperCase(char a); -S8_API bool CHAR_IsWhitespace(char w); -S8_API bool CHAR_IsAlphabetic(char a); -S8_API bool CHAR_IsIdent(char a); -S8_API bool CHAR_IsDigit(char a); -S8_API bool CHAR_IsAlphanumeric(char a); -S8_API bool S8_AreEqual(S8_String a, S8_String b, unsigned ignore_case S8_IF_CPP(= false)); -S8_API bool S8_EndsWith(S8_String a, S8_String end, unsigned ignore_case S8_IF_CPP(= false)); -S8_API bool S8_StartsWith(S8_String a, S8_String start, unsigned ignore_case S8_IF_CPP(= false)); -S8_API S8_String S8_Make(char *str, int64_t len); -S8_API S8_String S8_Copy(S8_Allocator allocator, S8_String string); -S8_API S8_String S8_CopyChar(S8_Allocator allocator, char *s); -S8_API S8_String S8_NormalizePath(S8_Allocator allocator, S8_String s); -S8_API void S8_NormalizePathUnsafe(S8_String s); // make sure there is no way string is const etc. -S8_API S8_String S8_Chop(S8_String string, int64_t len); -S8_API S8_String S8_Skip(S8_String string, int64_t len); -S8_API S8_String S8_GetPostfix(S8_String string, int64_t len); -S8_API S8_String S8_GetPrefix(S8_String string, int64_t len); -S8_API S8_String S8_Slice(S8_String string, int64_t first_index, int64_t one_past_last_index); -S8_API S8_String S8_Trim(S8_String string); -S8_API S8_String S8_TrimEnd(S8_String string); -S8_API S8_String S8_ToLowerCase(S8_Allocator allocator, S8_String s); -S8_API S8_String S8_ToUpperCase(S8_Allocator allocator, S8_String s); -S8_API bool S8_Seek(S8_String string, S8_String find, S8_FindFlag flags S8_IF_CPP(= S8_FindFlag_None), int64_t *index_out S8_IF_CPP(= 0)); -S8_API int64_t S8_Find(S8_String string, S8_String find, S8_FindFlag flags S8_IF_CPP(= S8_FindFlag_None)); -S8_API S8_String S8_ChopLastSlash(S8_String s); -S8_API S8_String S8_ChopLastPeriod(S8_String s); -S8_API S8_String S8_SkipToLastSlash(S8_String s); -S8_API S8_String S8_SkipToLastPeriod(S8_String s); -S8_API S8_String S8_GetNameNoExt(S8_String s); -S8_API bool S8_IsPointerInside(S8_String string, char *p); -S8_API S8_String S8_SkipToP(S8_String string, char *p); -S8_API S8_String S8_SkipPast(S8_String string, S8_String a); -S8_API int64_t S8_WideLength(char16_t *string); -S8_API S8_String S8_MakeFromChar(char *string); -S8_API S8_String S8_MakeEmpty(void); -S8_API S8_List S8_MakeEmptyList(void); -S8_API S8_String S8_FormatV(S8_Allocator allocator, const char *str, va_list args1); -S8_API S8_String S8_Format(S8_Allocator allocator, const char *str, ...) S8__PrintfFormat(2, 3); - -S8_API S8_List S8_Split(S8_Allocator allocator, S8_String string, S8_String find, S8_SplitFlag flags S8_IF_CPP(= S8_SplitFlag_None)); -S8_API S8_String S8_MergeWithSeparator(S8_Allocator allocator, S8_List list, S8_String separator S8_IF_CPP(= S8_Lit(" "))); -S8_API S8_String S8_Merge(S8_Allocator allocator, S8_List list); -S8_API S8_String S8_ReplaceAll(S8_Allocator allocator, S8_String string, S8_String replace, S8_String with, bool ignore_case S8_IF_CPP(= false)); -S8_API S8_List S8_FindAll(S8_Allocator allocator, S8_String string, S8_String find, bool ignore_case S8_IF_CPP(= false)); - -S8_API S8_Node *S8_CreateNode(S8_Allocator allocator, S8_String string); -S8_API void S8_ReplaceNodeString(S8_List *list, S8_Node *node, S8_String new_string); -S8_API void S8_AddExistingNode(S8_List *list, S8_Node *node); -S8_API void S8_AddArray(S8_Allocator allocator, S8_List *list, char **array, int count); -S8_API void S8_AddArrayWithPrefix(S8_Allocator allocator, S8_List *list, char *prefix, char **array, int count); -S8_API S8_List S8_MakeList(S8_Allocator allocator, S8_String a); -S8_API S8_List S8_CopyList(S8_Allocator allocator, S8_List a); -S8_API S8_List S8_ConcatLists(S8_Allocator allocator, S8_List a, S8_List b); -S8_API S8_Node *S8_AddNode(S8_Allocator allocator, S8_List *list, S8_String string); -S8_API S8_Node *S8_Add(S8_Allocator allocator, S8_List *list, S8_String string); -S8_API S8_String S8_AddF(S8_Allocator allocator, S8_List *list, const char *str, ...) S8__PrintfFormat(3, 4); - -S8_API S16_String S8_ToWidecharEx(S8_Allocator allocator, S8_String string); -S8_API char16_t *S8_ToWidechar(S8_Allocator allocator, S8_String string); -S8_API S8_String S8_FromWidecharEx(S8_Allocator allocator, char16_t *wstring, int64_t wsize); -S8_API S8_String S8_FromWidechar(S8_Allocator allocator, char16_t *wstring); - -#if defined(__cplusplus) -inline S8_String operator""_s(const char *str, size_t size) { return {(char *)str, (int64_t)size}; } -inline bool operator==(S8_String a, S8_String b) { return S8_AreEqual(a, b, 0); } -inline bool operator!=(S8_String a, S8_String b) { return !S8_AreEqual(a, b, 0); } -#endif -#endif \ No newline at end of file diff --git a/src/build_tool/standalone_libraries/unicode.c b/src/build_tool/standalone_libraries/unicode.c deleted file mode 100644 index c8e0465..0000000 --- a/src/build_tool/standalone_libraries/unicode.c +++ /dev/null @@ -1,210 +0,0 @@ -#include "unicode.h" - -#ifndef UTF__MemoryZero - #include - #define UTF__MemoryZero(p, size) memset(p, 0, size) -#endif - -UTF_API UTF32_Result UTF_ConvertUTF16ToUTF32(uint16_t *c, int max_advance) { - UTF32_Result result; - UTF__MemoryZero(&result, sizeof(result)); - if (max_advance >= 1) { - result.advance = 1; - result.out_str = c[0]; - if (c[0] >= 0xD800 && c[0] <= 0xDBFF && c[1] >= 0xDC00 && c[1] <= 0xDFFF) { - if (max_advance >= 2) { - result.out_str = 0x10000; - result.out_str += (uint32_t)(c[0] & 0x03FF) << 10u | (c[1] & 0x03FF); - result.advance = 2; - } - else - result.error = 2; - } - } - else { - result.error = 1; - } - return result; -} - -UTF_API UTF8_Result UTF_ConvertUTF32ToUTF8(uint32_t codepoint) { - UTF8_Result result; - UTF__MemoryZero(&result, sizeof(result)); - - if (codepoint <= 0x7F) { - result.len = 1; - result.out_str[0] = (char)codepoint; - } - else if (codepoint <= 0x7FF) { - result.len = 2; - result.out_str[0] = 0xc0 | (0x1f & (codepoint >> 6)); - result.out_str[1] = 0x80 | (0x3f & codepoint); - } - else if (codepoint <= 0xFFFF) { // 16 bit word - result.len = 3; - result.out_str[0] = 0xe0 | (0xf & (codepoint >> 12)); // 4 bits - result.out_str[1] = 0x80 | (0x3f & (codepoint >> 6)); // 6 bits - result.out_str[2] = 0x80 | (0x3f & codepoint); // 6 bits - } - else if (codepoint <= 0x10FFFF) { // 21 bit word - result.len = 4; - result.out_str[0] = 0xf0 | (0x7 & (codepoint >> 18)); // 3 bits - result.out_str[1] = 0x80 | (0x3f & (codepoint >> 12)); // 6 bits - result.out_str[2] = 0x80 | (0x3f & (codepoint >> 6)); // 6 bits - result.out_str[3] = 0x80 | (0x3f & codepoint); // 6 bits - } - else { - result.error = 1; - } - - return result; -} - -UTF_API UTF32_Result UTF_ConvertUTF8ToUTF32(char *c, int max_advance) { - UTF32_Result result; - UTF__MemoryZero(&result, sizeof(result)); - - if ((c[0] & 0x80) == 0) { // Check if leftmost zero of first byte is unset - if (max_advance >= 1) { - result.out_str = c[0]; - result.advance = 1; - } - else result.error = 1; - } - - else if ((c[0] & 0xe0) == 0xc0) { - if ((c[1] & 0xc0) == 0x80) { // Continuation byte required - if (max_advance >= 2) { - result.out_str = (uint32_t)(c[0] & 0x1f) << 6u | (c[1] & 0x3f); - result.advance = 2; - } - else result.error = 2; - } - else result.error = 2; - } - - else if ((c[0] & 0xf0) == 0xe0) { - if ((c[1] & 0xc0) == 0x80 && (c[2] & 0xc0) == 0x80) { // Two continuation bytes required - if (max_advance >= 3) { - result.out_str = (uint32_t)(c[0] & 0xf) << 12u | (uint32_t)(c[1] & 0x3f) << 6u | (c[2] & 0x3f); - result.advance = 3; - } - else result.error = 3; - } - else result.error = 3; - } - - else if ((c[0] & 0xf8) == 0xf0) { - if ((c[1] & 0xc0) == 0x80 && (c[2] & 0xc0) == 0x80 && (c[3] & 0xc0) == 0x80) { // Three continuation bytes required - if (max_advance >= 4) { - result.out_str = (uint32_t)(c[0] & 0xf) << 18u | (uint32_t)(c[1] & 0x3f) << 12u | (uint32_t)(c[2] & 0x3f) << 6u | (uint32_t)(c[3] & 0x3f); - result.advance = 4; - } - else result.error = 4; - } - else result.error = 4; - } - else result.error = 4; - - return result; -} - -UTF_API UTF16_Result UTF_ConvertUTF32ToUTF16(uint32_t codepoint) { - UTF16_Result result; - UTF__MemoryZero(&result, sizeof(result)); - if (codepoint < 0x10000) { - result.out_str[0] = (uint16_t)codepoint; - result.out_str[1] = 0; - result.len = 1; - } - else if (codepoint <= 0x10FFFF) { - uint32_t code = (codepoint - 0x10000); - result.out_str[0] = (uint16_t)(0xD800 | (code >> 10)); - result.out_str[1] = (uint16_t)(0xDC00 | (code & 0x3FF)); - result.len = 2; - } - else { - result.error = 1; - } - - return result; -} - -#define UTF__HANDLE_DECODE_ERROR(question_mark) \ - { \ - if (outlen < buffer_size - 1) buffer[outlen++] = (question_mark); \ - break; \ - } - -UTF_API int64_t UTF_CreateCharFromWidechar(char *buffer, int64_t buffer_size, char16_t *in, int64_t inlen) { - int64_t outlen = 0; - for (int64_t i = 0; i < inlen && in[i];) { - UTF32_Result decode = UTF_ConvertUTF16ToUTF32((uint16_t *)(in + i), (int)(inlen - i)); - if (!decode.error) { - i += decode.advance; - UTF8_Result encode = UTF_ConvertUTF32ToUTF8(decode.out_str); - if (!encode.error) { - for (int64_t j = 0; j < encode.len; j++) { - if (outlen < buffer_size - 1) { - buffer[outlen++] = encode.out_str[j]; - } - } - } - else UTF__HANDLE_DECODE_ERROR('?'); - } - else UTF__HANDLE_DECODE_ERROR('?'); - } - - buffer[outlen] = 0; - return outlen; -} - -UTF_API int64_t UTF_CreateWidecharFromChar(char16_t *buffer, int64_t buffer_size, char *in, int64_t inlen) { - int64_t outlen = 0; - for (int64_t i = 0; i < inlen;) { - UTF32_Result decode = UTF_ConvertUTF8ToUTF32(in + i, (int)(inlen - i)); - if (!decode.error) { - i += decode.advance; - UTF16_Result encode = UTF_ConvertUTF32ToUTF16(decode.out_str); - if (!encode.error) { - for (int64_t j = 0; j < encode.len; j++) { - if (outlen < buffer_size - 1) { - buffer[outlen++] = encode.out_str[j]; - } - } - } - else UTF__HANDLE_DECODE_ERROR(0x003f); - } - else UTF__HANDLE_DECODE_ERROR(0x003f); - } - - buffer[outlen] = 0; - return outlen; -} - -UTF_API void UTF8_Advance(UTF8_Iter *iter) { - iter->i += iter->utf8_codepoint_byte_size; - UTF32_Result r = UTF_ConvertUTF8ToUTF32(iter->str + iter->i, iter->len - iter->i); - if (r.error) { - iter->item = 0; - return; - } - - iter->utf8_codepoint_byte_size = r.advance; - iter->item = r.out_str; -} - -UTF_API UTF8_Iter UTF8_IterateEx(char *str, int len) { - UTF8_Iter result; - UTF__MemoryZero(&result, sizeof(result)); - result.str = str; - result.len = len; - if (len) UTF8_Advance(&result); - return result; -} - -UTF_API UTF8_Iter UTF8_Iterate(char *str) { - int length = 0; - while (str[length]) length += 1; - return UTF8_IterateEx(str, length); -} diff --git a/src/build_tool/standalone_libraries/unicode.h b/src/build_tool/standalone_libraries/unicode.h deleted file mode 100644 index 941f3bb..0000000 --- a/src/build_tool/standalone_libraries/unicode.h +++ /dev/null @@ -1,55 +0,0 @@ -#ifndef FIRST_UTF_HEADER -#define FIRST_UTF_HEADER -#define UTF_HEADER -#include -typedef struct UTF32_Result UTF32_Result; -typedef struct UTF8_Result UTF8_Result; -typedef struct UTF16_Result UTF16_Result; -typedef struct UTF8_Iter UTF8_Iter; - -#ifndef UTF_API - #ifdef __cplusplus - #define UTF_API extern "C" - #else - #define UTF_API - #endif -#endif - -struct UTF32_Result { - uint32_t out_str; - int advance; - int error; -}; - -struct UTF8_Result { - uint8_t out_str[4]; - int len; - int error; -}; - -struct UTF16_Result { - uint16_t out_str[2]; - int len; - int error; -}; - -struct UTF8_Iter { - char *str; - int len; - int utf8_codepoint_byte_size; - int i; - uint32_t item; -}; - -UTF_API UTF32_Result UTF_ConvertUTF16ToUTF32(uint16_t *c, int max_advance); -UTF_API UTF8_Result UTF_ConvertUTF32ToUTF8(uint32_t codepoint); -UTF_API UTF32_Result UTF_ConvertUTF8ToUTF32(char *c, int max_advance); -UTF_API UTF16_Result UTF_ConvertUTF32ToUTF16(uint32_t codepoint); -UTF_API int64_t UTF_CreateCharFromWidechar(char *buffer, int64_t buffer_size, char16_t *in, int64_t inlen); -UTF_API int64_t UTF_CreateWidecharFromChar(char16_t *buffer, int64_t buffer_size, char *in, int64_t inlen); -UTF_API void UTF8_Advance(UTF8_Iter *iter); -UTF_API UTF8_Iter UTF8_IterateEx(char *str, int len); -UTF_API UTF8_Iter UTF8_Iterate(char *str); - -#define UTF8_For(name, str, len) for (UTF8_Iter name = UTF8_IterateEx(str, (int)len); name.item; UTF8_Advance(&name)) -#endif \ No newline at end of file diff --git a/src/text_editor/commands.cpp b/src/text_editor/commands.cpp index e75da59..56468b6 100644 --- a/src/text_editor/commands.cpp +++ b/src/text_editor/commands.cpp @@ -709,7 +709,6 @@ void EncloseLine(View *view) { Int eof = 0; it.range.max = GetFullLineEnd(buffer, it.range.max, &eof); it.range.min = GetFullLineStart(buffer, it.range.min); - it.range.min -= Clamp(eof, (Int)0, buffer->len); } } @@ -1216,8 +1215,11 @@ void Command_ListBuffers() { ActiveWindow = main.window->id; JumpGarbageBuffer(&main); for (Buffer *it = FirstBuffer; it; it = it->next) { - Command_Appendf(main.view, "%.*s\n", FmtString(it->name)); + RawAppendf(main.buffer, "%-80.*s || %.*s\n", FmtString(SkipToLastSlash(it->name)), FmtString(it->name)); } + main.view->fuzzy_search = true; + main.view->update_scroll = true; + Command_SelectRangeOneCursor(main.view, GetEndAsRange(main.buffer)); } int Lua_ListBuffers(lua_State *L) {