From 2f0d93978d731e77230d84e6ade30c88ad14539e Mon Sep 17 00:00:00 2001 From: LeonardoBizzoni Date: Thu, 2 Apr 2026 17:19:10 +0200 Subject: [PATCH] CBuild refactor --- cbuild.h | 1871 ++++++++++++++++++++++++++-------------- extra/cbuild_codegen.h | 14 +- extra/cbuild_linagen.h | 146 ++-- extra/cbuild_tests.h | 4 +- 4 files changed, 1294 insertions(+), 741 deletions(-) diff --git a/cbuild.h b/cbuild.h index 90f5db9..3de54bc 100644 --- a/cbuild.h +++ b/cbuild.h @@ -7,6 +7,17 @@ # define COMPILER_CLANG 1 #elif defined(_MSC_VER) # define COMPILER_CL 1 +# if defined(_M_IX86) +# define ARCH_X86_32 1 +# elif defined(_M_AMD64) +# define ARCH_X86_64 1 +# elif defined(_M_ARM) +# define ARCH_ARM32 1 +# elif defined(_M_ARM64) +# define ARCH_ARM64 1 +# else +# error Unsupported platform +# endif #else # error Unsupported compiler #endif @@ -23,6 +34,18 @@ # error Unknown operating system #endif +#if defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) || defined(_M_AMD64) +# define ARCH_X86_64 1 +#elif defined(i386) || defined(__i386) || defined(__i386__) +# define ARCH_X86_32 1 +#elif defined(__aarch64__) +# define ARCH_ARM64 1 +#elif defined(__arm__) +# define ARCH_ARM32 1 +#else +# error Unknown architecture +#endif + #if !defined(COMPILER_GCC) # define COMPILER_GCC 0 #endif @@ -49,13 +72,21 @@ # define OS_NONE 0 #endif +#ifdef alignof +# undef alignof +#endif +#if COMPILER_GCC +# define alignof(TYPE) __alignof__(TYPE) +#elif COMPILER_CLANG || COMPILER_CL +# define alignof(TYPE) __alignof(TYPE) +#else +# error undefined alignof macro +#endif + #define internal static -#define BOOL_DEFINED 1 -#if __STDC_VERSION__ >= 199901L -# include -#else - typedef enum {false, true} bool; +#if !OS_WINDOWS && !defined(_GNU_SOURCE) +# define _GNU_SOURCE #endif #include @@ -65,17 +96,6 @@ #include #include #include - -#if OS_WINDOWS -# if COMPILER_CL -# define CC "cl" -# else -# define CC "x86_64-w64-mingw32-gcc" -# endif -#else -# define CC "cc" -#endif - #if OS_WINDOWS # define WIN32_LEAN_AND_MEAN # include @@ -87,24 +107,44 @@ # undef stdin # undef stdout # undef stderr -# define _cb_platform_mkdir(Path) _mkdir((Path)); -# define MAX_ENVVAR 32767 -# define CB_PROC_INVALID INVALID_HANDLE_VALUE -# define CB_HANDLE_INVALID INVALID_HANDLE_VALUE +#endif - typedef HANDLE CB_Handle; - typedef HANDLE CB_ProcHandle; +typedef float f32; +typedef double f64; +typedef uint8_t b8; +typedef uint32_t b32; +typedef int8_t s8; +typedef int16_t s16; +typedef int32_t s32; +typedef int64_t s64; +typedef uint8_t u8; +typedef uint16_t u16; +typedef uint32_t u32; +typedef uint64_t u64; +typedef uintptr_t usize; +typedef intptr_t ssize; + +typedef u64 time64; +typedef u64 unix_time; + +#define false 0 +#define true 1 + +#define UNIX_MINUTE 60 +#define UNIX_HOUR 3600 +#define UNIX_DAY 86400 +#define UNIX_WEEK 604800 +#define UNIX_YEAR 31536000 +#define UNIX_LEAP_YEAR 31622400 + +#if COMPILER_CL +# define CC "cl" +#elif COMPILER_GCC +# define CC "gcc" +#elif COMPILER_CLANG +# define CC "clang" #else -# include -# include -# include -# include -# include -# define _cb_platform_mkdir(Path) mkdir((Path), S_IRWXU | (S_IRGRP | S_IXGRP) | (S_IROTH | S_IXOTH)); -# define CB_PROC_INVALID -1 -# define CB_HANDLE_INVALID -1 - typedef int32_t CB_Handle; - typedef pid_t CB_ProcHandle; +# define CC "cc" #endif #define ANSI_COLOR_RED "\x1b[31m" @@ -115,6 +155,330 @@ #define ANSI_COLOR_CYAN "\x1b[36m" #define ANSI_COLOR_RESET "\x1b[0m" +#define cb_memcopy(Destination, Source, Size) memcpy((Destination), (Source), (u64)(Size)) +#define cb_memzero(Destination, Size) memset((Destination), 0, (u64)(Size)) + +#define cb_arrlength(Arr) (sizeof((Arr)) / sizeof(*(Arr))) + +// ================================================================================ +// Static arena +#define CB_ARENA_SIZE 4 * 1024 * 1024 + +static struct { + u8 data[CB_ARENA_SIZE]; + s64 head; +} cb_arena = {0}; + +typedef struct CB_Scratch CB_Scratch; +struct CB_Scratch { + s64 restore_point; +}; + +#define cb_arena_push(type) cb_arena_push_many(type, 1) +#define cb_arena_push_many(type, count) ((type*)_cb_arena_push(sizeof(type) * (u64)(count), alignof(type))) +#define cb_arena_push_explicit(bytes, alignment) (_cb_arena_push((bytes), (alignment))) + +#define cb_scratch_begin() ((CB_Scratch) { .restore_point = cb_arena.head }) +#define cb_scratch_end(scratch) cb_arena_pop(cb_arena.head - (scratch).restore_point) + +static void cb_arena_pop(s64 bytes); +internal void* _cb_arena_push(u64 bytes, u64 alignment); + +static inline u64 cb_align_forward(u64 x, u64 align); + +// ================================================================================ +// Compact time format +static time64 cb_time64_from_unix(unix_time timestamp); +#if OS_WINDOWS +static time64 time64_from_systemtime(const SYSTEMTIME *in); +#endif + +// ================================================================================ +// Strings & Arrays +typedef struct CB_StringView CB_StringView; +struct CB_StringView { + u8 *data; + int64_t length; +}; + +typedef struct CB_StringBuilder_Node CB_StringBuilder_Node; +struct CB_StringBuilder_Node { + struct CB_StringBuilder_Node *prev; + struct CB_StringBuilder_Node *next; + CB_StringView value; +}; + +typedef struct CB_StringBuilder CB_StringBuilder; +struct CB_StringBuilder { + struct CB_StringBuilder_Node *first; + struct CB_StringBuilder_Node *last; + int32_t total_length; + int32_t node_count; +}; + +typedef struct CB_Array CB_Array; +struct CB_Array { + s64 length; + void *data; +}; + +typedef uint8_t CB_LogLevel; +enum { + CB_LogLevel_None, + CB_LogLevel_Info, + CB_LogLevel_Warn, + CB_LogLevel_Error, + CB_LogLevel_COUNT, +}; + +#define cb_strlit(cstr) (CB_StringView) { .data = (cstr), .length = cb_arrlength(cstr) - 1 } +#define cb_strinit(cstr) { .data = (cstr), .length = cb_arrlength(cstr) - 1 } +#define cb_view_expand(view) (s32)(view).length, (view).data + +#define cb_array(CArrayLitteral) (CB_Array) { .data = (CArrayLitteral), .length = cb_arrlength((CArrayLitteral)) } + +#ifndef CB_DYN_DEFAULT_CAPACITY +# define CB_DYN_DEFAULT_CAPACITY 8 +#endif + +#define cb_dyn_reserve(Dynarr, HowMany) cb_dyn_reserve_custom((Dynarr), (HowMany), values, count, capacity) +#define cb_dyn_free(Dynarr) cb_dyn_free_custom((Dynarr), values, count) +#define cb_dyn_push(Dynarr, Node) cb_dyn_push_custom((Dynarr), (Node), values, count, capacity) +#define cb_dyn_append(Dynarr, Array, Size) cb_dyn_append_custom((Dynarr), (Array), (Size), values, count, capacity) + +#define cb_stack_push(Head, Nodeptr) cb_ull_push_front_custom((Head), (Head), (Nodeptr), next) +#define cb_stack_pop(Head) (Head ? (Head = Head->next) : 0) + +#define cb_ull_push_front_custom(Head, Last, Nodeptr, Next) \ + (!(Head) ? (Head) = (Nodeptr), (Last) = (Nodeptr) \ + : ((Nodeptr)->Next = (Head), (Head) = (Nodeptr))) + +#define cb_queue_push(Head, Last, Nodeptr) cb_ull_push_back_custom((Head), (Last), (Nodeptr), next) +#define cb_queue_pop(Head) (Head ? (Head = Head->next) : 0) + +#define cb_ull_push_back_custom(Head, Last, Nodeptr, Next) \ + (!(Head) ? (Head) = (Last) = (Nodeptr) \ + : ((Last) ? ((Last)->Next = (Nodeptr), (Last) = (Nodeptr)) \ + : ((Head)->Next = (Last) = (Nodeptr)))) + +#define cb_bll_push_front(Head, Last, Nodeptr) cb_bll_push_front_custom(Head, Last, Nodeptr, next, prev) +#define cb_bll_push_back(Head, Last, Nodeptr) cb_bll_push_back_custom(Head, Last, Nodeptr, next, prev) + +#define cb_bll_push_front_custom(Head, Last, Nodeptr, Next, Prev) \ + (!(Head) ? (Head) = (Last) = (Nodeptr) \ + : ((Nodeptr)->Next = (Head), (Head)->Prev = (Nodeptr), \ + (Head) = (Nodeptr))) + +#define cb_bll_push_back_custom(DLLNodeHead, DLLNodeLast, NodeToInsertptr, Next, Prev) \ + (!DLLNodeHead \ + ? DLLNodeHead = DLLNodeLast = NodeToInsertptr \ + : (DLLNodeLast->Next = NodeToInsertptr, \ + NodeToInsertptr->Prev = DLLNodeLast, DLLNodeLast = NodeToInsertptr)) + +#define cb_bll_remove(Head, Last, Nodeptr) \ + ((Head) == (Last) && (Head) == (Nodeptr) \ + ? (Head) = (Last) = 0 \ + : ((Last) == (Nodeptr) \ + ? ((Last) = (Last)->prev, (Last)->next = 0) \ + : ((Head) == (Nodeptr) \ + ? ((Head) = (Head)->next, (Head)->prev = 0) \ + : ((Nodeptr)->prev->next = (Nodeptr)->next, \ + (Nodeptr)->next->prev = (Nodeptr)->prev)))) + +#define cb_bll_pop(Head, Last) cb_bll_pop_back(Head, Last) + +#define cb_bll_pop_back(Head, Last) \ + (!(Last) \ + ? 0 \ + : (!(Last)->prev ? (Head) = (Last) = 0 \ + : ((Last)->prev->next = 0, (Last) = (Last)->prev))) + +#define cb_bll_pop_front(Head, Last) \ + (!(Head) \ + ? 0 \ + : (!(Head)->next ? (Head) = (Last) = 0 \ + : ((Head)->next->prev = 0, (Head) = (Head)->next))) + +#define cb_dyn_free_custom(Dynarr, Values, Count) \ + do { \ + free((Dynarr)->Values); \ + (Dynarr)->Count = 0; \ + } while (0) + +#define cb_dyn_reserve_custom(Dynarr, HowMany, Values, Count, Capacity) \ + do { \ + if (!(Dynarr)->Capacity) { \ + (Dynarr)->Capacity = CB_DYN_DEFAULT_CAPACITY; \ + } \ + while ((HowMany) > (Dynarr)->Capacity) { \ + (Dynarr)->Capacity *= 2; \ + } \ + (Dynarr)->Values = realloc((Dynarr)->Values, \ + (Dynarr)->Capacity * sizeof((Dynarr)->Values[0])); \ + cb_assert((Dynarr)->Values); \ + } while(0) + +#define cb_dyn_push_custom(Dynarr, Node, Values, Count, Capacity) \ + do { \ + cb_dyn_reserve_custom((Dynarr), (Dynarr)->Count + 1, \ + Values, Count, Capacity); \ + (Dynarr)->Values[(Dynarr)->Count++] = (Node); \ + } while(0) + +#define cb_dyn_append_custom(Dynarr, Array, Size, Values, Count, Capacity) \ + do { \ + cb_dyn_reserve((Dynarr), (Dynarr)->Count + (Size)); \ + memcpy((Dynarr)->Values + (Dynarr)->Count, (Array), \ + (Size) * sizeof((Dynarr)->Values[0])); \ + (Dynarr)->Count += (Size); \ + } while(0) + +static void cb_print(CB_LogLevel level, const char *fmt, ...); + +static char* cb_format(const char *format, ...); +static char* cb_cstr_from_view(CB_StringView view); + +static CB_StringView cb_view_from_cstr(const char *cstr); +static b8 cb_view_starts_with(const char *string, CB_StringView sv); +static void cb_view_trim(CB_StringView *sv); +static CB_StringBuilder cb_view_split(CB_StringView sv, char delim); + +static void cb_sb_append(CB_StringBuilder *sb, CB_StringView sv); +static void cb_sb_concat(CB_StringBuilder *sb, const CB_StringBuilder *other); +static CB_StringView cb_sb_join_with_ch(CB_StringBuilder sb, char ch); + +static b8 cb_cli_contains(int32_t argc, char **argv, const char *target); + +internal char* cb_format_va(const char *format, va_list args); + +// ================================================================================ +// File-system interaction +#if !OS_WINDOWS +# include +# include +# include +# include +# include +#endif + +typedef u8 CB_FileType; +enum { + CB_FileType_Unknown = 0, + CB_FileType_Device_Disk, + CB_FileType_Device_Terminal, + CB_FileType_Directory, + CB_FileType_Pipe, + CB_FileType_Link, + CB_FileType_Socket, + CB_FileType_Regular, + CB_FileType_COUNT, +}; + +typedef u8 CB_FilePermission; +enum { + CB_FilePermission_Unknown = 0, + CB_FilePermission_Read = 1 << 0, + CB_FilePermission_Write = 1 << 1, + CB_FilePermission_Execute = 1 << 2, +}; + +typedef u8 CB_AccessFlag; +enum { + CB_AccessFlag_Read = 1 << 0, + CB_AccessFlag_Write = 1 << 1, + CB_AccessFlag_Append = 1 << 2, +}; + +typedef struct CB_FileProperties CB_FileProperties; +struct CB_FileProperties { + s64 size; + time64 time_last_access; + time64 time_last_modification; + time64 time_last_status_change; + CB_FileType type; + union { + CB_FilePermission values[3]; + struct { + CB_FilePermission user; + CB_FilePermission group; + CB_FilePermission other; + }; + } permission; +}; + +typedef struct CB_FileInfo CB_FileInfo; +struct CB_FileInfo { + s64 size; + char *path; + CB_FileType type; +}; + +typedef struct CB_FileIterator_Handle CB_FileIterator_Handle; +#if OS_WINDOWS +struct CB_FileIterator_Handle { + const char *path; +}; +#else +struct CB_FileIterator_Handle { + DIR *dir; + const char *path; + struct dirent *dir_entry; +}; +#endif + +typedef struct CB_FileIterator CB_FileIterator; +struct CB_FileIterator { + CB_FileType filter_allowed; + CB_FileIterator_Handle handle; +}; + +#if OS_WINDOWS +# define CB_FILEHANDLE_INVALID INVALID_HANDLE_VALUE + typedef HANDLE CB_FileHandle; +#else +# define CB_FILEHANDLE_INVALID -1 + typedef int32_t CB_FileHandle; +#endif + +static CB_FileProperties cb_file_properties(CB_FileHandle hfile); +static CB_StringView cb_file_read(CB_FileHandle hfile, s64 size, s64 offset); +static u8* cb_file_memory_map(CB_FileHandle hfile, s64 size, s64 offset); +static void cb_file_write_at_pointer(CB_FileHandle hfile, CB_StringView content); +static void cb_file_write_at_offset(CB_FileHandle hfile, CB_StringView content, s64 offset); +static b8 cb_file_pointer_set_position_absolute(CB_FileHandle hfile, s64 position); +static b8 cb_file_pointer_set_position_relative(CB_FileHandle hfile, s64 offset); +static b8 cb_file_flush(CB_FileHandle hfile); +static b8 cb_file_set_size(CB_FileHandle hfile, s64 new_size); +static void cb_file_memory_unmap(u8 *file_map, s64 size); +static void cb_file_close(CB_FileHandle hfile); + +static CB_FileHandle cb_filesystem_open(CB_StringView path, CB_AccessFlag flags); +static CB_FileHandle cb_filesystem_open_temp(CB_StringView *path); +static CB_FileProperties cb_filesystem_properties(CB_StringView path); +static void cb_filesystem_delete(CB_StringView path); +static b8 cb_filesystem_exists(CB_StringView path); +static b8 cb_filesystem_rename(CB_StringView old, CB_StringView new); +static b8 cb_filesystem_copy(CB_StringView path_source, CB_StringView path_dest, s64 bytes_to_copy, s64 offset_source, s64 offset_dest); +static b8 cb_filesystem_link_create_symbolic(CB_StringView realpath, CB_StringView linkpath); +static b8 cb_filesystem_link_create_physical(CB_StringView realpath, CB_StringView linkpath); +static CB_StringView cb_filesystem_link_read(CB_StringView linkpath); +static b8 cb_filesystem_directory_create(CB_StringView path); +static b8 cb_filesystem_directory_copy(CB_StringView path, CB_StringView new); +static b8 cb_filesystem_directory_delete(CB_StringView path, b8 recursive); +static CB_StringView cb_filesystem_filename_from_path(CB_StringView path); +static CB_StringView cb_filesystem_path_canonicalize(CB_StringView path); + +static void cb_filesystem_iter_begin(CB_FileIterator *it, const char *rootpath); +static b8 cb_filesystem_iter_next(CB_FileIterator *it, CB_FileInfo *output); +static void cb_filesystem_iter_end(CB_FileIterator *it); + +#if !OS_WINDOWS +internal CB_FileProperties cb_fileproperties_from_stat(struct stat *file_stat); +#endif + +// ================================================================================ +// Custom assertion handler +// TODO(lb): rename to `expect` and move to "test" extra #ifndef _assert_break # if OS_WINDOWS # define _assert_break() __debugbreak() @@ -140,264 +504,183 @@ internal cb_assertion_handler_fn cb_assertion_handler = cb_assertion_break; } \ } while (0) -struct CB_PathList { - const char **values; - size_t count; - size_t capacity; -}; -typedef struct CB_PathList CB_Cmd; - -struct CB_Cmd_RunArgs { - CB_Handle stdin; - CB_Handle stdout; - CB_Handle stderr; - bool async; - bool reset; -}; +// ================================================================================ +// Processes +#if OS_WINDOWS +# define CB_PROC_INVALID INVALID_HANDLE_VALUE + typedef HANDLE CB_ProcHandle; +#else +# include +# include +# define CB_PROC_INVALID -1 + typedef pid_t CB_ProcHandle; +#endif -typedef struct { +typedef struct CB_Process CB_Process; +struct CB_Process { CB_ProcHandle handle; int32_t status_code; -} CB_Process; +}; -typedef struct { +typedef struct CB_ProcessList CB_ProcessList; +struct CB_ProcessList { CB_Process *values; size_t count; size_t capacity; -} CB_ProcessList; - -typedef uint8_t CB_AccessFlag; -enum { - CB_AccessFlag_Read = 1 << 0, - CB_AccessFlag_Write = 1 << 1, - CB_AccessFlag_Append = 1 << 2, }; -typedef uint8_t CB_LogLevel; -enum { - CB_LogLevel_None, - CB_LogLevel_Info, - CB_LogLevel_Warn, - CB_LogLevel_Error, - CB_LogLevel_COUNT, -}; - -typedef uint8_t CB_FileType; -enum { - CB_FileType_Device_Block = 1 << 0, - CB_FileType_Device_Char = 1 << 1, - CB_FileType_Directory = 1 << 2, - CB_FileType_Pipe = 1 << 3, - CB_FileType_Link = 1 << 4, - CB_FileType_Socket = 1 << 5, - CB_FileType_Regular = 1 << 6, -}; - -#if OS_WINDOWS -#else -# include - struct CB_FileIterator_Handle { - const char *path; - DIR *dir; - struct dirent *dir_entry; - }; -#endif - -typedef struct { - CB_FileType filter_allowed; - struct CB_FileIterator_Handle handle; -} CB_FileIterator; - -typedef struct { - size_t size; - char *path; - CB_FileType type; -} CB_FileInfo; +#define cb_proclist_push(Dynarr, Value) cb_dyn_push(Dynarr, Value) -typedef struct CB_StringView { - const char *data; - ssize_t length; -} CB_StringView; +static void cb_process_wait(CB_Process *handle); +static void cb_proclist_wait(CB_ProcessList *procs); -struct CB_StringBuilder_Node { - struct CB_StringBuilder_Node *prev; - struct CB_StringBuilder_Node *next; - CB_StringView value; +// ================================================================================ +// Commands +typedef struct CB_Cmd CB_Cmd; +struct CB_Cmd { + const char **values; + u64 count; + u64 capacity; }; -typedef struct CB_StringBuilder { - struct CB_StringBuilder_Node *first; - struct CB_StringBuilder_Node *last; - int32_t total_length; - int32_t node_count; -} CB_StringBuilder; - -#ifndef CB_DYN_DEFAULT_CAPACITY -# define CB_DYN_DEFAULT_CAPACITY 8 -#endif - -#if COMPILER_CL -# define CB_CMD_REBUILD_SELF(Exe_name, Builder_src) CC, "/Fe:", (Exe_name), (Builder_src), "/nologo" -#else -# define CB_CMD_REBUILD_SELF(Exe_name, Builder_src) CC, "-o", (Exe_name), (Builder_src) -#endif -#define CB_CMD_REBUILD_SELF_WITH_OPTION(Exe_name, Builder_src, ...) CB_CMD_REBUILD_SELF(Exe_name, Builder_src), __VA_ARGS__ +typedef struct CB_Cmd_RunArgs CB_Cmd_RunArgs; +struct CB_Cmd_RunArgs { + CB_FileHandle stream_in; + CB_FileHandle stream_out; + CB_FileHandle stream_err; + b8 async; + b8 reset; +}; -#define cb_strlit(cstr) (CB_StringView) { .data = (cstr), .length = cb_arrlength(cstr) - 1 } -#define cb_strinit(cstr) { .data = (cstr), .length = cb_arrlength(cstr) - 1 } -#define cb_arrlength(Arr) (sizeof((Arr)) / sizeof(*(Arr))) -#define cb_dyn_reserve(Dynarr, HowMany) cb_dyn_reserve_custom((Dynarr), (HowMany), values, count, capacity) -#define cb_dyn_free(Dynarr) cb_dyn_free_custom((Dynarr), values, count) -#define cb_dyn_push(Dynarr, Node) cb_dyn_push_custom((Dynarr), (Node), values, count, capacity) -#define cb_dyn_append(Dynarr, Array, Size) cb_dyn_append_custom((Dynarr), (Array), (Size), values, count, capacity) #define cb_cmd_push(Dynarr, Value) cb_dyn_push(Dynarr, Value) #define cb_cmd_append_dyn(Dynarr, Values, Count) cb_dyn_append((Dynarr), (Values), (Count)); #define cb_cmd_append(Dynarr, ...) cb_dyn_append((Dynarr), ((const char*[]){__VA_ARGS__}), (sizeof((const char*[]){__VA_ARGS__}) / sizeof(char*))) -#define cb_rebuild_self(argc, argv) _cb_rebuild(argc, argv, __FILE__, NULL) -#define cb_rebuild_self_with(argc, argv, ...) _cb_rebuild(argc, argv, __FILE__, __VA_ARGS__, NULL) -#define cb_is_outdated(OutputFile, ...) _cb_is_outdated((OutputFile), __VA_ARGS__, 0) -#define cb_proclist_push(Dynarr, Value) cb_dyn_push(Dynarr, Value) -#define cb_cmd_exec(Cmd) \ - _cb_cmd_run((Cmd), \ - (struct CB_Cmd_RunArgs) { \ - .async = false, \ - .reset = true, \ + +#define cb_cmd_exec(Cmd) \ + _cb_cmd_run((Cmd), \ + (CB_Cmd_RunArgs) { \ + .async = false, \ + .reset = true, \ }) + #define cb_cmd_exec_with_option(Cmd, ...) \ _cb_cmd_run((Cmd), \ - (struct CB_Cmd_RunArgs) { \ + (CB_Cmd_RunArgs) { \ .async = false, \ .reset = true, \ __VA_ARGS__ \ }) -#define cb_dyn_free_custom(Dynarr, Values, Count) \ - do { \ - free((Dynarr)->Values); \ - (Dynarr)->Count = 0; \ - } while (0) -#define cb_dyn_reserve_custom(Dynarr, HowMany, Values, Count, Capacity) \ - do { \ - if (!(Dynarr)->Capacity) { \ - (Dynarr)->Capacity = CB_DYN_DEFAULT_CAPACITY; \ - } \ - while ((HowMany) > (Dynarr)->Capacity) { \ - (Dynarr)->Capacity *= 2; \ - } \ - (Dynarr)->Values = realloc((Dynarr)->Values, \ - (Dynarr)->Capacity * sizeof((Dynarr)->Values[0])); \ - cb_assert((Dynarr)->Values); \ - } while(0) -#define cb_dyn_push_custom(Dynarr, Node, Values, Count, Capacity) \ - do { \ - cb_dyn_reserve_custom((Dynarr), (Dynarr)->Count + 1, \ - Values, Count, Capacity); \ - (Dynarr)->Values[(Dynarr)->Count++] = (Node); \ - } while(0) -#define cb_dyn_append_custom(Dynarr, Array, Size, Values, Count, Capacity) \ - do { \ - cb_dyn_reserve((Dynarr), (Dynarr)->Count + (Size)); \ - memcpy((Dynarr)->Values + (Dynarr)->Count, (Array), \ - (Size) * sizeof((Dynarr)->Values[0])); \ - (Dynarr)->Count += (Size); \ - } while(0) +static void cb_cmd_print(const CB_Cmd *cmd); +static void cb_cmd_clear(CB_Cmd *cmd); +internal CB_Process _cb_cmd_run(CB_Cmd *cmd, struct CB_Cmd_RunArgs args); -#define stack_push(Head, Nodeptr) ull_push_front_custom((Head), (Head), (Nodeptr), next) -#define stack_pop(Head) (Head ? (Head = Head->next) : 0) -#define ull_push_front_custom(Head, Last, Nodeptr, Next) \ - (!(Head) ? (Head) = (Nodeptr), (Last) = (Nodeptr) \ - : ((Nodeptr)->Next = (Head), (Head) = (Nodeptr))) +static void cb_rebuild_and_restart(s32 argc, char **argv, CB_Array sources, CB_Array build_options); -#define queue_push(Head, Last, Nodeptr) ull_push_back_custom((Head), (Last), (Nodeptr), next) -#define queue_pop(Head) (Head ? (Head = Head->next) : 0) -#define ull_push_back_custom(Head, Last, Nodeptr, Next) \ - (!(Head) ? (Head) = (Last) = (Nodeptr) \ - : ((Last) ? ((Last)->Next = (Nodeptr), (Last) = (Nodeptr)) \ - : ((Head)->Next = (Last) = (Nodeptr)))) - -#define bll_push_front(Head, Last, Nodeptr) bll_push_front_custom(Head, Last, Nodeptr, next, prev) -#define bll_push_back(Head, Last, Nodeptr) bll_push_back_custom(Head, Last, Nodeptr, next, prev) -#define bll_push_front_custom(Head, Last, Nodeptr, Next, Prev) \ - (!(Head) ? (Head) = (Last) = (Nodeptr) \ - : ((Nodeptr)->Next = (Head), (Head)->Prev = (Nodeptr), \ - (Head) = (Nodeptr))) -#define bll_push_back_custom(DLLNodeHead, DLLNodeLast, NodeToInsertptr, Next, Prev) \ - (!DLLNodeHead \ - ? DLLNodeHead = DLLNodeLast = NodeToInsertptr \ - : (DLLNodeLast->Next = NodeToInsertptr, \ - NodeToInsertptr->Prev = DLLNodeLast, DLLNodeLast = NodeToInsertptr)) -#define bll_remove(Head, Last, Nodeptr) \ - ((Head) == (Last) && (Head) == (Nodeptr) \ - ? (Head) = (Last) = 0 \ - : ((Last) == (Nodeptr) \ - ? ((Last) = (Last)->prev, (Last)->next = 0) \ - : ((Head) == (Nodeptr) \ - ? ((Head) = (Head)->next, (Head)->prev = 0) \ - : ((Nodeptr)->prev->next = (Nodeptr)->next, \ - (Nodeptr)->next->prev = (Nodeptr)->prev)))) -#define bll_pop(Head, Last) bll_pop_back(Head, Last) -#define bll_pop_back(Head, Last) \ - (!(Last) \ - ? 0 \ - : (!(Last)->prev ? (Head) = (Last) = 0 \ - : ((Last)->prev->next = 0, (Last) = (Last)->prev))) -#define bll_pop_front(Head, Last) \ - (!(Head) \ - ? 0 \ - : (!(Head)->next ? (Head) = (Last) = 0 \ - : ((Head)->next->prev = 0, (Head) = (Head)->next))) - -#define cb_file_write(Handle, Content) _Generic((Content), \ - char *: cb_file_write_cstr, \ - const char *: cb_file_write_cstr, \ - CB_StringView: cb_file_write_sv \ - )((Handle), (Content)) +// ============================================================================== +// Environment variables +#if OS_WINDOWS +# define MAX_ENVVAR 32767 +#endif -static char* cb_format(const char *format, ...); -static void cb_print(CB_LogLevel level, const char *fmt, ...); static char* cb_getenv(const char *varname); -static bool cb_setenv(const char *varname, const char *value); -static void cb_cmd_print(const CB_Cmd *cmd); -static void cb_process_wait(CB_Process *handle); -static void cb_proclist_wait(CB_ProcessList *procs); -static bool cb_dir_create(const char *path); -static void cb_dir_delete(const char *path); -static CB_Handle cb_file_open(const char *path, CB_AccessFlag permission); -static void cb_file_close(CB_Handle fd); -static CB_StringView cb_file_read(CB_Handle fd); -static void cb_file_write_cstr(CB_Handle fd, const char *cstr); -static void cb_file_write_sv(CB_Handle fd, CB_StringView sv); -static void cb_file_delete(const char *path); -static bool cb_file_rename(const char *path, const char *to); -static bool cb_file_exists(const char *path); -static bool cb_symlink_create(const char *target, const char *linkpath); -static bool cb_cli_contains(int32_t argc, char **argv, const char *target); -static bool cb_view_starts_with(const char *string, CB_StringView sv); -static void cb_view_trim(CB_StringView *sv); -static CB_StringBuilder cb_view_split(CB_StringView sv, char delim); -static void cb_sb_append(CB_StringBuilder *sb, CB_StringView sv); -static void cb_sb_concat(CB_StringBuilder *sb, const CB_StringBuilder *other); - -internal void _cb_file_write_buffer(CB_Handle fd, const char *buffer, size_t size); -internal char* cb_format_va(const char *format, va_list args); -internal bool _cb_need_rebuild(const char *output_path, struct CB_PathList sources); -internal void _cb_rebuild(int argc, char **argv, const char *cb_src, ...); -internal bool _cb_is_outdated(const char *output, ...); -internal CB_Process _cb_cmd_run(CB_Cmd *cmd, struct CB_Cmd_RunArgs args); -internal size_t _last_occurance_of(const char *string, char ch); - +static b8 cb_setenv(const char *varname, const char *value); // ============================================================================== // Implementation -static char* cb_format(const char *format, ...) { - va_list args = {0}; - va_start(args, format); - char *res = cb_format_va(format, args); - va_end(args); + +// ================================================================================ +// Static arena impl +static inline u64 cb_align_forward(u64 x, u64 align) +{ + assert(align > 0); + assert((align & (align - 1)) == 0); + u64 mod = x & (align - 1); + return (mod ? x = x + align - mod : x); +} + +static void cb_arena_pop(s64 bytes) +{ + assert(bytes >= 0); + if ((u64)bytes == (u64)-1) { + cb_arena.head = 0; + } else { + cb_arena.head -= bytes; + } +} + +internal void* _cb_arena_push(u64 bytes, u64 alignment) +{ + u64 res = cb_align_forward((u64)cb_arena.data + (u32)cb_arena.head, alignment); + assert(res >= (u64)cb_arena.data); + s32 offset = (s32)(res - ((u64)cb_arena.data + (u32)cb_arena.head)); + assert(offset >= 0 && (u64)offset <= alignment); + cb_arena.head += bytes + (u32)offset; + assert(cb_arena.head < CB_ARENA_SIZE); + return (void*)res; +} + +// ================================================================================ +// Compact time format +static time64 cb_time64_from_unix(unix_time timestamp) +{ + static const u8 daysXmonth[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; + time64 res = 1ULL << 63; + s32 year = 1970; + b8 is_leap_year = (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0); + for (u64 secondsXyear = is_leap_year ? UNIX_LEAP_YEAR : UNIX_YEAR; + timestamp >= secondsXyear; + ++year, timestamp -= secondsXyear, + secondsXyear = is_leap_year ? UNIX_LEAP_YEAR : UNIX_YEAR); + + res |= (u64)((s64)year & ~(1 << 27)) << 36; + u64 month = 1; + for (;;) { + u8 days = daysXmonth[month - 1]; + if (month == 2 && is_leap_year) { ++days; } + u64 secondsXmonth = days * UNIX_DAY; + if (timestamp < secondsXmonth) { break; } + timestamp -= secondsXmonth; + ++month; + } + res |= month << 32; + res |= (timestamp / UNIX_DAY + 1) << 27; + timestamp %= UNIX_DAY; + res |= (timestamp / UNIX_HOUR) << 22; + timestamp %= UNIX_HOUR; + res |= (timestamp / UNIX_MINUTE) << 16; + timestamp %= UNIX_MINUTE; + res |= timestamp << 10; return res; } -static void cb_print(CB_LogLevel level, const char *fmt, ...) { +#if OS_WINDOWS +static time64 time64_from_systemtime(const SYSTEMTIME *in) +{ + assert(in); + assert(in->wMilliseconds <= 999); + assert(in->wSecond <= 60); + assert(in->wMinute <= 60); + assert(in->wHour <= 23); + assert(in->wDay <= 31); + assert(in->wMonth >= 1 && in->wMonth <= 12); + s16 year = (s16)in->wYear; + time64 res = (year >= 0 ? 1ULL << 63 : 0); + res |= (u64)((year >= 0 ? year : -year) & ~(1 << 27)) << 36; + res |= (u64)(in->wMonth) << 32; + res |= (u64)(in->wDay) << 27; + res |= (u64)(in->wHour) << 22; + res |= (u64)(in->wMinute) << 16; + res |= (u64)(in->wSecond) << 10; + res |= (u64)in->wMilliseconds; + return res; +} +#endif + +// ================================================================================ +// Strings & Arrays +static void cb_print(CB_LogLevel level, const char *fmt, ...) +{ cb_assert(fmt != NULL); cb_assert(level >= CB_LogLevel_None && level <= CB_LogLevel_COUNT); switch (level) { @@ -421,234 +704,589 @@ static void cb_print(CB_LogLevel level, const char *fmt, ...) { va_end(args); } -static char* cb_getenv(const char *varname) { - cb_assert(varname != NULL); +static char* cb_format(const char *format, ...) +{ + va_list args = {0}; + va_start(args, format); + char *res = cb_format_va(format, args); + va_end(args); + return res; +} + +static char* cb_cstr_from_view(CB_StringView view) +{ + assert(view.length > 0); + assert(view.data != NULL); + char *res = cb_arena_push_many(char, view.length + 1); + cb_memcopy(res, view.data, view.length); + res[view.length] = '\0'; + return res; +} + +static CB_StringView cb_view_from_cstr(const char *cstr) +{ + CB_StringView res = {0}; + res.data = (u8*)cstr; + if (cstr != NULL) { + const char *start = cstr; + for (; *cstr; ++cstr); + res.length = cstr - start; + } + return res; +} + +static b8 cb_view_starts_with(const char *string, CB_StringView sv) +{ + if (string == NULL || sv.length == 0 || sv.data == NULL) { return false; } + for (int32_t i = 0; i < sv.length; ++i) { + if (string[i] == 0 || string[i] != sv.data[i]) { return false; } + } + return true; +} + +static void cb_view_trim(CB_StringView *sv) +{ + cb_assert(sv != NULL); + if (sv->length <= 0) { return; } + cb_assert(sv->data != NULL); + cb_assert(sv->length > 0); + + for (; sv->data[0] == ' ' || sv->data[0] == '\n' || sv->data[0] == '\r' || sv->data[0] == '\t'; + sv->length -= 1, sv->data += 1) {} + for (; sv->data[sv->length - 1] == ' ' || sv->data[sv->length - 1] == '\n' || + sv->data[sv->length - 1] == '\r' || sv->data[sv->length - 1] == '\t'; + sv->length -= 1) {} +} + +static CB_StringBuilder cb_view_split(CB_StringView sv, char delim) +{ + CB_StringBuilder res = {0}; + if (sv.data == NULL || sv.length == 0) { return res; } + ssize_t prev = 0; + for (ssize_t i = 0; i < sv.length;) { + if (sv.data[i] == delim) { + if (prev != i) { + cb_sb_append(&res, (CB_StringView) { + .data = sv.data + prev, + .length = (int64_t)(i - prev), + }); + } + do { + prev = ++i; + } while (sv.data[i] == delim); + } else { + ++i; + } + } + if (prev != sv.length) { + cb_sb_append(&res, (CB_StringView) { + .data = sv.data + prev, + .length = (int64_t)(sv.length - prev), + }); + } + cb_assert(res.node_count > 0); + return res; +} + +static void cb_sb_append(CB_StringBuilder *sb, CB_StringView sv) +{ + cb_assert(sb != NULL); + if (sv.length == 0 || sv.data == NULL) { return; } + CB_StringBuilder_Node *node = cb_arena_push(CB_StringBuilder_Node); + cb_assert(node != NULL); + memset(node, 0, sizeof *node); + node->value = sv; + cb_bll_push_back(sb->first, sb->last, node); + sb->total_length += sv.length; + sb->node_count += 1; +} + +static void cb_sb_concat(CB_StringBuilder *sb, const CB_StringBuilder *other) +{ + cb_assert(sb != NULL); + cb_assert(sb->node_count >= 0); + cb_assert(sb->total_length >= 0); + cb_assert(other != NULL); + cb_assert(other->node_count >= 0); + cb_assert(other->total_length >= 0); + sb->node_count += other->node_count; + sb->total_length += other->total_length; + cb_bll_push_back(sb->first, sb->last, other->first); + sb->last = other->last; +} + +static CB_StringView cb_sb_join_with_ch(CB_StringBuilder sb, char ch) +{ + CB_StringView sv = {0}; + sv.data = malloc((uint32_t)(sb.total_length + sb.node_count)); + sv.length = sb.total_length + sb.node_count - 1; + int32_t offset = 0; + for (struct CB_StringBuilder_Node *curr = sb.first; curr;) { + memcpy((char*)(sv.data + offset), curr->value.data, (uint32_t)curr->value.length); + offset += curr->value.length; + ((char*)sv.data)[offset++] = ch; + struct CB_StringBuilder_Node *next = curr->next; + free(curr); + curr = next; + } + ((char*)sv.data)[sv.length] = 0; + return sv; +} + +static b8 cb_cli_contains(int32_t argc, char **argv, const char *target) +{ + for (int32_t i = 0; i < argc; ++i) { + if (!strcmp(argv[i], target)) { + return true; + } + } + return false; +} + +internal char* cb_format_va(const char *format, va_list args) +{ + va_list args2; + va_copy(args2, args); + size_t needed_bytes = (size_t)vsnprintf(0, 0, format, args2) + 1; + va_end(args2); + + char *res = cb_arena_push_many(char, needed_bytes); + (void)vsnprintf(res, needed_bytes, format, args); + return res; +} + +// ================================================================================ +// File-system interaction +static CB_FileProperties cb_file_properties(CB_FileHandle hfile) +{ + assert(hfile != CB_FILEHANDLE_INVALID); #if OS_WINDOWS - char *res = malloc(MAX_ENVVAR); - if (!GetEnvironmentVariableA(varname, res, MAX_ENVVAR)) { - free(res); - res = 0; + CB_FileProperties properties = {0}; + + BY_HANDLE_FILE_INFORMATION file_info = {0}; + BOOL get_info_res = GetFileInformationByHandle(hfile, &file_info); + assert(get_info_res == TRUE); + + properties.size = (((s64)file_info.nFileSizeHigh << 32) | file_info.nFileSizeLow); + assert(properties.size >= 0); + + if (file_info.dwFileAttributes & FILE_ATTRIBUTE_NORMAL || file_info.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE) { + properties.type = OS_FileType_Regular; + } else if (file_info.dwFileAttributes & FILE_ATTRIBUTE_DEVICE) { + properties.type = OS_FileType_Device_Block; + } else if (file_info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { + properties.type = OS_FileType_Link; + } else if (file_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + properties.type = OS_FileType_Directory; + } else { + unreachable(); } + + assert((((u64)file_info.ftLastAccessTime.dwHighDateTime << 32) | file_info.ftLastAccessTime.dwLowDateTime) <= 0x8000000000000000); + assert((((u64)file_info.ftLastWriteTime.dwHighDateTime << 32) | file_info.ftLastWriteTime.dwLowDateTime) <= 0x8000000000000000); + SYSTEMTIME last_access_time = {0}, last_write_time = {0}; + res = FileTimeToSystemTime(&file_info.ftLastAccessTime, &last_access_time); + assert(res == TRUE); + res = FileTimeToSystemTime(&file_info.ftLastWriteTime, &last_write_time); + assert(res == TRUE); + + properties.time_last_access = time64_from_systemtime(&last_access_time); + properties.time_last_status_change = time64_from_systemtime(&last_write_time); + properties.time_last_modification = properties.time_last_status_change; + + return properties; +#else + struct stat file_stat = {0}; + s32 stat_res = fstat(hfile, &file_stat); + assert(stat_res == 0); + return cb_fileproperties_from_stat(&file_stat); +#endif +} + +static CB_StringView cb_file_read(CB_FileHandle hfile, s64 size, s64 offset) +{ + assert(hfile != CB_FILEHANDLE_INVALID); + assert(size > 0); + assert(offset >= 0); + assert(offset < size); + + CB_StringView result = {0}; + u8 *buffer = cb_arena_push_many(u8, size); + +#if OS_WINDOWS + // TODO(lb): win32 +#else + s64 bytes_read = pread(hfile, buffer, (u64)size, offset); + assert(bytes_read != -1); + cb_arena_pop(size - bytes_read); + result.data = (u8*)buffer; + result.length = bytes_read; + return result; +#endif +} + +static u8* cb_file_memory_map(CB_FileHandle hfile, s64 size, s64 offset) +{ + assert(hfile != CB_FILEHANDLE_INVALID); + assert(size > 0); + assert(offset >= 0); + assert(offset < size); + +#if OS_WINDOWS + // TODO(lb): win32 +#else + u8 *res = mmap(NULL, (u64)size, O_RDWR, MAP_SHARED, hfile, offset); + assert(res != MAP_FAILED); return res; +#endif +} + +static void cb_file_write_at_pointer(CB_FileHandle hfile, CB_StringView content) +{ + assert(hfile != CB_FILEHANDLE_INVALID); + assert(content.length > 0); + assert(content.data != NULL); + +#if OS_WINDOWS + // TODO(lb): win32 #else - return getenv(varname); + CB_Scratch scratch = cb_scratch_begin(); + s64 bytes_wrote = write(hfile, cb_cstr_from_view(content), (u64)content.length); + cb_scratch_end(scratch); + assert(bytes_wrote == content.length); +#endif +} + +static void cb_file_write_at_offset(CB_FileHandle hfile, CB_StringView content, s64 offset) +{ + assert(hfile != CB_FILEHANDLE_INVALID); + assert(content.length > 0); + assert(content.data != NULL); + assert(offset >= 0); + +#if OS_WINDOWS + // TODO(lb): win32 +#else + CB_Scratch scratch = cb_scratch_begin(); + s64 bytes_wrote = pwrite(hfile, cb_cstr_from_view(content), (u64)content.length, offset); + cb_scratch_end(scratch); + assert(bytes_wrote <= content.length); +#endif +} + +static b8 cb_file_pointer_set_position_absolute(CB_FileHandle hfile, s64 position) +{ + assert(hfile != CB_FILEHANDLE_INVALID); + assert(position > 0); +#if OS_WINDOWS + // TODO(lb): win32 +#else + off_t res = lseek(hfile, position, SEEK_SET); + return res == 0; +#endif +} + +static b8 cb_file_pointer_set_position_relative(CB_FileHandle hfile, s64 offset) +{ + assert(hfile != CB_FILEHANDLE_INVALID); +#if OS_WINDOWS + // TODO(lb): win32 +#else + off_t res = lseek(hfile, offset, SEEK_CUR); + return res == 0; #endif } -static bool cb_setenv(const char *varname, const char *value) { - cb_assert(varname != NULL); - cb_assert(value != NULL); +static b8 cb_file_flush(CB_FileHandle hfile) +{ + assert(hfile != CB_FILEHANDLE_INVALID); #if OS_WINDOWS - return SetEnvironmentVariableA(varname, value); + // TODO(lb): win32 #else - return !setenv(varname, value, true); + s32 res = fsync(hfile); + return res == 0; #endif } -static void cb_cmd_print(const CB_Cmd *cmd) { - cb_assert(cmd != NULL); - cb_print(CB_LogLevel_Info, "Command: `"); - for (size_t i = 0; i < cmd->count; ++i) { - printf("%s ", cmd->values[i]); - } - printf("\b`\n"); +static b8 cb_file_set_size(CB_FileHandle hfile, s64 new_size) +{ + assert(hfile != CB_FILEHANDLE_INVALID); + assert(new_size >= 0); +#if OS_WINDOWS + // TODO(lb): win32 +#else + s32 res = ftruncate(hfile, new_size); + return res == 0; +#endif } -static void cb_process_wait(CB_Process *proc) { - cb_assert(proc != NULL); - if (proc->handle == CB_PROC_INVALID) { - cb_print(CB_LogLevel_Error, "Waiting on invalid process handle\n"); - cb_assert(false); - } - +static void cb_file_memory_unmap(u8 *file_map, s64 size) +{ + assert(file_map != NULL); + assert(size > 0); #if OS_WINDOWS - WaitForSingleObject(proc->handle, INFINITE); - GetExitCodeProcess(proc->handle, (LPDWORD)&proc->status_code); - CloseHandle(proc->handle); + // TODO(lb): win32 #else - int32_t status = 0; - int32_t wait_res = waitpid(proc->handle, &status, 0); - cb_assert(wait_res == proc->handle); - if (WIFEXITED(status)) { - proc->status_code = WEXITSTATUS(status); - } else if (WIFSIGNALED(status)) { - proc->status_code = WTERMSIG(status); - } else { - proc->status_code = 0; - } + s32 res = munmap(file_map, (u64)size); + assert(res == 0); #endif } -static void cb_proclist_wait(CB_ProcessList *procs) { - cb_assert(procs != NULL); - if (procs->count == 0) { return; } - for (size_t i = 0; i < procs->count; ++i) { - cb_process_wait(&procs->values[i]); - } - cb_dyn_free(procs); +static void cb_file_close(CB_FileHandle hfile) +{ + assert(hfile != CB_FILEHANDLE_INVALID); +#if OS_WINDOWS + // TODO(lb): win32 +#else + s32 res = close(hfile); + assert(res == 0); +#endif } -static CB_Handle cb_file_open(const char *path, CB_AccessFlag permission) { - cb_assert(path != NULL); +static CB_FileHandle cb_filesystem_open(CB_StringView path, CB_AccessFlag flags) +{ + assert(path.length > 0); + assert(path.data != NULL); #if OS_WINDOWS - SECURITY_ATTRIBUTES security_attributes = {sizeof(SECURITY_ATTRIBUTES), 0, 0}; - DWORD access_flags = 0; - DWORD share_mode = 0; - DWORD creation_disposition = OPEN_EXISTING; - - if(permission & CB_AccessFlag_Read) { access_flags |= GENERIC_READ; } - if(permission & CB_AccessFlag_Write) { - access_flags |= GENERIC_WRITE; - creation_disposition = CREATE_ALWAYS; - } - if(permission & CB_AccessFlag_Append) { - access_flags |= FILE_APPEND_DATA; - creation_disposition = OPEN_ALWAYS; - } - return CreateFileA(path, access_flags, - share_mode, &security_attributes, - creation_disposition, - FILE_ATTRIBUTE_NORMAL, 0); + // TODO(lb): win32 #else - int32_t flags = O_CREAT; - if ((permission & CB_AccessFlag_Read) && ((permission & CB_AccessFlag_Write) || - (permission & CB_AccessFlag_Append))) { - flags |= O_RDWR; + s32 mode = O_CREAT; + if ((flags & CB_AccessFlag_Read) && ((flags & CB_AccessFlag_Write) || (flags & CB_AccessFlag_Append))) { + mode |= O_RDWR; } else { - if (permission & CB_AccessFlag_Read) { - flags |= O_RDONLY; - } else if ((permission & CB_AccessFlag_Write) || - (permission & CB_AccessFlag_Append)) { - flags |= O_WRONLY; + if (flags & CB_AccessFlag_Read) { + mode |= O_RDONLY; + } else if ((flags & CB_AccessFlag_Write) || (flags & CB_AccessFlag_Append)) { + mode |= O_WRONLY; } } - if (permission & CB_AccessFlag_Append) { flags |= O_APPEND; } - int32_t res = open(path, flags, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); - if (res == -1) { return CB_HANDLE_INVALID; } - return (CB_Handle)res; + if (flags & CB_AccessFlag_Append) { mode |= O_APPEND; } + CB_Scratch scratch = cb_scratch_begin(); + int32_t res = open(cb_cstr_from_view(path), mode, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + cb_scratch_end(scratch); + if (res == -1) { return CB_FILEHANDLE_INVALID; } + return (CB_FileHandle)res; #endif } -static void cb_file_close(CB_Handle fd) { - if (fd == CB_HANDLE_INVALID) { - cb_print(CB_LogLevel_Error, "Closing invalid handle\n"); - cb_assert(false); - } - +static CB_FileHandle cb_filesystem_open_temp(CB_StringView *path) +{ + assert(path != NULL); #if OS_WINDOWS - FlushFileBuffers(fd); - CloseHandle(fd); + // TODO(lb): win32 #else - close(fd); + path->length = cb_arrlength("/tmp/XXXXXX"); + char *bytes = cb_arena_push_many(char, path->length); + cb_memcopy(bytes, "/tmp/XXXXXX", path->length); + path->data = (u8*)(bytes); + CB_FileHandle res = mkstemp(bytes); + assert(res != -1); + return res; #endif } -static CB_StringView cb_file_read(CB_Handle fd) { - if (fd == CB_HANDLE_INVALID) { - cb_print(CB_LogLevel_Warn, "Reading from invalid handle\n"); - return (CB_StringView) {0}; - } +static CB_FileProperties cb_filesystem_properties(CB_StringView path) +{ + assert(path.length > 0); + assert(path.data != NULL); #if OS_WINDOWS - LARGE_INTEGER file_size = {0}; - GetFileSizeEx(fd, &file_size); - - LONGLONG size = file_size.QuadPart; - LONGLONG total_read = 0; - char *buffer = malloc((size_t)(size + 1)); - ReadFile(fd, buffer, (DWORD)size, NULL, NULL); - buffer[size] = 0; - return (CB_StringView) { - .data = buffer, - .length = size, - }; + // TODO(lb): get file properties from path on win32 + CB_FileProperties res = {0}; + return res; #else struct stat file_stat = {0}; - if (fstat(fd, &file_stat) == -1 || file_stat.st_size <= 0) { return (CB_StringView) {0}; } - char *res = malloc(file_stat.st_size + 1); - if (pread(fd, res, file_stat.st_size, 0) == -1) { return (CB_StringView) {0}; } - res[file_stat.st_size] = 0; - return (CB_StringView) { - .data = res, - .length = file_stat.st_size, - }; + CB_Scratch scratch = cb_scratch_begin(); + s32 stat_res = stat(cb_cstr_from_view(path), &file_stat); + cb_scratch_end(scratch); + assert(stat_res == 0); + return cb_fileproperties_from_stat(&file_stat); #endif } -static void cb_file_write_sv(CB_Handle fd, CB_StringView sv) { - _cb_file_write_buffer(fd, sv.data, sv.length); +static void cb_filesystem_delete(CB_StringView path) +{ + assert(path.length > 0); + assert(path.data != NULL); +#if OS_WINDOWS + // TODO(lb): implement file delete on win32 +#else + CB_Scratch scratch = cb_scratch_begin(); + unlink(cb_cstr_from_view(path)); + cb_scratch_end(scratch); +#endif } -static void cb_file_write_cstr(CB_Handle fd, const char *buffer) { - if (fd == CB_HANDLE_INVALID) { - cb_print(CB_LogLevel_Error, "Writing to invalid handle\n"); - assert(false); - } - size_t buffsize = strlen(buffer); - _cb_file_write_buffer(fd, buffer, buffsize); +static b8 cb_filesystem_exists(CB_StringView path) +{ +#if OS_WINDOWS + // TODO(lb): win32 +# define F_OK 0 +# define access _access +#endif + CB_Scratch scratch = cb_scratch_begin(); + b8 res = (access(cb_cstr_from_view(path), F_OK) == 0); + cb_scratch_end(scratch); + return res; } -static bool cb_dir_create(const char *path) { - cb_assert(path != NULL); - int32_t mkdir_res = _cb_platform_mkdir(path); - if (mkdir_res < 0 && errno == ENOENT) { - size_t parent_end = _last_occurance_of(path, '/'); - if (!parent_end) { return false; } - char *parent = (char *)malloc(parent_end + 1); - memcpy(parent, path, parent_end); - parent[parent_end] = 0; - cb_dir_create(parent); - free(parent); - _cb_platform_mkdir(path); - } - return !mkdir_res; +static b8 cb_filesystem_rename(CB_StringView old, CB_StringView new) +{ +#if OS_WINDOWS + // TODO(lb): implement file rename on win32 +#else + CB_Scratch scratch = cb_scratch_begin(); + char *old_cstr = cb_cstr_from_view(old); + char *new_cstr = cb_cstr_from_view(new); + b8 res = (rename(old_cstr, new_cstr) == 0); + cb_scratch_end(scratch); + return res; +#endif } -static void cb_dir_delete(const char *path) { +static b8 cb_filesystem_copy(CB_StringView path_source, CB_StringView path_dest, s64 bytes_to_copy, s64 offset_source, s64 offset_dest) +{ + assert(bytes_to_copy > 0); + assert(offset_source >= 0); + assert(offset_dest >= 0); + assert(cb_filesystem_exists(path_source)); + if (!cb_filesystem_exists(path_dest)) { assert(offset_dest == 0); } #if OS_WINDOWS - _rmdir(path); + // TODO(lb): win32 #else - rmdir(path); + CB_Scratch scratch = cb_scratch_begin(); + s32 src = open(cb_cstr_from_view(path_source), O_RDONLY, 0); + s32 dest = open(cb_cstr_from_view(path_dest), O_WRONLY | O_CREAT, 0644); + cb_scratch_end(scratch); + assert(src != -1); + assert(dest != -1); + + s64 bytes_copied = copy_file_range(src, &offset_source, dest, &offset_dest, (u64)bytes_to_copy, 0); + assert(bytes_copied != -1); + + struct stat stat_src = {0}; + s32 res_fstat = fstat(src, &stat_src); + assert(res_fstat == 0); + fchmod(dest, stat_src.st_mode & 0777); + + fdatasync(dest); + close(src); + close(dest); + return bytes_copied == bytes_to_copy; #endif } -static void cb_file_delete(const char *path) { +static b8 cb_filesystem_link_create_symbolic(CB_StringView realpath, CB_StringView linkpath) +{ + assert(cb_filesystem_exists(realpath)); + assert(!cb_filesystem_exists(linkpath)); #if OS_WINDOWS - _unlink(path); + // TODO(lb): create symlink on win32 + return false; #else - unlink(path); + CB_Scratch scratch = cb_scratch_begin(); + s32 res = symlink(cb_cstr_from_view(realpath), cb_cstr_from_view(linkpath)); + cb_scratch_end(scratch); + return res == 0; #endif } -static bool cb_file_rename(const char *path, const char *to) { +static b8 cb_filesystem_link_create_physical(CB_StringView realpath, CB_StringView linkpath) +{ + assert(cb_filesystem_properties(realpath).type != CB_FileType_Directory); + assert(!cb_filesystem_exists(linkpath)); #if OS_WINDOWS - return MoveFileExA(path, to, MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH); + // TODO(lb): win32 #else - return !rename(path, to); + CB_Scratch scratch = cb_scratch_begin(); + s32 res = link(cb_cstr_from_view(realpath), cb_cstr_from_view(linkpath)); + cb_scratch_end(scratch); + return res == 0; #endif } -static bool cb_file_exists(const char *path) { +static CB_StringView cb_filesystem_link_read(CB_StringView linkpath) +{ + assert(cb_filesystem_exists(linkpath)); + assert(cb_filesystem_properties(linkpath).type == CB_FileType_Link); + CB_StringView res = {0}; #if OS_WINDOWS -# define F_OK 0 -# define access _access + // TODO(lb): win32 +#else + s64 approx_length = 1024; + char *buffer = cb_arena_push_many(char, approx_length); + CB_Scratch scratch = cb_scratch_begin(); + s64 length = readlink(cb_cstr_from_view(linkpath), buffer, (u64)approx_length); + assert(length > 0); + cb_scratch_end(scratch); + cb_arena_pop(approx_length - length); + res.length = length; + res.data = (u8*)buffer; #endif - return access(path, F_OK) == 0; + return res; } -static bool cb_symlink_create(const char *target, const char *linkpath) { - cb_assert(target != NULL); - cb_assert(linkpath != NULL); - +static b8 cb_filesystem_directory_create(CB_StringView path) +{ + assert(!cb_filesystem_exists(path)); #if OS_WINDOWS + // TODO(lb): win32 #else - int32_t res = symlink(target, linkpath); + CB_Scratch scratch = cb_scratch_begin(); + s32 res = mkdir(cb_cstr_from_view(path), (S_IRWXU) | (S_IRWXG) | (S_IROTH | S_IXOTH)); + cb_scratch_end(scratch); return res == 0; #endif } -static void cb_file_iter_begin(CB_FileIterator *it, const char *rootpath) { +static b8 cb_filesystem_directory_copy(CB_StringView dirpath, CB_StringView new) +{ + assert(cb_filesystem_exists(dirpath)); + assert(cb_filesystem_properties(dirpath).type == CB_FileType_Directory); + assert(!cb_filesystem_exists(new)); + // TODO(lb): directory copy + return false; +} + +static b8 cb_filesystem_directory_delete(CB_StringView path, b8 recursive) +{ + assert(cb_filesystem_exists(path)); + assert(cb_filesystem_properties(path).type == CB_FileType_Directory); + // TODO(lb): directory delete + return false; +} + +static CB_StringView cb_filesystem_filename_from_path(CB_StringView path) +{ + assert(cb_filesystem_exists(path)); +#if OS_WINDOWS + // TODO(lb): win32 +#else + const char *fullname = basename(cb_cstr_from_view(path)); + assert(fullname != NULL); + CB_StringView res = cb_view_from_cstr(fullname); + return res; +#endif +} + +static CB_StringView cb_filesystem_path_canonicalize(CB_StringView path) +{ + assert(cb_filesystem_exists(path)); +#if OS_WINDOWS + // TODO(lb): win32 +#else + CB_Scratch scratch = cb_scratch_begin(); + char *cstr_fullpath = realpath(cb_cstr_from_view(path), NULL); + assert(cstr_fullpath != NULL); + cb_scratch_end(scratch); + CB_StringView res = cb_view_from_cstr(cstr_fullpath); + return res; +#endif +} + +static void cb_filesystem_iter_begin(CB_FileIterator *it, const char *rootpath) +{ memset(&it->handle, 0, sizeof it->handle); #if OS_WINDOWS // TODO(lb): file iteration on win32 @@ -658,12 +1296,14 @@ static void cb_file_iter_begin(CB_FileIterator *it, const char *rootpath) { #endif } -static bool cb_file_iter_next(CB_FileIterator *it, CB_FileInfo *output) { +static b8 cb_filesystem_iter_next(CB_FileIterator *it, CB_FileInfo *output) +{ static const char *const currdir = "."; static const char *const parentdir = ".."; #if OS_WINDOWS // TODO(lb): file iteration on win32 + return false; #else struct dirent *entry = NULL; char *filepath = NULL; @@ -680,9 +1320,9 @@ static bool cb_file_iter_next(CB_FileIterator *it, CB_FileInfo *output) { if (!filename) { return false; } int32_t filepath_size = snprintf(NULL, 0, "%s/%s", it->handle.path, filename) + 1; - filepath = malloc(filepath_size); + filepath = malloc((uint32_t)filepath_size); if (!filepath) { return false; } - snprintf(filepath, filepath_size, "%s/%s", it->handle.path, filename); + snprintf(filepath, (uint32_t)filepath_size, "%s/%s", it->handle.path, filename); struct stat file_stat = {0}; if (stat(filepath, &file_stat) != 0) { @@ -692,13 +1332,13 @@ static bool cb_file_iter_next(CB_FileIterator *it, CB_FileInfo *output) { CB_FileType filetype = 0; switch (file_stat.st_mode & S_IFMT) { - case S_IFBLK: filetype = CB_FileType_Device_Block; break; - case S_IFCHR: filetype = CB_FileType_Device_Char; break; - case S_IFDIR: filetype = CB_FileType_Directory; break; - case S_IFIFO: filetype = CB_FileType_Pipe; break; - case S_IFLNK: filetype = CB_FileType_Link; break; - case S_IFSOCK: filetype = CB_FileType_Socket; break; - case S_IFREG: filetype = CB_FileType_Regular; break; + case S_IFBLK: filetype = CB_FileType_Device_Disk; break; + case S_IFCHR: filetype = CB_FileType_Device_Terminal; break; + case S_IFDIR: filetype = CB_FileType_Directory; break; + case S_IFIFO: filetype = CB_FileType_Pipe; break; + case S_IFLNK: filetype = CB_FileType_Link; break; + case S_IFSOCK: filetype = CB_FileType_Socket; break; + case S_IFREG: filetype = CB_FileType_Regular; break; } if (!(it->filter_allowed & filetype)) { @@ -709,7 +1349,7 @@ static bool cb_file_iter_next(CB_FileIterator *it, CB_FileInfo *output) { } else { output->path = filepath; output->type = filetype; - output->size = file_stat.st_size; + output->size = (uint32_t)file_stat.st_size; } return true; } @@ -718,7 +1358,8 @@ static bool cb_file_iter_next(CB_FileIterator *it, CB_FileInfo *output) { #endif } -static void cb_file_iter_end(CB_FileIterator *it) { +static void cb_filesystem_iter_end(CB_FileIterator *it) +{ #if OS_WINDOWS // TODO(lb): file iteration on win32 #else @@ -726,162 +1367,98 @@ static void cb_file_iter_end(CB_FileIterator *it) { #endif } -static bool cb_cli_contains(int32_t argc, char **argv, const char *target) { - for (int32_t i = 0; i < argc; ++i) { - if (!strcmp(argv[i], target)) { - return true; - } - } - return false; -} - -static bool cb_view_starts_with(const char *string, CB_StringView sv) { - if (string == NULL || sv.length == 0 || sv.data == NULL) { return false; } - for (int32_t i = 0; i < sv.length; ++i) { - if (string[i] == 0 || string[i] != sv.data[i]) { return false; } - } - return true; -} - -static void cb_view_trim(CB_StringView *sv) { - cb_assert(sv != NULL); - if (sv->length <= 0) { return; } - cb_assert(sv->data != NULL); - cb_assert(sv->length > 0); - - for (; sv->data[0] == ' ' || sv->data[0] == '\n' || sv->data[0] == '\r' || sv->data[0] == '\t'; - sv->length -= 1, sv->data += 1) {} - for (; sv->data[sv->length - 1] == ' ' || sv->data[sv->length - 1] == '\n' || - sv->data[sv->length - 1] == '\r' || sv->data[sv->length - 1] == '\t'; - sv->length -= 1) {} -} - -static CB_StringBuilder cb_view_split(CB_StringView sv, char delim) { - CB_StringBuilder res = {0}; - if (sv.data == NULL || sv.length == 0) { return res; } - size_t prev = 0; - for (size_t i = 0; i < sv.length;) { - if (sv.data[i] == delim) { - if (prev != i) { - cb_sb_append(&res, (CB_StringView) { - .data = sv.data + prev, - .length = i - prev, - }); - } - do { - prev = ++i; - } while (sv.data[i] == delim); - } else { - ++i; - } - } - if (prev != sv.length) { - cb_sb_append(&res, (CB_StringView) { - .data = sv.data + prev, - .length = sv.length - prev, - }); +#if !OS_WINDOWS +internal CB_FileProperties cb_fileproperties_from_stat(struct stat *file_stat) +{ + CB_FileProperties res = {0}; + res.size = file_stat->st_size; + res.time_last_access = cb_time64_from_unix((unix_time)file_stat->st_atime); + res.time_last_modification = cb_time64_from_unix((unix_time)file_stat->st_mtime); + res.time_last_status_change = cb_time64_from_unix((unix_time)file_stat->st_ctime); + switch (file_stat->st_mode & S_IFMT) { + case S_IFBLK: res.type = CB_FileType_Device_Disk; break; + case S_IFCHR: res.type = CB_FileType_Device_Terminal; break; + case S_IFDIR: res.type = CB_FileType_Directory; break; + case S_IFIFO: res.type = CB_FileType_Pipe; break; + case S_IFLNK: res.type = CB_FileType_Link; break; + case S_IFSOCK: res.type = CB_FileType_Socket; break; + case S_IFREG: res.type = CB_FileType_Regular; break; } - cb_assert(res.node_count > 0); - return res; -} - -static CB_StringView cb_view_from_cstr(const char *cstr) { - CB_StringView res = {0}; - res.data = cstr; - res.length = strlen(cstr); + res.permission.user = CB_FilePermission_Unknown; + if (file_stat->st_mode & S_IRUSR) { res.permission.user |= CB_FilePermission_Read; } + if (file_stat->st_mode & S_IWUSR) { res.permission.user |= CB_FilePermission_Write; } + if (file_stat->st_mode & S_IXUSR) { res.permission.user |= CB_FilePermission_Execute; } + res.permission.group = CB_FilePermission_Unknown; + if (file_stat->st_mode & S_IRGRP) { res.permission.group |= CB_FilePermission_Read; } + if (file_stat->st_mode & S_IWGRP) { res.permission.group |= CB_FilePermission_Write; } + if (file_stat->st_mode & S_IXGRP) { res.permission.group |= CB_FilePermission_Execute; } + res.permission.other = CB_FilePermission_Unknown; + if (file_stat->st_mode & S_IROTH) { res.permission.other |= CB_FilePermission_Read; } + if (file_stat->st_mode & S_IWOTH) { res.permission.other |= CB_FilePermission_Write; } + if (file_stat->st_mode & S_IXOTH) { res.permission.other |= CB_FilePermission_Execute; } return res; } +#endif -static void cb_sb_append(CB_StringBuilder *sb, CB_StringView sv) { - cb_assert(sb != NULL); - if (sv.length == 0 || sv.data == NULL) { return; } - struct CB_StringBuilder_Node *node = malloc(sizeof *node); - cb_assert(node != NULL); - memset(node, 0, sizeof *node); - node->value = sv; - bll_push_back(sb->first, sb->last, node); - sb->total_length += sv.length; - sb->node_count += 1; -} - -static void cb_sb_concat(CB_StringBuilder *sb, const CB_StringBuilder *other) { - cb_assert(sb != NULL); - cb_assert(sb->node_count >= 0); - cb_assert(sb->total_length >= 0); - cb_assert(other != NULL); - cb_assert(other->node_count >= 0); - cb_assert(other->total_length >= 0); - sb->node_count += other->node_count; - sb->total_length += other->total_length; - bll_push_back(sb->first, sb->last, other->first); - sb->last = other->last; -} - -static CB_StringView cb_sb_join_with_ch(CB_StringBuilder sb, char ch) { - CB_StringView sv = {0}; - sv.data = malloc(sb.total_length + sb.node_count); - sv.length = sb.total_length + sb.node_count - 1; - int32_t offset = 0; - for (struct CB_StringBuilder_Node *curr = sb.first; curr;) { - memcpy((char*)(sv.data + offset), curr->value.data, curr->value.length); - offset += curr->value.length; - ((char*)sv.data)[offset++] = ch; - struct CB_StringBuilder_Node *next = curr->next; - free(curr); - curr = next; +// ================================================================================ +// Processes +static void cb_process_wait(CB_Process *proc) +{ + cb_assert(proc != NULL); + if (proc->handle == CB_PROC_INVALID) { + cb_print(CB_LogLevel_Error, "Waiting on invalid process handle\n"); + cb_assert(false); } - ((char*)sv.data)[sv.length] = 0; - return sv; -} -internal void _cb_file_write_buffer(CB_Handle fd, const char *buffer, size_t size) { - cb_assert(fd != CB_HANDLE_INVALID); - cb_assert(buffer != NULL); - cb_assert(size > 0); - while (!buffer[size - 1]) { size -= 1; } #if OS_WINDOWS - uint64_t to_write = buffsize; - uint64_t total_write = 0; - char *ptr = buffer; - for(;total_write < to_write;) { - uint64_t amount64 = to_write - total_write;; - uint32_t amount32 = amount64 > 0xFFFFFFFF ? 0xFFFFFFFF : (uint32_t)amount64; - DWORD bytes_written = 0; - WriteFile(fd, ptr + total_write, amount32, &bytes_written, 0); - total_write += bytes_written; - if(bytes_written != amount32) { break; } - } + WaitForSingleObject(proc->handle, INFINITE); + GetExitCodeProcess(proc->handle, (LPDWORD)&proc->status_code); + CloseHandle(proc->handle); #else - write(fd, buffer, size); + int32_t status = 0; + int32_t wait_res = waitpid(proc->handle, &status, 0); + cb_assert(wait_res == proc->handle); + if (WIFEXITED(status)) { + proc->status_code = WEXITSTATUS(status); + } else if (WIFSIGNALED(status)) { + proc->status_code = WTERMSIG(status); + } else { + proc->status_code = 0; + } #endif } -internal bool _cb_is_outdated(const char *output, ...) { - struct CB_PathList sources = {0}; - va_list args; - va_start(args, output); - for (;;) { - char *path = va_arg(args, char*); - if (!path) { break; } - cb_dyn_push(&sources, path); +static void cb_proclist_wait(CB_ProcessList *procs) +{ + cb_assert(procs != NULL); + if (procs->count == 0) { return; } + for (size_t i = 0; i < procs->count; ++i) { + cb_process_wait(&procs->values[i]); } - va_end(args); - return _cb_need_rebuild(output, sources); + cb_dyn_free(procs); } +// ================================================================================ +// Commands +static void cb_cmd_print(const CB_Cmd *cmd) +{ + cb_assert(cmd != NULL); + cb_print(CB_LogLevel_Info, "Command: `"); + for (size_t i = 0; i < cmd->count; ++i) { + printf("%s ", cmd->values[i]); + } + printf("\b`\n"); +} -internal char* cb_format_va(const char *format, va_list args) { - va_list args2; - va_copy(args2, args); - size_t needed_bytes = (size_t)vsnprintf(0, 0, format, args2) + 1; - va_end(args2); - - char *res = malloc(needed_bytes); - (void)vsnprintf(res, needed_bytes, format, args); - return res; +static void cb_cmd_clear(CB_Cmd *cmd) +{ + free(cmd->values); + cmd->capacity = cmd->count = 0; + cmd->values = NULL; } -internal CB_Process _cb_cmd_run(CB_Cmd *cmd, struct CB_Cmd_RunArgs args) { +internal CB_Process _cb_cmd_run(CB_Cmd *cmd, struct CB_Cmd_RunArgs args) +{ CB_Process res = {0}; #if OS_WINDOWS @@ -897,9 +1474,9 @@ internal CB_Process _cb_cmd_run(CB_Cmd *cmd, struct CB_Cmd_RunArgs args) { STARTUPINFOA si = {0}; si.cb = sizeof(si); si.dwFlags = STARTF_USESTDHANDLES; - si.hStdInput = args.stdin ? args.stdin : GetStdHandle(STD_INPUT_HANDLE); - si.hStdOutput = args.stdout ? args.stdout : GetStdHandle(STD_OUTPUT_HANDLE); - si.hStdError = args.stderr ? args.stderr : GetStdHandle(STD_ERROR_HANDLE); + si.hStdInput = args.stream_in ? args.stream_in : GetStdHandle(STD_INPUT_HANDLE); + si.hStdOutput = args.stream_out ? args.stream_out : GetStdHandle(STD_OUTPUT_HANDLE); + si.hStdError = args.stream_err ? args.stream_err : GetStdHandle(STD_ERROR_HANDLE); PROCESS_INFORMATION pi = {0}; if (!CreateProcessA(0, cmdline, 0, 0, TRUE, 0, 0, 0, &si, &pi)) { @@ -924,11 +1501,11 @@ internal CB_Process _cb_cmd_run(CB_Cmd *cmd, struct CB_Cmd_RunArgs args) { cmd->values[0], errno, strerror(errno)); exit(-1); } else if (!res.handle) { - if (args.stdout) { dup2(args.stdout, STDOUT_FILENO); } - if (args.stderr) { dup2(args.stderr, STDERR_FILENO); } - if (args.stdin) { - lseek(args.stdin, 0, SEEK_SET); - dup2(args.stdin, STDIN_FILENO); + if (args.stream_out) { dup2(args.stream_out, STDOUT_FILENO); } + if (args.stream_err) { dup2(args.stream_err, STDERR_FILENO); } + if (args.stream_in) { + lseek(args.stream_in, 0, SEEK_SET); + dup2(args.stream_in, STDIN_FILENO); } CB_Cmd _cmd = {0}; @@ -953,118 +1530,98 @@ internal CB_Process _cb_cmd_run(CB_Cmd *cmd, struct CB_Cmd_RunArgs args) { return res; } -internal void _cb_rebuild(int argc, char **argv, const char *builder_src, ...) { - cb_assert(argc >= 1); - char *exe_name = argv[0]; - - struct CB_PathList sources = {0}; - cb_dyn_push(&sources, builder_src); - va_list args; - va_start(args, builder_src); - for (;;) { - char *path = va_arg(args, char*); - if (!path) { break; } - cb_dyn_push(&sources, path); - } - va_end(args); - - if (!_cb_need_rebuild(exe_name, sources)) { - cb_dyn_free(&sources); - return; +static void cb_rebuild_and_restart(s32 argc, char **argv, CB_Array sources, CB_Array build_options) +{ + assert(argc >= 1); + assert(argv != NULL); + assert(sources.length >= 1); + assert(sources.data != NULL); + assert(build_options.length >= 0); + if (build_options.length > 0) { assert(build_options.data != NULL); } + + b8 should_rebuild = false; + CB_StringView executable = cb_view_from_cstr(argv[0]); + cb_view_trim(&executable); + time64 last_edit_executable = cb_filesystem_properties(executable).time_last_modification; + CB_StringView *str_sources = sources.data; + for (s64 i = 0; i < sources.length; ++i) { + time64 last_edit_source = cb_filesystem_properties(str_sources[i]).time_last_modification; + if (last_edit_executable < last_edit_source) { + should_rebuild = true; + break; + } } - cb_print(CB_LogLevel_Info, "rebuilding %s\n", exe_name); + if (!should_rebuild) { return; } #if OS_WINDOWS - char *exe_name_old = cb_format("%s.old", exe_name); - if (!cb_file_rename(exe_name, exe_name_old)) { - cb_print(CB_LogLevel_Info, "File rename failed: %s -> %s\n", - exe_name, exe_name_old); - exit(-1); + { + CB_Scratch scratch = cb_scratch_begin(); + CB_StringView executable_old = cb_view_from_cstr(cb_format("%.*s.old", executable)); + if (!cb_file_rename(executable, executable_old)) { + cb_print(CB_LogLevel_Info, "File rename failed: %.*s -> %.*s\n", cb_view_expand(executable), cb_view_expand(executable_old)); + exit(-1); + } + cb_scratch_end(scratch); } #endif CB_Cmd cmd = {0}; - cb_cmd_append(&cmd, CB_CMD_REBUILD_SELF(exe_name, builder_src)); - cb_print(CB_LogLevel_Info, "running: `"); - for (size_t i = 0; i < cmd.count; ++i) { - printf("%s ", cmd.values[i]); + cb_cmd_push(&cmd, CC); +#if COMPILER_CL + cb_cmd_append(&cmd, "/std:c11", "/nologo"); + cb_cmd_push(&cmd, cb_format("/Fe:%.*s", cb_view_expand(executable))); + cb_cmd_push(&cmd, cb_format("%.*s", cb_view_expand(str_sources[0]))); +#else + cb_cmd_push(&cmd, "-o"); + cb_cmd_push(&cmd, cb_format("%.*s", cb_view_expand(executable))); + cb_cmd_push(&cmd, cb_format("%.*s", cb_view_expand(str_sources[0]))); +#endif + CB_StringView *str_build_options = build_options.data; + for (s64 i = 0; i < build_options.length; ++i) { + cb_cmd_push(&cmd, cb_format("%.*s", cb_view_expand(str_build_options[i]))); } - printf("\b`\n"); - CB_Process recompiler = cb_cmd_exec(&cmd); - if (recompiler.status_code) { + + cb_cmd_print(&cmd); + CB_Process compilation_proc = cb_cmd_exec(&cmd); + if (compilation_proc.status_code != 0) { #if OS_WINDOWS - cb_file_rename(exe_name_old, exe_name); + cb_file_rename(executable_old, executable); #endif exit(-1); } - cb_cmd_push(&cmd, exe_name); + cb_cmd_push(&cmd, cb_format("%.*s", cb_view_expand(executable))); cb_cmd_append_dyn(&cmd, argv, (size_t)argc); (void)cb_cmd_exec(&cmd); exit(0); } -internal bool _cb_need_rebuild(const char *output_path, struct CB_PathList sources) { +// ============================================================================== +// Environment variables +static char* cb_getenv(const char *varname) +{ + cb_assert(varname != NULL); #if OS_WINDOWS - FILETIME output_mtime_large = {0}; - HANDLE output_handle = CreateFileA(output_path, GENERIC_READ, - FILE_SHARE_READ, 0, OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, 0); - if (output_handle == INVALID_HANDLE_VALUE || - !GetFileTime(output_handle, 0, 0, &output_mtime_large)) { - CloseHandle(output_handle); - return true; - } - CloseHandle(output_handle); - - ULARGE_INTEGER output_mtime = {0}; - output_mtime.LowPart = output_mtime_large.dwLowDateTime; - output_mtime.HighPart = output_mtime_large.dwHighDateTime; - - for (size_t i = 0; i < sources.count; ++i) { - FILETIME source_mtime_large = {0}; - HANDLE source_handle = CreateFileA(sources.values[i], GENERIC_READ, - FILE_SHARE_READ, 0, OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, 0); - if (source_handle == INVALID_HANDLE_VALUE) { return true; } - if (!GetFileTime(source_handle, 0, 0, &source_mtime_large)) { - CloseHandle(output_handle); - return true; - } - CloseHandle(output_handle); - - ULARGE_INTEGER source_mtime = {0}; - source_mtime.LowPart = source_mtime_large.dwLowDateTime; - source_mtime.HighPart = source_mtime_large.dwHighDateTime; - if (output_mtime.QuadPart < source_mtime.QuadPart) { - return true; - } + char *res = cb_arena_push_many(char, MAX_ENVVAR); + if (!GetEnvironmentVariableA(varname, res, MAX_ENVVAR)) { + cb_arena_pop(sizeof(char) * MAX_ENVVAR); + res = 0; } - return false; + return res; #else - struct stat output_stat = {}; - if (stat(output_path, &output_stat) < 0) { return true; } - for (size_t i = 0; i < sources.count; ++i) { - struct stat source_stat = {}; - if (stat(sources.values[i], &source_stat) < 0) { - rebuild_failure: - cb_print(CB_LogLevel_Error, - "`%s` modification time unreadable: %s\n", - sources.values[i], strerror(errno)); - exit(-1); - } - if (output_stat.st_mtime < source_stat.st_mtime) { return true; } - } - return false; + return getenv(varname); #endif } -internal size_t _last_occurance_of(const char *string, char ch) { - const char *res = string; - for (const char *curr = string; curr && *curr; ++curr) { - if (*curr == ch) { res = curr; } - } - return (size_t)(res - string); +static b8 cb_setenv(const char *varname, const char *value) +{ + cb_assert(varname != NULL); + cb_assert(value != NULL); +#if OS_WINDOWS + return SetEnvironmentVariableA(varname, value); +#else + return !setenv(varname, value, true); +#endif } #endif diff --git a/extra/cbuild_codegen.h b/extra/cbuild_codegen.h index f7d3e73..c1fae9e 100644 --- a/extra/cbuild_codegen.h +++ b/extra/cbuild_codegen.h @@ -13,25 +13,23 @@ typedef struct { } signature; } CB_Generator; -static void cb_gen_write(CB_Generator *gen, char *filepath, bool append_mode); +static void cb_gen_write(CB_Generator *gen, CB_StringView path, b8 append_mode); static void cb_gen_push(CB_Generator *gen, char *string); static void cb_gen_push_func_begin(CB_Generator *gen, char *signature_no_args); static void cb_gen_push_func_arg(CB_Generator *gen, char *argument); -static void cb_gen_push_func_end(CB_Generator *gen, bool implementation); +static void cb_gen_push_func_end(CB_Generator *gen, b8 implementation); // ====================================================================== // Implementations -static void cb_gen_write(CB_Generator *gen, char *filepath, bool append_mode) { - CB_Handle file = cb_file_open(filepath, append_mode - ? CB_AccessFlag_Append - : CB_AccessFlag_Write); +static void cb_gen_write(CB_Generator *gen, CB_StringView path, b8 append_mode) { + CB_FileHandle file = cb_filesystem_open(path, append_mode ? CB_AccessFlag_Append : CB_AccessFlag_Write); char *full_string = malloc(gen->total_length + 1); memset(full_string, 0, gen->total_length + 1); for (size_t i = 0; i < gen->count; ++i) { strcat(full_string, gen->values[i]); } - cb_file_write(file, full_string); + cb_file_write_at_pointer(file, cb_view_from_cstr(full_string)); free(full_string); cb_file_close(file); cb_dyn_free(gen); @@ -72,7 +70,7 @@ static void cb_gen_push_func_arg(CB_Generator *gen, char *argument) { #define cb_gen_push_func_end(GeneratorPtr, Implementation) \ _cb_gen_push_func_end((GeneratorPtr), (Implementation), __FILE__, __LINE__) -static void _cb_gen_push_func_end(CB_Generator *gen, bool implementation, +static void _cb_gen_push_func_end(CB_Generator *gen, b8 implementation, const char *file, int32_t line) { if (!gen->signature.has_args) { cb_gen_push(gen, "void"); diff --git a/extra/cbuild_linagen.h b/extra/cbuild_linagen.h index cf6f1f0..e70b9d8 100644 --- a/extra/cbuild_linagen.h +++ b/extra/cbuild_linagen.h @@ -13,12 +13,12 @@ internal void cb_linagen_defun_vecn_element_wise(CB_Generator *gen, char *type, - int32_t n, bool implementation, + int32_t n, b8 implementation, char *func_name, char op); internal void cb_linagen_defun_matnn_element_wise(CB_Generator *gen, char *type, - int32_t n, bool implementation, + int32_t n, b8 implementation, char *func_name, char op); internal char char_toupper(char ch); @@ -31,74 +31,74 @@ static void cb_linagen_typedef_matnn(CB_Generator *gen, char *type, int32_t n); static inline void -cb_linagen_defun_vecn(CB_Generator *gen, char *type, int32_t n, bool implementation); +cb_linagen_defun_vecn(CB_Generator *gen, char *type, int32_t n, b8 implementation); static inline void -cb_linagen_defun_vecn_add(CB_Generator *gen, char *type, int32_t n, bool implementation); +cb_linagen_defun_vecn_add(CB_Generator *gen, char *type, int32_t n, b8 implementation); static inline void -cb_linagen_defun_vecn_sub(CB_Generator *gen, char *type, int32_t n, bool implementation); +cb_linagen_defun_vecn_sub(CB_Generator *gen, char *type, int32_t n, b8 implementation); static inline void -cb_linagen_defun_vecn_hadamard_prod(CB_Generator *gen, char *type, int32_t n, bool implementation); +cb_linagen_defun_vecn_hadamard_prod(CB_Generator *gen, char *type, int32_t n, b8 implementation); static inline void -cb_linagen_defun_vecn_hadamard_div(CB_Generator *gen, char *type, int32_t n, bool implementation); +cb_linagen_defun_vecn_hadamard_div(CB_Generator *gen, char *type, int32_t n, b8 implementation); static inline void -cb_linagen_defun_vecn_equal(CB_Generator *gen, char *type, int32_t n, bool implementation); +cb_linagen_defun_vecn_equal(CB_Generator *gen, char *type, int32_t n, b8 implementation); static inline void -cb_linagen_defun_vecn_near(CB_Generator *gen, char *type, int32_t n, bool implementation); +cb_linagen_defun_vecn_near(CB_Generator *gen, char *type, int32_t n, b8 implementation); static inline void -cb_linagen_defun_vecn_lerp(CB_Generator *gen, char *type, int32_t n, bool implementation); +cb_linagen_defun_vecn_lerp(CB_Generator *gen, char *type, int32_t n, b8 implementation); static void -cb_linagen_defun_vecn_scale(CB_Generator *gen, char *type, int32_t n, bool implementation); +cb_linagen_defun_vecn_scale(CB_Generator *gen, char *type, int32_t n, b8 implementation); static void -cb_linagen_defun_vecn_normalize(CB_Generator *gen, char *type, int32_t n, bool implementation); +cb_linagen_defun_vecn_normalize(CB_Generator *gen, char *type, int32_t n, b8 implementation); static void -cb_linagen_defun_vecn_dot(CB_Generator *gen, char *type, int32_t n, bool implementation); +cb_linagen_defun_vecn_dot(CB_Generator *gen, char *type, int32_t n, b8 implementation); static void -cb_linagen_defun_vecn_mulm(CB_Generator *gen, char *type, int32_t n, bool implementation); +cb_linagen_defun_vecn_mulm(CB_Generator *gen, char *type, int32_t n, b8 implementation); static void -cb_linagen_defun_vecn_magnitude(CB_Generator *gen, char *type, int32_t n, bool implementation); +cb_linagen_defun_vecn_magnitude(CB_Generator *gen, char *type, int32_t n, b8 implementation); static void -cb_linagen_defun_vecn_magnitude64(CB_Generator *gen, char *type, int32_t n, bool implementation); +cb_linagen_defun_vecn_magnitude64(CB_Generator *gen, char *type, int32_t n, b8 implementation); static void -cb_linagen_defun_vecn_distance(CB_Generator *gen, char *type, int32_t n, bool implementation); +cb_linagen_defun_vecn_distance(CB_Generator *gen, char *type, int32_t n, b8 implementation); static void -cb_linagen_defun_vecn_distance2(CB_Generator *gen, char *type, int32_t n, bool implementation); +cb_linagen_defun_vecn_distance2(CB_Generator *gen, char *type, int32_t n, b8 implementation); static inline void -cb_linagen_defun_vec3_cross(CB_Generator *gen, char *type, bool implementation); +cb_linagen_defun_vec3_cross(CB_Generator *gen, char *type, b8 implementation); static void -cb_linagen_defun_matnn_scale(CB_Generator *gen, char *type, int32_t n, bool implementation); +cb_linagen_defun_matnn_scale(CB_Generator *gen, char *type, int32_t n, b8 implementation); static inline void -cb_linagen_defun_matnn_add(CB_Generator *gen, char *type, int32_t n, bool implementation); +cb_linagen_defun_matnn_add(CB_Generator *gen, char *type, int32_t n, b8 implementation); static inline void -cb_linagen_defun_matnn_sub(CB_Generator *gen, char *type, int32_t n, bool implementation); +cb_linagen_defun_matnn_sub(CB_Generator *gen, char *type, int32_t n, b8 implementation); static inline void -cb_linagen_defun_matnn_hadamard_prod(CB_Generator *gen, char *type, int32_t n, bool implementation); +cb_linagen_defun_matnn_hadamard_prod(CB_Generator *gen, char *type, int32_t n, b8 implementation); static inline void -cb_linagen_defun_matnn_hadamard_div(CB_Generator *gen, char *type, int32_t n, bool implementation); +cb_linagen_defun_matnn_hadamard_div(CB_Generator *gen, char *type, int32_t n, b8 implementation); static void -cb_linagen_defun_matnn_dot(CB_Generator *gen, char *type, int32_t n, bool implementation); +cb_linagen_defun_matnn_dot(CB_Generator *gen, char *type, int32_t n, b8 implementation); static void -cb_linagen_defun_matnn_mulv(CB_Generator *gen, char *type, int32_t n, bool implementation); +cb_linagen_defun_matnn_mulv(CB_Generator *gen, char *type, int32_t n, b8 implementation); static void -cb_linagen_defun_matnn_identity(CB_Generator *gen, char *type, int32_t n, bool implementation); +cb_linagen_defun_matnn_identity(CB_Generator *gen, char *type, int32_t n, b8 implementation); static void -cb_linagen_defun_mat4_transform_translate_by(CB_Generator *gen, char *type, bool implementation); +cb_linagen_defun_mat4_transform_translate_by(CB_Generator *gen, char *type, b8 implementation); static void -cb_linagen_defun_mat4_transform_translate_to(CB_Generator *gen, char *type, bool implementation); +cb_linagen_defun_mat4_transform_translate_to(CB_Generator *gen, char *type, b8 implementation); static void -cb_linagen_defun_mat4_transform_rotate(CB_Generator *gen, char *type, bool implementation); +cb_linagen_defun_mat4_transform_rotate(CB_Generator *gen, char *type, b8 implementation); static void -cb_linagen_defun_mat4_transform_rotate_rad(CB_Generator *gen, char *type, bool implementation); +cb_linagen_defun_mat4_transform_rotate_rad(CB_Generator *gen, char *type, b8 implementation); static void -cb_linagen_defun_mat4_transform_scale(CB_Generator *gen, char *type, bool implementation); +cb_linagen_defun_mat4_transform_scale(CB_Generator *gen, char *type, b8 implementation); static void -cb_linagen_defun_mat4_projection_orthographic(CB_Generator *gen, char *type, bool implementation); +cb_linagen_defun_mat4_projection_orthographic(CB_Generator *gen, char *type, b8 implementation); static void -cb_linagen_defun_mat4_projection_perspective(CB_Generator *gen, char *type, bool implementation); +cb_linagen_defun_mat4_projection_perspective(CB_Generator *gen, char *type, b8 implementation); static void -cb_linagen_defun_mat4_projection_perspective_rad(CB_Generator *gen, char *type, bool implementation); +cb_linagen_defun_mat4_projection_perspective_rad(CB_Generator *gen, char *type, b8 implementation); // ====================================================================== // Implementations @@ -111,7 +111,7 @@ cb_linagen_typedef_vecn(CB_Generator *gen, char *type, int32_t n, ...) { cb_gen_push(gen, cb_format("typedef union {" "\n %s values[%d];" "\n struct {", type, n)); - bool found_last_named_field = false; + b8 found_last_named_field = false; for (int32_t i = 0; i < n; ++i) { char *prefix = " "; if (i % 4 == 0) { @@ -162,7 +162,7 @@ cb_linagen_typedef_matnn(CB_Generator *gen, char *type, int32_t n) { } static inline void -cb_linagen_defun_vecn(CB_Generator *gen, char *type, int32_t n, bool implementation) { +cb_linagen_defun_vecn(CB_Generator *gen, char *type, int32_t n, b8 implementation) { char *suffix = strdup(type); *suffix = char_toupper(*type); cb_gen_push_func_begin(gen, cb_format("linagen_fn Vec%d%s vec%d%s", @@ -182,33 +182,33 @@ cb_linagen_defun_vecn(CB_Generator *gen, char *type, int32_t n, bool implementat } static inline void -cb_linagen_defun_vecn_add(CB_Generator *gen, char *type, int32_t n, bool implementation) { +cb_linagen_defun_vecn_add(CB_Generator *gen, char *type, int32_t n, b8 implementation) { cb_linagen_defun_vecn_element_wise(gen, type, n, implementation, "add", '+'); } static inline void -cb_linagen_defun_vecn_sub(CB_Generator *gen, char *type, int32_t n, bool implementation) { +cb_linagen_defun_vecn_sub(CB_Generator *gen, char *type, int32_t n, b8 implementation) { cb_linagen_defun_vecn_element_wise(gen, type, n, implementation, "sub", '-'); } static inline void -cb_linagen_defun_vecn_hadamard_prod(CB_Generator *gen, char *type, int32_t n, bool implementation) { +cb_linagen_defun_vecn_hadamard_prod(CB_Generator *gen, char *type, int32_t n, b8 implementation) { cb_linagen_defun_vecn_element_wise(gen, type, n, implementation, "hadamard_prod", '*'); } static inline void -cb_linagen_defun_vecn_hadamard_div(CB_Generator *gen, char *type, int32_t n, bool implementation) { +cb_linagen_defun_vecn_hadamard_div(CB_Generator *gen, char *type, int32_t n, b8 implementation) { cb_linagen_defun_vecn_element_wise(gen, type, n, implementation, "hadamard_div", '/'); } static inline void -cb_linagen_defun_vecn_equal(CB_Generator *gen, char *type, int32_t n, bool implementation) { +cb_linagen_defun_vecn_equal(CB_Generator *gen, char *type, int32_t n, b8 implementation) { assert(n > 1); char *suffix = strdup(type); *suffix = char_toupper(*type); - cb_gen_push_func_begin(gen, cb_format("linagen_fn bool vec%d%s_equal", n, type)); + cb_gen_push_func_begin(gen, cb_format("linagen_fn b8 vec%d%s_equal", n, type)); cb_gen_push_func_arg(gen, cb_format("Vec%d%s *v1", n, suffix)); cb_gen_push_func_arg(gen, cb_format("Vec%d%s *v2", n, suffix)); cb_gen_push_func_end(gen, implementation); @@ -223,11 +223,11 @@ cb_linagen_defun_vecn_equal(CB_Generator *gen, char *type, int32_t n, bool imple } static inline void -cb_linagen_defun_vecn_near(CB_Generator *gen, char *type, int32_t n, bool implementation) { +cb_linagen_defun_vecn_near(CB_Generator *gen, char *type, int32_t n, b8 implementation) { assert(n > 1); char *suffix = strdup(type); *suffix = char_toupper(*type); - cb_gen_push_func_begin(gen, cb_format("linagen_fn bool vec%d%s_near", + cb_gen_push_func_begin(gen, cb_format("linagen_fn b8 vec%d%s_near", n, type)); cb_gen_push_func_arg(gen, cb_format("Vec%d%s *v1", n, suffix)); cb_gen_push_func_arg(gen, cb_format("Vec%d%s *v2", n, suffix)); @@ -244,7 +244,7 @@ cb_linagen_defun_vecn_near(CB_Generator *gen, char *type, int32_t n, bool implem } static inline void -cb_linagen_defun_vecn_lerp(CB_Generator *gen, char *type, int32_t n, bool implementation) { +cb_linagen_defun_vecn_lerp(CB_Generator *gen, char *type, int32_t n, b8 implementation) { assert(n > 1); char *suffix = strdup(type); *suffix = char_toupper(*type); @@ -278,7 +278,7 @@ cb_linagen_defun_vecn_lerp(CB_Generator *gen, char *type, int32_t n, bool implem } static void -cb_linagen_defun_vecn_scale(CB_Generator *gen, char *type, int32_t n, bool implementation) { +cb_linagen_defun_vecn_scale(CB_Generator *gen, char *type, int32_t n, b8 implementation) { assert(n > 1); char *suffix = strdup(type); *suffix = char_toupper(*type); @@ -310,7 +310,7 @@ cb_linagen_defun_vecn_scale(CB_Generator *gen, char *type, int32_t n, bool imple } static void -cb_linagen_defun_vecn_normalize(CB_Generator *gen, char *type, int32_t n, bool implementation) { +cb_linagen_defun_vecn_normalize(CB_Generator *gen, char *type, int32_t n, b8 implementation) { assert(n > 1); char *suffix = strdup(type); *suffix = char_toupper(*type); @@ -351,7 +351,7 @@ cb_linagen_defun_vecn_normalize(CB_Generator *gen, char *type, int32_t n, bool i } static void -cb_linagen_defun_vecn_dot(CB_Generator *gen, char *type, int32_t n, bool implementation) { +cb_linagen_defun_vecn_dot(CB_Generator *gen, char *type, int32_t n, b8 implementation) { assert(n > 1); char *suffix = strdup(type); *suffix = char_toupper(*type); @@ -370,7 +370,7 @@ cb_linagen_defun_vecn_dot(CB_Generator *gen, char *type, int32_t n, bool impleme } static void -cb_linagen_defun_vecn_mulm(CB_Generator *gen, char *type, int32_t n, bool implementation) { +cb_linagen_defun_vecn_mulm(CB_Generator *gen, char *type, int32_t n, b8 implementation) { assert(n > 1); char *suffix = strdup(type); *suffix = char_toupper(*type); @@ -417,7 +417,7 @@ cb_linagen_defun_vecn_mulm(CB_Generator *gen, char *type, int32_t n, bool implem } static void -cb_linagen_defun_vecn_magnitude(CB_Generator *gen, char *type, int32_t n, bool implementation) { +cb_linagen_defun_vecn_magnitude(CB_Generator *gen, char *type, int32_t n, b8 implementation) { assert(n > 1); char *suffix = strdup(type); *suffix = char_toupper(*type); @@ -437,7 +437,7 @@ cb_linagen_defun_vecn_magnitude(CB_Generator *gen, char *type, int32_t n, bool i } static void -cb_linagen_defun_vecn_magnitude64(CB_Generator *gen, char *type, int32_t n, bool implementation) { +cb_linagen_defun_vecn_magnitude64(CB_Generator *gen, char *type, int32_t n, b8 implementation) { assert(n > 1); char *suffix = strdup(type); *suffix = char_toupper(*type); @@ -457,7 +457,7 @@ cb_linagen_defun_vecn_magnitude64(CB_Generator *gen, char *type, int32_t n, bool } static void -cb_linagen_defun_vecn_distance(CB_Generator *gen, char *type, int32_t n, bool implementation) { +cb_linagen_defun_vecn_distance(CB_Generator *gen, char *type, int32_t n, b8 implementation) { assert(n > 1); char *suffix = strdup(type); *suffix = char_toupper(*type); @@ -483,7 +483,7 @@ cb_linagen_defun_vecn_distance(CB_Generator *gen, char *type, int32_t n, bool im } static void -cb_linagen_defun_vecn_distance2(CB_Generator *gen, char *type, int32_t n, bool implementation) { +cb_linagen_defun_vecn_distance2(CB_Generator *gen, char *type, int32_t n, b8 implementation) { char *suffix = strdup(type); *suffix = char_toupper(*type); cb_gen_push_func_begin(gen, cb_format("linagen_fn float vec%d%s_distance2", @@ -507,7 +507,7 @@ cb_linagen_defun_vecn_distance2(CB_Generator *gen, char *type, int32_t n, bool i } static inline void -cb_linagen_defun_vec3_cross(CB_Generator *gen, char *type, bool implementation) { +cb_linagen_defun_vec3_cross(CB_Generator *gen, char *type, b8 implementation) { char *suffix = strdup(type); *suffix = char_toupper(*type); cb_gen_push_func_begin(gen, cb_format("linagen_fn Vec3%s vec3%s_cross", suffix, type)); @@ -525,7 +525,7 @@ cb_linagen_defun_vec3_cross(CB_Generator *gen, char *type, bool implementation) } static void -cb_linagen_defun_matnn_scale(CB_Generator *gen, char *type, int32_t n, bool implementation) { +cb_linagen_defun_matnn_scale(CB_Generator *gen, char *type, int32_t n, b8 implementation) { assert(n > 1); char *suffix = strdup(type); *suffix = char_toupper(*type); @@ -563,29 +563,29 @@ cb_linagen_defun_matnn_scale(CB_Generator *gen, char *type, int32_t n, bool impl } static inline void -cb_linagen_defun_matnn_add(CB_Generator *gen, char *type, int32_t n, bool implementation) { +cb_linagen_defun_matnn_add(CB_Generator *gen, char *type, int32_t n, b8 implementation) { cb_linagen_defun_matnn_element_wise(gen, type, n, implementation, "add", '+'); } static inline void -cb_linagen_defun_matnn_sub(CB_Generator *gen, char *type, int32_t n, bool implementation) { +cb_linagen_defun_matnn_sub(CB_Generator *gen, char *type, int32_t n, b8 implementation) { cb_linagen_defun_matnn_element_wise(gen, type, n, implementation, "sub", '-'); } static inline void -cb_linagen_defun_matnn_hadamard_prod(CB_Generator *gen, char *type, int32_t n, bool implementation) { +cb_linagen_defun_matnn_hadamard_prod(CB_Generator *gen, char *type, int32_t n, b8 implementation) { cb_linagen_defun_matnn_element_wise(gen, type, n, implementation, "hadamard_prod", '*'); } static inline void -cb_linagen_defun_matnn_hadamard_div(CB_Generator *gen, char *type, int32_t n, bool implementation) { +cb_linagen_defun_matnn_hadamard_div(CB_Generator *gen, char *type, int32_t n, b8 implementation) { cb_linagen_defun_matnn_element_wise(gen, type, n, implementation, "hadamard_div", '/'); } static void -cb_linagen_defun_matnn_dot(CB_Generator *gen, char *type, int32_t n, bool implementation) { +cb_linagen_defun_matnn_dot(CB_Generator *gen, char *type, int32_t n, b8 implementation) { assert(n > 1); char *suffix = strdup(type); *suffix = char_toupper(*type); @@ -637,7 +637,7 @@ cb_linagen_defun_matnn_dot(CB_Generator *gen, char *type, int32_t n, bool implem } static void -cb_linagen_defun_matnn_mulv(CB_Generator *gen, char *type, int32_t n, bool implementation) { +cb_linagen_defun_matnn_mulv(CB_Generator *gen, char *type, int32_t n, b8 implementation) { assert(n > 1); char *suffix = strdup(type); *suffix = char_toupper(*type); @@ -685,7 +685,7 @@ cb_linagen_defun_matnn_mulv(CB_Generator *gen, char *type, int32_t n, bool imple } static void -cb_linagen_defun_matnn_identity(CB_Generator *gen, char *type, int32_t n, bool implementation) { +cb_linagen_defun_matnn_identity(CB_Generator *gen, char *type, int32_t n, b8 implementation) { assert(n > 1); char *suffix = strdup(type); *suffix = char_toupper(*type); @@ -715,7 +715,7 @@ cb_linagen_defun_matnn_identity(CB_Generator *gen, char *type, int32_t n, bool i } static void -cb_linagen_defun_mat4_transform_translate_by(CB_Generator *gen, char *type, bool implementation) { +cb_linagen_defun_mat4_transform_translate_by(CB_Generator *gen, char *type, b8 implementation) { char *suffix = strdup(type); *suffix = char_toupper(*type); cb_gen_push_func_begin(gen, cb_format("linagen_fn Mat4%s mat4%s_transform_translate_by", suffix, type)); @@ -733,7 +733,7 @@ cb_linagen_defun_mat4_transform_translate_by(CB_Generator *gen, char *type, bool } static void -cb_linagen_defun_mat4_transform_translate_to(CB_Generator *gen, char *type, bool implementation) { +cb_linagen_defun_mat4_transform_translate_to(CB_Generator *gen, char *type, b8 implementation) { char *suffix = strdup(type); *suffix = char_toupper(*type); cb_gen_push_func_begin(gen, cb_format("linagen_fn Mat4%s mat4%s_transform_translate_to", suffix, type)); @@ -751,7 +751,7 @@ cb_linagen_defun_mat4_transform_translate_to(CB_Generator *gen, char *type, bool } static void -cb_linagen_defun_mat4_transform_rotate(CB_Generator *gen, char *type, bool implementation) { +cb_linagen_defun_mat4_transform_rotate(CB_Generator *gen, char *type, b8 implementation) { char *suffix = strdup(type); *suffix = char_toupper(*type); cb_gen_push_func_begin(gen, cb_format("linagen_fn Mat4%s mat4%s_transform_rotate", suffix, type)); @@ -787,7 +787,7 @@ cb_linagen_defun_mat4_transform_rotate(CB_Generator *gen, char *type, bool imple } static void -cb_linagen_defun_mat4_transform_rotate_rad(CB_Generator *gen, char *type, bool implementation) { +cb_linagen_defun_mat4_transform_rotate_rad(CB_Generator *gen, char *type, b8 implementation) { char *suffix = strdup(type); *suffix = char_toupper(*type); cb_gen_push_func_begin(gen, cb_format("linagen_fn Mat4%s mat4%s_transform_rotate_rad", suffix, type)); @@ -821,7 +821,7 @@ cb_linagen_defun_mat4_transform_rotate_rad(CB_Generator *gen, char *type, bool i } static void -cb_linagen_defun_mat4_transform_scale(CB_Generator *gen, char *type, bool implementation) { +cb_linagen_defun_mat4_transform_scale(CB_Generator *gen, char *type, b8 implementation) { char *suffix = strdup(type); *suffix = char_toupper(*type); cb_gen_push_func_begin(gen, cb_format("linagen_fn Mat4%s mat4%s_transform_scale", suffix, type)); @@ -854,7 +854,7 @@ cb_linagen_defun_mat4_transform_scale(CB_Generator *gen, char *type, bool implem } static void -cb_linagen_defun_mat4_projection_orthographic(CB_Generator *gen, char *type, bool implementation) { +cb_linagen_defun_mat4_projection_orthographic(CB_Generator *gen, char *type, b8 implementation) { char *suffix = strdup(type); *suffix = char_toupper(*type); cb_gen_push_func_begin(gen, cb_format("linagen_fn Mat4%s mat4%s_projection_orthographic", suffix, type)); @@ -877,7 +877,7 @@ cb_linagen_defun_mat4_projection_orthographic(CB_Generator *gen, char *type, boo } static void -cb_linagen_defun_mat4_projection_perspective(CB_Generator *gen, char *type, bool implementation) { +cb_linagen_defun_mat4_projection_perspective(CB_Generator *gen, char *type, b8 implementation) { char *suffix = strdup(type); *suffix = char_toupper(*type); cb_gen_push_func_begin(gen, cb_format("linagen_fn Mat4%s mat4%s_projection_perspective", suffix, type)); @@ -900,7 +900,7 @@ cb_linagen_defun_mat4_projection_perspective(CB_Generator *gen, char *type, bool } static void -cb_linagen_defun_mat4_projection_perspective_rad(CB_Generator *gen, char *type, bool implementation) { +cb_linagen_defun_mat4_projection_perspective_rad(CB_Generator *gen, char *type, b8 implementation) { char *suffix = strdup(type); *suffix = char_toupper(*type); cb_gen_push_func_begin(gen, cb_format("linagen_fn Mat4%s mat4%s_projection_perspective_rad", suffix, type)); @@ -924,7 +924,7 @@ cb_linagen_defun_mat4_projection_perspective_rad(CB_Generator *gen, char *type, internal void cb_linagen_defun_vecn_element_wise(CB_Generator *gen, char *type, - int32_t n, bool implementation, + int32_t n, b8 implementation, char *func_name, char op) { assert(n > 1); char *suffix = strdup(type); @@ -962,7 +962,7 @@ cb_linagen_defun_vecn_element_wise(CB_Generator *gen, char *type, internal void cb_linagen_defun_matnn_element_wise(CB_Generator *gen, char *type, - int32_t n, bool implementation, + int32_t n, b8 implementation, char *func_name, char op) { assert(n > 1); char *suffix = strdup(type); diff --git a/extra/cbuild_tests.h b/extra/cbuild_tests.h index f79e0e7..3213174 100644 --- a/extra/cbuild_tests.h +++ b/extra/cbuild_tests.h @@ -40,9 +40,7 @@ typedef void cb_w32_test_func_init(void); static void cb_test_run(void); internal void cb_test_register(struct CB_Test test); -internal void cb_assertion_test(char *condition, - char *file, - int32_t line); +internal void cb_assertion_test(char *condition, char *file, int32_t line); // ====================================================================== -- 2.52.0