From 43f770b7908a23d07c0b0dadd8b48708b3cacf50 Mon Sep 17 00:00:00 2001 From: Krzosa Karol Date: Sat, 27 Jan 2024 19:32:12 +0100 Subject: [PATCH] Many changes, building many targets at the same time --- .gitignore | 1 + build.bat | 1 + build.sh | 2 +- build_file.cpp | 54 +++++------ build_tool/easy_strings.cpp | 8 +- build_tool/library.cpp | 3 +- build_tool/process.cpp | 139 +++++++++++++++++++++++++++++ core_library/core.c | 6 +- core_library/core.h | 1 - core_library/filesystem.c | 18 ++-- standalone_libraries/clexer.c | 15 ++++ standalone_libraries/io.c | 6 +- standalone_libraries/io.h | 6 +- standalone_libraries/preproc_env.h | 8 +- standalone_libraries/string.c | 35 ++++++++ standalone_libraries/string.h | 10 +++ standalone_libraries/unicode.c | 3 + tests/test_thread.cpp | 128 ++++++++++++++++++++++++++ 18 files changed, 386 insertions(+), 58 deletions(-) create mode 100644 build_tool/process.cpp create mode 100644 tests/test_thread.cpp diff --git a/.gitignore b/.gitignore index 126820f..a0f30e0 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,7 @@ *.10x *.sublime-project *.sublime-workspace +*.rdbg backup.* bld imgui.ini diff --git a/build.bat b/build.bat index 02bda1c..3fa39b2 100644 --- a/build.bat +++ b/build.bat @@ -5,3 +5,4 @@ cl -Fe:bld.exe ../build_tool/main.cpp -FC -WX -W3 -wd4200 -diagnostics:column -n cd .. rem build\bld.exe clear_cache build\bld.exe +rem build\bld.exe cc=clang diff --git a/build.sh b/build.sh index 8ab3e5a..167dc12 100644 --- a/build.sh +++ b/build.sh @@ -1,3 +1,3 @@ #!/usr/bin/env bash -gcc -o bld build_tool/main.cpp -g +g++ -o bld build_tool/main.cpp -g ./bld diff --git a/build_file.cpp b/build_file.cpp index 5bb26a2..81f88ef 100644 --- a/build_file.cpp +++ b/build_file.cpp @@ -7,8 +7,9 @@ int main(int argc, char **argv) { Array cmd = CMD_Make(argv, argc); S8_String cc = CMD_Get(cmd, "cc", IF_WINDOWS("cl") IF_MAC("clang") IF_LINUX("gcc")); - Compile(cc, "../tests/test_main.cpp"); - Compile(cc, "../tests/test_filesystem.c"); + Compile(cc, "../tests/test_thread.cpp"); + // Compile(cc, "../tests/test_main.cpp"); + // Compile(cc, "../tests/test_filesystem.c"); return ReturnValue; } @@ -18,43 +19,46 @@ void Compile(S8_String cc, S8_String file) { S8_String name_no_ext = S8_GetNameNoExt(file); S8_String exe = Fmt("%.*s.exe", S8_Expand(name_no_ext)); + bool is_cpp = S8_EndsWith(file, ".cpp"); if (cc == "cl") { - Array flags = Split("/MP /Zi -D_CRT_SECURE_NO_WARNINGS /GF /Gm- /Oi"); - flags += Split("/FC /WX /W3 /wd4200 /diagnostics:column /nologo"); - flags += Split("/GR- /EHa-"); - flags += Split("-RTC1"); - Array link = Split("/link /incremental:no"); - S8_String name = Fmt("/Fe:%.*s", S8_Expand(exe)); + Array flags = {Perm}; + flags += "/MP /Zi -D_CRT_SECURE_NO_WARNINGS"; + flags += "/FC /WX /W3 /wd4200 /diagnostics:column /nologo"; + flags += "/GF /Gm- /Oi"; + flags += "/GR- /EHa-"; + flags += "/D_DEBUG -RTC1 -Od"; + flags += Fmt("/Fe:%.*s", S8_Expand(exe)); - result = Run(cc + file + name + flags + link); + Array link = {Perm}; + link += "/link /incremental:no"; + + result = Run(cc + file + flags + link); } else if (cc == "clang") { - Array flags = Split("-g -Wno-write-strings -fdiagnostics-absolute-paths"); + if (is_cpp) cc = "clang++"; + + Array flags = {Perm}; + flags += "-g -Wno-write-strings"; + flags += "-fdiagnostics-absolute-paths"; flags += "-fsanitize=address"; + if (is_cpp) flags += "-std=c++11"; + flags += Fmt("-o %.*s", S8_Expand(exe)); - if (S8_EndsWith(file, ".cpp")) { - cc = "clang++"; - flags += "-std=c++11"; - } - - S8_String name = Fmt("-o %.*s", S8_Expand(exe)); - result = Run(cc + file + name + flags); + result = Run(cc + file + flags); } else { IO_Assert(cc == "gcc"); + if (is_cpp) cc = "g++"; - Array flags = Split("-g -Wno-write-strings"); + Array flags = {Perm}; + flags += "-g -Wno-write-strings"; flags += "-fsanitize=address"; + if (is_cpp) flags += "-std=c++11"; + flags += Fmt("-o %.*s", S8_Expand(exe)); - if (S8_EndsWith(file, ".cpp")) { - cc = "g++"; - flags += "-std=c++11"; - } - - S8_String name = Fmt("-o %.*s", S8_Expand(exe)); - result = Run(cc + file + name + flags); + result = Run(cc + file + flags); } if (result == 0) result = OS_SystemF(IF_WINDOWS_ELSE("", "./") "%.*s", S8_Expand(exe)); diff --git a/build_tool/easy_strings.cpp b/build_tool/easy_strings.cpp index f8b961b..6e582d1 100644 --- a/build_tool/easy_strings.cpp +++ b/build_tool/easy_strings.cpp @@ -45,7 +45,7 @@ Array Split(char *str) { return result; } -S8_String Merge(Array list, S8_String separator = " "_s) { +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 {}; @@ -54,7 +54,7 @@ S8_String Merge(Array list, S8_String separator = " "_s) { 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(Perm, sizeof(char) * 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); @@ -70,6 +70,10 @@ S8_String Merge(Array list, S8_String separator = " "_s) { 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; diff --git a/build_tool/library.cpp b/build_tool/library.cpp index b1c6ac1..1306caa 100644 --- a/build_tool/library.cpp +++ b/build_tool/library.cpp @@ -1,5 +1,5 @@ #ifndef _CRT_SECURE_NO_WARNINGS -#define _CRT_SECURE_NO_WARNINGS + #define _CRT_SECURE_NO_WARNINGS #endif #include "../core_library/core.c" @@ -53,4 +53,3 @@ S8_String Clang_Debug = "-fsanitize=address -g"; S8_String GCC_Flags = "-Wno-write-strings"; S8_String GCC_NoStd = "-fno-exceptions"; S8_String GCC_Debug = "-fsanitize=address -g"; - diff --git a/build_tool/process.cpp b/build_tool/process.cpp new file mode 100644 index 0000000..83563a5 --- /dev/null +++ b/build_tool/process.cpp @@ -0,0 +1,139 @@ +struct TH_Process { + bool is_valid; + char platform[32]; +}; + +#if OS_WINDOWS +TH_Process TH_CreateProcess(S8_String in_cmd, S8_String in_working_dir = "") { + MA_Scratch scratch; + if (in_working_dir != "" && !OS_IsAbsolute(in_working_dir)) { + in_working_dir = OS_GetAbsolutePath(scratch, in_working_dir); + } + + wchar_t *application_name = NULL; + wchar_t *cmd = S8_ToWidechar(scratch, in_cmd); + BOOL inherit_handles = FALSE; + DWORD creation_flags = 0; + void *enviroment = NULL; + wchar_t *working_dir = in_working_dir == "" ? NULL : S8_ToWidechar(scratch, in_working_dir); + STARTUPINFOW startup_info = {}; + startup_info.cb = sizeof(STARTUPINFOW); + TH_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 \nworking_dir: %.*s\ncmd: %.*s\nwindows_message: %s", S8_Expand(in_working_dir), S8_Expand(in_cmd), lpMsgBuf); + } + return result; +} + +int TH_WaitForProcessExit(TH_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; + +TH_Process TH_CreateProcess(S8_String cmd, S8_String working_dir = "") { + MA_Scratch scratch; + if (working_dir != "" && !OS_IsAbsolute(working_dir)) { + working_dir = OS_GetAbsolutePath(scratch, working_dir); + } + + TH_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 = {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); + } + + S8_String prev_dir = {}; + if (working_dir != "") prev_dir = OS_GetWorkingDir(scratch); + if (working_dir != "") OS_SetWorkingDir(working_dir); + int err = posix_spawnp(&u->pid, exec_file.str, NULL, NULL, args.data, environ); + if (err == 0) { + result.is_valid = true; + } + else { + perror("Failed to create process"); + IO_FatalErrorf("Failed to create process \nworking_dir: %.*s\ncmd: %.*s", S8_Expand(working_dir), S8_Expand(cmd)); + } + if (working_dir != "") OS_SetWorkingDir(prev_dir); + + return result; +} + +int TH_WaitForProcessExit(TH_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 diff --git a/core_library/core.c b/core_library/core.c index bfc1e80..d8cbd88 100644 --- a/core_library/core.c +++ b/core_library/core.c @@ -3,6 +3,8 @@ leeway for big buffers and other such things. Just make sure to not relay on it because it's easier unless specified. - Not sure if we should assume that strings should use allocators or arenas, for now it's arenas because I don't have other use cases @todo +- Remove static buffers from filesystem, use scratch arenas instead? +- Use allocators instead of concrete Arenas - Add proper string arrays and utilities for build files - also add String Arrays and String Builder, temp allocators hook ins for nicer api */ @@ -28,7 +30,3 @@ #include "../standalone_libraries/hash.c" #include "../standalone_libraries/load_library.c" #include "filesystem.c" - -// #if LANG_CPP -// #include "string.cpp" -// #endif \ No newline at end of file diff --git a/core_library/core.h b/core_library/core.h index 0521cc3..e4a93db 100644 --- a/core_library/core.h +++ b/core_library/core.h @@ -28,5 +28,4 @@ #define ARRAY_SET_DEFAULT_ALLOCATOR \ if (!allocator.p) allocator = M_GetSystemAllocator(); #include "../standalone_libraries/array.hpp" -// #include "string.hpp" #endif diff --git a/core_library/filesystem.c b/core_library/filesystem.c index dfee07c..275d094 100644 --- a/core_library/filesystem.c +++ b/core_library/filesystem.c @@ -46,7 +46,7 @@ OS_API S8_String OS_GetExePath(MA_Arena *arena) { DWORD wsize = GetModuleFileNameW(0, wbuffer, MA_LENGTHOF(wbuffer)); IO_Assert(wsize != 0); - S8_String path = UTF_CreateStringFromWidechar(arena, wbuffer, wsize); + S8_String path = S8_FromWidecharEx(arena, wbuffer, wsize); S8_NormalizePathUnsafe(path); return path; } @@ -66,7 +66,7 @@ OS_API S8_String OS_GetWorkingDir(MA_Arena *arena) { wbuffer[wsize++] = '/'; wbuffer[wsize] = 0; - S8_String path = UTF_CreateStringFromWidechar(arena, wbuffer, wsize); + S8_String path = S8_FromWidecharEx(arena, wbuffer, wsize); S8_NormalizePathUnsafe(path); return path; } @@ -84,7 +84,7 @@ OS_API S8_String OS_GetAbsolutePath(MA_Arena *arena, S8_String relative) { DWORD written = GetFullPathNameW((wchar_t *)wpath, MA_LENGTHOF(wpath_abs), wpath_abs, 0); if (written == 0) return S8_MakeEmpty(); - S8_String path = UTF_CreateStringFromWidechar(arena, wpath_abs, written); + S8_String path = S8_FromWidecharEx(arena, wpath_abs, written); S8_NormalizePathUnsafe(path); return path; } @@ -152,7 +152,7 @@ OS_API void OS_Advance(OS_FileIter *it) { if (data->cFileName[0] == '.' && data->cFileName[1] == 0) continue; it->is_directory = data->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY; - it->filename = UTF_CreateStringFromWidechar(it->arena, data->cFileName, S8_WideLength(data->cFileName)); + it->filename = S8_FromWidecharEx(it->arena, data->cFileName, S8_WideLength(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); @@ -674,14 +674,6 @@ OS_API int OS_SystemF(const char *string, ...) { return error_code; } -OS_API S8_String UTF_CreateStringFromWidechar(MA_Arena *arena, wchar_t *wstr, int64_t wsize) { - int64_t buffer_size = (wsize + 1) * 2; - char *buffer = (char *)MA_PushSizeNonZeroed(arena, buffer_size); - int64_t size = UTF_CreateCharFromWidechar(buffer, buffer_size, wstr, wsize); - IO_Assert(size < buffer_size); - return S8_Make(buffer, size); -} - 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; @@ -724,4 +716,4 @@ OS_API S8_String OS_ExpandIncludes(MA_Arena *arena, S8_String filepath) { result = S8_Merge(arena, out); } return result; -} \ No newline at end of file +} diff --git a/standalone_libraries/clexer.c b/standalone_libraries/clexer.c index 6797a6d..d8fac92 100644 --- a/standalone_libraries/clexer.c +++ b/standalone_libraries/clexer.c @@ -1,6 +1,21 @@ #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 diff --git a/standalone_libraries/io.c b/standalone_libraries/io.c index 9a97f03..f600287 100644 --- a/standalone_libraries/io.c +++ b/standalone_libraries/io.c @@ -31,7 +31,7 @@ IO_StaticFunc int IO_Strlen(char *string) { return len; } -void (*IO_User_OutputMessage)(int kind, char *file, int line, char *str, int len); +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; @@ -83,7 +83,7 @@ IO_API bool IO__FatalErrorf(const char *file, int line, const char *msg, ...) { return ret == IO_ErrorResult_Break; } -IO_API void IO__Printf(int kind, char *file, int line, const char *msg, ...) { +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. @@ -127,7 +127,7 @@ IO_API bool IO__FatalError(char *msg) { return result == IO_ErrorResult_Break; } -IO_API void IO_Print(int kind, char *file, int line, char *msg, int len) { +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); } diff --git a/standalone_libraries/io.h b/standalone_libraries/io.h index d38def7..f794f0f 100644 --- a/standalone_libraries/io.h +++ b/standalone_libraries/io.h @@ -31,7 +31,7 @@ typedef enum IO_ErrorResult { #define IO__PrintfFormat(fmt, va) #endif -extern void (*IO_User_OutputMessage)(int kind, char *file, int line, char *str, int len); +extern 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) @@ -74,9 +74,9 @@ extern void (*IO_User_OutputMessage)(int kind, char *file, int line, char *str, #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, char *file, int line, const char *msg, ...) IO__PrintfFormat(4, 5); +IO_API void IO__Printf(int kind, const char *file, int line, const char *msg, ...) IO__PrintfFormat(4, 5); IO_API bool IO__FatalError(char *msg); -IO_API void IO_Print(int kind, char *file, int line, char *msg, int len); +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); diff --git a/standalone_libraries/preproc_env.h b/standalone_libraries/preproc_env.h index 0630e10..8a0b434 100644 --- a/standalone_libraries/preproc_env.h +++ b/standalone_libraries/preproc_env.h @@ -103,13 +103,13 @@ #endif #if OS_WINDOWS - #define OS_NAME "Windows" + #define OS_NAME "windows" #elif OS_LINUX - #define OS_NAME "Linux" + #define OS_NAME "linux" #elif OS_MAC - #define OS_NAME "MacOS" + #define OS_NAME "mac_os" #else - #error couldn't figure out OS + #error couldnt figure out OS #endif // #if COMPILER_CLANG diff --git a/standalone_libraries/string.c b/standalone_libraries/string.c index 9e2249c..283690f 100644 --- a/standalone_libraries/string.c +++ b/standalone_libraries/string.c @@ -529,3 +529,38 @@ S8_API S8_String S8_AddF(S8_Allocator allocator, S8_List *list, const char *str, S8_AddNode(allocator, list, result); return result; } + +#ifdef UTF_HEADER + +S8_API S16_String S8_ToWidecharEx(S8_Allocator allocator, S8_String string) { + S8_ASSERT(sizeof(wchar_t) == 2); + wchar_t *buffer = (wchar_t *)S8_ALLOCATE(allocator, sizeof(wchar_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 wchar_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, wchar_t *wstring, int64_t wsize) { + S8_ASSERT(sizeof(wchar_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, wchar_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/standalone_libraries/string.h b/standalone_libraries/string.h index b44b3a7..c9e4dc3 100644 --- a/standalone_libraries/string.h +++ b/standalone_libraries/string.h @@ -80,6 +80,11 @@ struct S8_List { #endif }; +typedef struct S16_String { + wchar_t *str; + int64_t len; +} S16_String; + typedef int S8_FindFlag; enum { S8_FindFlag_None = 0, @@ -177,6 +182,11 @@ S8_API S8_Node *S8_AddNode(S8_Allocator allocator, S8_List *list, S8_String stri 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 wchar_t *S8_ToWidechar(S8_Allocator allocator, S8_String string); +S8_API S8_String S8_FromWidecharEx(S8_Allocator allocator, wchar_t *wstring, int64_t wsize); +S8_API S8_String S8_FromWidechar(S8_Allocator allocator, wchar_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); } diff --git a/standalone_libraries/unicode.c b/standalone_libraries/unicode.c index 8cc03ab..eb999ca 100644 --- a/standalone_libraries/unicode.c +++ b/standalone_libraries/unicode.c @@ -159,6 +159,9 @@ UTF_API int64_t UTF_CreateCharFromWidechar(char *buffer, int64_t buffer_size, wc return outlen; } +// @todo: the api here is from one side cool but from other kind of weird +// int64_t size = UTF_CreateWidecharFromChar(wcmd, cmd.len + 1, cmd.str, cmd.len); +// the "+ 1" part is bothering me, but if it wrote one past buffer_size, that would be worse UTF_API int64_t UTF_CreateWidecharFromChar(wchar_t *buffer, int64_t buffer_size, char *in, int64_t inlen) { int64_t outlen = 0; for (int64_t i = 0; i < inlen;) { diff --git a/tests/test_thread.cpp b/tests/test_thread.cpp new file mode 100644 index 0000000..faf2d8f --- /dev/null +++ b/tests/test_thread.cpp @@ -0,0 +1,128 @@ +#include "../build_tool/library.cpp" +#include "../build_tool/process.cpp" + +int main() { + MA_Scratch scratch; + S8_String working_dir = OS_GetWorkingDir(scratch); + + Array exes = {scratch}; + Array proc = {scratch}; + Array files = {scratch}; + files.add("../../tests/test_main.cpp"); + files.add("../../tests/test_filesystem.c"); + + For2(file, files) { + S8_String name_no_ext = S8_GetNameNoExt(file); + S8_String exe = Fmt("%.*s.exe", S8_Expand(name_no_ext)); + bool is_cpp = S8_EndsWith(file, ".cpp"); + +#if OS_WINDOWS + // Setup CL Debug + { + S8_String cc = "cl"; + + Array flags = {scratch}; + flags += "/MP /Zi -D_CRT_SECURE_NO_WARNINGS"; + flags += "/FC /WX /W3 /wd4200 /diagnostics:column /nologo"; + flags += "/GF /Gm- /Oi"; + flags += "/GR- /EHa-"; + flags += Fmt("/Fe:%.*s", S8_Expand(exe)); + + Array debug = {scratch}; + debug += "/D_DEBUG -RTC1 -Od"; + + Array release = {scratch}; + release += "-O2 -MT -DNDEBUG -GL"; + + Array link = {scratch}; + link += "/link /incremental:no"; + + S8_String dir_debug = Fmt("%.*s/%.*s_cl_debug_" OS_NAME, S8_Expand(working_dir), S8_Expand(name_no_ext)); + S8_String dir_release = Fmt("%.*s/%.*s_cl_release_" OS_NAME, S8_Expand(working_dir), S8_Expand(name_no_ext)); + + OS_MakeDir(dir_debug); + OS_MakeDir(dir_release); + + Array cmd_debug = cc + file + flags + debug + link; + Array cmd_release = cc + file + flags + release + link; + + S8_String cmd_debug_m = Merge(cmd_debug); + S8_String cmd_release_m = Merge(cmd_release); + + TH_Process p1 = TH_CreateProcess(cmd_debug_m, dir_debug); + TH_Process p2 = TH_CreateProcess(cmd_release_m, dir_release); + + proc.add(p1); + proc.add(p2); + + exes.add(Fmt("%.*s/%.*s", S8_Expand(dir_debug), S8_Expand(exe))); + exes.add(Fmt("%.*s/%.*s", S8_Expand(dir_release), S8_Expand(exe))); + } +#endif + + { + S8_String cc = is_cpp ? "clang++" : "clang"; + + Array flags = {scratch}; + flags += "-g -Wno-write-strings"; + flags += "-fdiagnostics-absolute-paths"; + flags += "-fsanitize=address"; + if (is_cpp) flags += "-std=c++11"; + flags += Fmt("-o %.*s", S8_Expand(exe)); + + S8_String dir = Fmt("%.*s/%.*s_debug_clang_" OS_NAME, S8_Expand(working_dir), S8_Expand(name_no_ext)); + OS_MakeDir(dir); + + S8_String cmd = Merge(cc + file + flags); + TH_Process p = TH_CreateProcess(cmd, dir); + proc.add(p); + exes.add(Fmt("%.*s/%.*s", S8_Expand(dir), S8_Expand(exe))); + } + +#if OS_LINUX + { + S8_String cc = is_cpp ? "g++" : "gcc"; + Array flags = {scratch}; + flags += "-g -Wno-write-strings"; + flags += "-fsanitize=address"; + if (is_cpp) flags += "-std=c++11"; + flags += Fmt("-o %.*s", S8_Expand(exe)); + + S8_String dir = Fmt("%.*s/%.*s_debug_gcc_" OS_NAME, S8_Expand(working_dir), S8_Expand(name_no_ext)); + OS_MakeDir(dir); + + S8_String cmd = Merge(cc + file + flags); + TH_Process p = TH_CreateProcess(cmd, dir); + proc.add(p); + exes.add(Fmt("%.*s/%.*s", S8_Expand(dir), S8_Expand(exe))); + } +#endif + } + + // + // Wait for all compilation to finalize + // + int result = 0; + For(proc) { + int exit_code = TH_WaitForProcessExit(&it); + if (exit_code != 0) result = exit_code; + } + + // + // Run exes if there were no errors + // + if (result == 0) { + proc.reset(); + For(exes) { + TH_Process p = TH_CreateProcess(it); + proc.add(p); + } + + For(proc) { + int exit_code = TH_WaitForProcessExit(&it); + if (exit_code != 0) result = exit_code; + } + } + + return result; +} \ No newline at end of file