From f68500a804e6de654f8749f4eed430521a2231f6 Mon Sep 17 00:00:00 2001 From: Krzosa Karol Date: Fri, 12 Jan 2024 09:54:41 +0100 Subject: [PATCH] Restructuring and add format strings typechecking for clang --- .github/workflows/run-tests.yml | 4 ++-- build.bat | 3 +-- build.sh | 2 +- build_file.cpp | 10 +++++----- code/filesystem.c | 13 +++++++------ code/hash.h | 5 ----- code/io.h | 14 ++++++++++++-- code/load_library.c | 2 +- code/string.h | 14 ++++++++++++-- code/table.hpp | 4 ++-- test/test_filesystem.c | 4 ---- {code => tools}/build_lib.cpp | 14 +++++++++----- {code => tools}/build_main.cpp | 18 +++++++++--------- 13 files changed, 61 insertions(+), 46 deletions(-) rename {code => tools}/build_lib.cpp (96%) rename {code => tools}/build_main.cpp (71%) diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index 4ed5c03..45c0af2 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -5,13 +5,13 @@ jobs: steps: - uses: actions/checkout@v4 - run: sudo apt install g++ - - run: g++ code/build_main.cpp -o bld && ./bld + - run: g++ tools/build_main.cpp -o bld && ./bld run-and-compile-mac: runs-on: macos-latest steps: - uses: actions/checkout@v4 - run: brew install llvm - - run: clang++ code/build_main.cpp -std=c++11 -o bld && ./bld + - run: clang++ tools/build_main.cpp -std=c++11 -o bld && ./bld run-and-compile-windows: runs-on: windows-latest steps: diff --git a/build.bat b/build.bat index e9aeadc..1f0eb17 100644 --- a/build.bat +++ b/build.bat @@ -3,7 +3,6 @@ call ../misc/compile_setup.bat mkdir build cd build -cl -Fe:bld.exe ../code/build_main.cpp -WX -W3 -wd4200 -diagnostics:column -nologo -Zi -D_CRT_SECURE_NO_WARNINGS +cl -Fe:bld.exe ../tools/build_main.cpp -WX -W3 -wd4200 -diagnostics:column -nologo -Zi -D_CRT_SECURE_NO_WARNINGS cd .. build\bld.exe - diff --git a/build.sh b/build.sh index 2949aac..e73a0fc 100644 --- a/build.sh +++ b/build.sh @@ -1,3 +1,3 @@ #!/usr/bin/env bash -gcc -o bld code/build_main.cpp -g +gcc -o bld tools/build_main.cpp -g ./bld diff --git a/build_file.cpp b/build_file.cpp index e53b810..2790bc0 100644 --- a/build_file.cpp +++ b/build_file.cpp @@ -1,4 +1,4 @@ -#include "code/build_lib.cpp" +#include "tools/build_lib.cpp" void CompileFiles(Strs cc, Strs files); int ReturnValue = 0; @@ -21,17 +21,17 @@ void CompileFiles(Strs cc, Strs files) { Str exe = FilenameWithoutExt(files[0]); Str filestr = Merge(files); if (cc == "gcc") { - result = OS_SystemF("g++ -o %Q.exe %Q -g -Wno-write-strings -fsanitize=address", exe, filestr); + result = OS_SystemF("g++ -o %.*s.exe %.*s -g -Wno-write-strings -fsanitize=address", S8_Expand(exe), S8_Expand(filestr)); } else if (cc == "clang") { - result = OS_SystemF("clang++ -std=c++11 -o %Q.exe %Q -g -Wno-writable-strings -fsanitize=address", exe, filestr); + result = OS_SystemF("clang++ -std=c++11 -o %.*s.exe %.*s -fdiagnostics-absolute-paths -g -Wno-writable-strings -fsanitize=address", S8_Expand(exe), S8_Expand(filestr)); } else { - result = OS_SystemF("cl -Fe:%Q.exe %Q -Zi -WX -W3 -wd4200 -diagnostics:column -nologo -D_CRT_SECURE_NO_WARNINGS -fsanitize=address -RTC1", exe, filestr); + result = OS_SystemF("cl -Fe:%.*s.exe %.*s -FC -Zi -WX -W3 -wd4200 -diagnostics:column -nologo -D_CRT_SECURE_NO_WARNINGS -fsanitize=address -RTC1", S8_Expand(exe), S8_Expand(filestr)); } if (result == 0) { - result = OS_SystemF(IF_WINDOWS_ELSE("", "./") "%Q.exe", exe); + result = OS_SystemF(IF_WINDOWS_ELSE("", "./") "%.*s.exe", S8_Expand(exe)); } else { ReturnValue = result; diff --git a/code/filesystem.c b/code/filesystem.c index a226560..24f5c76 100644 --- a/code/filesystem.c +++ b/code/filesystem.c @@ -169,7 +169,8 @@ OS_API S8_List OS_ListDir(MA_Arena *arena, S8_String path, unsigned flags) { bool dir = ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY; S8_String filename = UTF_CreateStringFromWidechar(scratch.arena, ffd.cFileName, S8_WideLength(ffd.cFileName)); - S8_String rel_abs_path = S8_Format(scratch.arena, "%Q/%Q%Q", it->string, filename, dir ? S8_Lit("/") : S8_Lit("")); + S8_String is_dir = dir ? S8_Lit("/") : S8_Lit(""); + S8_String rel_abs_path = S8_Format(scratch.arena, "%.*s/%.*s%.*s", S8_Expand(it->string), S8_Expand(filename), S8_Expand(is_dir)); if (flags & OS_RELATIVE_PATHS) { S8_Add(arena, &result, rel_abs_path); } @@ -498,12 +499,12 @@ OS_API S8_List OS_ListDir(MA_Arena *arena, S8_String path, unsigned flags) { continue; } - S8_String n = S8_Format(scratch.arena, "%Q/%s", path, dir->d_name); + S8_String n = S8_Format(scratch.arena, "%.*s/%s", S8_Expand(path), dir->d_name); if ((flags & OS_RELATIVE_PATHS) == 0) { n = OS_GetAbsolutePath(scratch.arena, n); } if (dir->d_type == DT_DIR) { - n = S8_Format(scratch.arena, "%Q/", n); + n = S8_Format(scratch.arena, "%.*s/", S8_Expand(n)); } S8_AddNode(arena, &result, S8_Copy(arena, n)); @@ -525,18 +526,18 @@ OS_API OS_Result OS_MakeDir(S8_String path) { 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 %Q %Q", ow, from, to); + 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 %Q"); + 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 %Q"); + int result = OS_SystemF("rm -r %.*s", S8_Expand(path)); return result == 0 ? OS_SUCCESS : OS_FAILURE; } diff --git a/code/hash.h b/code/hash.h index faaeac6..cf442c5 100644 --- a/code/hash.h +++ b/code/hash.h @@ -9,15 +9,11 @@ #endif #endif -//@begin gen_structs typedef struct RandomSeed RandomSeed; -//@end gen_structs - struct RandomSeed { uint64_t a; }; -//@begin gen_api_funcs 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); @@ -25,7 +21,6 @@ HASH_API_FUNCTION int GetRandomRangeI(RandomSeed *seed, int first, int last_incl 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); -//@end gen_api_funcs #define WRAP_AROUND_POWER_OF_2(x, pow2) (((x) & ((pow2)-1llu))) static inline float GetRandomNormalF(RandomSeed *series) { return (float)GetRandomNormal(series); } diff --git a/code/io.h b/code/io.h index 678ca90..a328911 100644 --- a/code/io.h +++ b/code/io.h @@ -21,6 +21,16 @@ typedef enum IO_ErrorResult { #define IO_DebugBreak() (IO_Exit(1), 0) #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 + extern void (*IO_User_OutputMessage)(char *str, int len); #define IO__STRINGIFY(x) #x @@ -63,8 +73,8 @@ extern void (*IO_User_OutputMessage)(char *str, int len); } #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_API void IO_Printf(const char *msg, ...); +IO_API bool IO__FatalErrorf(const char *file, int line, const char *msg, ...) IO__PrintfFormat(3, 4); +IO_API void IO_Printf(const char *msg, ...) IO__PrintfFormat(1, 2); IO_API bool IO__FatalError(char *msg); IO_API void IO_Print(char *msg); IO_API void IO_OutputMessage(char *str, int len); diff --git a/code/load_library.c b/code/load_library.c index 0f44622..eda26be 100644 --- a/code/load_library.c +++ b/code/load_library.c @@ -14,7 +14,7 @@ LIB_Library LIB_LoadLibrary(char *str) { } void *LIB_LoadSymbol(LIB_Library lib, char *symbol) { - void *result = GetProcAddress((HMODULE)lib, symbol); + void *result = (void *)GetProcAddress((HMODULE)lib, symbol); return result; } diff --git a/code/string.h b/code/string.h index 1c75c78..375bdc2 100644 --- a/code/string.h +++ b/code/string.h @@ -44,6 +44,16 @@ enum { S8_MATCH_FIND_LAST = 32, }; +#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 } @@ -104,7 +114,7 @@ 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_API S8_String S8_Format(S8_Allocator allocator, const char *str, ...) S8__PrintfFormat(2, 3); 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); @@ -115,4 +125,4 @@ 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_API S8_String S8_AddF(S8_Allocator allocator, S8_List *list, const char *str, ...) S8__PrintfFormat(3, 4); diff --git a/code/table.hpp b/code/table.hpp index ed95877..e6a7d4f 100644 --- a/code/table.hpp +++ b/code/table.hpp @@ -38,10 +38,10 @@ #define TABLE_ASSERT(x) assert(x) #endif -#ifndef TABLE_SET_DEFAULT_ALLOCATOR - #define TABLE_SET_DEFAULT_ALLOCATOR // Example: // #define TABLE_SET_DEFAULT_ALLOCATOR if (!allocator) allocator = global_heap; +#ifndef TABLE_SET_DEFAULT_ALLOCATOR + #define TABLE_SET_DEFAULT_ALLOCATOR #endif #ifndef TABLE_HASH_BYTES diff --git a/test/test_filesystem.c b/test/test_filesystem.c index a1384bd..23b306e 100644 --- a/test/test_filesystem.c +++ b/test/test_filesystem.c @@ -55,10 +55,6 @@ int main() { S8_String dir_path = OS_GetExeDir(&arena); S8_String work_path = OS_GetWorkingDir(&arena); S8_String abs_path = OS_GetAbsolutePath(&arena, read_file_path); - // IO_Printf("Exe path = %Q\n", exe_path); - // IO_Printf("Dir path = %Q\n", dir_path); - // IO_Printf("Working path = %Q\n", work_path); - // IO_Printf("Abs path = %Q\n", abs_path); IO_Assert(OS_IsDir(dir_path)); IO_Assert(!OS_IsFile(dir_path)); diff --git a/code/build_lib.cpp b/tools/build_lib.cpp similarity index 96% rename from code/build_lib.cpp rename to tools/build_lib.cpp index d5ad450..d6a5d41 100644 --- a/code/build_lib.cpp +++ b/tools/build_lib.cpp @@ -23,6 +23,10 @@ RELEASE_LINK = -opt:ref -opt:icf /RTC1 = runtime error checks /opt:ref = eliminates functions and data that are never referenced /opt:icf = eliminates redundant 'COMDAT's + +----------------- CLANG ----------------- +FLAGS = -fdiagnostics-absolute-paths -g -Wno-writable-strings +DEBUG = -fsanitize=address */ #ifndef _CRT_SECURE_NO_WARNINGS @@ -37,7 +41,7 @@ RELEASE_LINK = -opt:ref -opt:icf #define CL_VSNPRINTF stbsp_vsnprintf #define CL_SNPRINTF stbsp_snprintf #define AND_CL_STRING_TERMINATE_ON_NEW_LINE -#include "clexer.c" +#include "../code/clexer.c" #define SRC_CACHE_ENTRY_COUNT 1024 struct SRC_CacheEntry { @@ -316,7 +320,7 @@ void MakeDir(char *str) { OS_MakeDir(S8_MakeFromChar(str)); } void ChangeDir(char *str) { OS_SetWorkingDir(S8_MakeFromChar(str)); } int Run(Strs s) { Str cmd = Merge(s); - return OS_SystemF("%Q", cmd); + return OS_SystemF("%.*s", S8_Expand(cmd)); } Strs ListDir(char *dir) { @@ -328,9 +332,9 @@ Strs ListDir(char *dir) { void ReportError(S8_String it) { IO_FatalErrorf("Invalid command line argument syntax! Expected a key value pair!\n" - "Here is the wrong argument: %Q\n" + "Here is the wrong argument: %.*s\n" "Here is a good example: bld.exe profile=release platform=windows\n", - it); + S8_Expand(it)); } #ifndef BUILD_MAIN @@ -347,7 +351,7 @@ int main(int argc, char **argv) { S8_String value = S8_Skip(it, idx + 1); if (key.len == 0) ReportError(it); if (value.len == 0) ReportError(it); - IO_Printf("[%d] %Q = %Q\n", i, key, value); + IO_Printf("[%d] %.*s = %.*s\n", i, S8_Expand(key), S8_Expand(value)); CMDLine.put(key, value); } diff --git a/code/build_main.cpp b/tools/build_main.cpp similarity index 71% rename from code/build_main.cpp rename to tools/build_main.cpp index 7470175..1403519 100644 --- a/code/build_main.cpp +++ b/tools/build_main.cpp @@ -4,7 +4,8 @@ int main(int argument_count, char **arguments) { OS_MakeDir(S8_Lit("build")); OS_SetWorkingDir(S8_Lit("build")); - IO_Printf("WORKING DIR: %Q\n", OS_GetWorkingDir(Perm)); + S8_String working_dir = OS_GetWorkingDir(Perm); + IO_Printf("WORKING DIR: %.*s\n", S8_Expand(working_dir)); S8_String cc = ON_WINDOWS("cl"_s) ON_MAC("clang"_s) ON_LINUX("gcc"_s); S8_String cache_filename = "build_tool.cache"_s; @@ -17,7 +18,7 @@ int main(int argument_count, char **arguments) { break; } - cmdline_args = S8_Format(Perm, "%Q%Q ", cmdline_args, arg); + cmdline_args = S8_Format(Perm, "%.*s%.*s ", S8_Expand(cmdline_args), S8_Expand(arg)); } SRC_InitCache(Perm, cache_filename); @@ -33,29 +34,28 @@ int main(int argument_count, char **arguments) { } if (build_file.str == 0) { - IO_Printf("IDLE Nothing to do, couldnt find build file in current dir: %Q, exiting ... \n", OS_GetWorkingDir(Perm)); + IO_Printf("IDLE Nothing to do, couldnt find build file in current dir: %.*s, exiting ... \n", S8_Expand(working_dir)); return 0; } } S8_String a = S8_ChopLastPeriod(build_file); S8_String b = S8_SkipToLastSlash(a); - S8_String exe_name = S8_Format(Perm, "%Q.exe", b); + S8_String exe_name = S8_Format(Perm, "%.*s.exe", S8_Expand(b)); - // @todo: add search path? // 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"_s) { - result = OS_SystemF("cl %Q -Fe:%Q -WX -W3 -wd4200 -diagnostics:column -nologo -Zi", build_file, exe_name); + result = OS_SystemF("cl %.*s -Fe:%.*s -WX -W3 -wd4200 -diagnostics:column -nologo -Zi", S8_Expand(build_file), S8_Expand(exe_name)); } else if (cc == "clang"_s) { - result = OS_SystemF("clang++ -std=c++11 -Wno-writable-strings %Q -o %Q -g", build_file, exe_name); + result = OS_SystemF("clang++ -std=c++11 -Wno-writable-strings %.*s -o %.*s -g", S8_Expand(build_file), S8_Expand(exe_name)); } else { IO_Assert(cc == "gcc"_s); - result = OS_SystemF("gcc -Wno-write-strings %Q -o %Q -g", build_file, exe_name); + result = OS_SystemF("gcc -Wno-write-strings %.*s -o %.*s -g", S8_Expand(build_file), S8_Expand(exe_name)); } if (result != 0) { @@ -69,7 +69,7 @@ int main(int argument_count, char **arguments) { // Run the build file double time = OS_GetTime(); if (build_file.str) { - int result = OS_SystemF(IF_WINDOWS_ELSE("", "./") "%Q %Q", exe_name, cmdline_args); + int result = OS_SystemF(IF_WINDOWS_ELSE("", "./") "%.*s %.*s", S8_Expand(exe_name), S8_Expand(cmdline_args)); if (result != 0) { printf("FAILED execution of the build file!\n"); return 1;